Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5oappy/feature/create v2 testing #191

Merged
merged 7 commits into from
Mar 24, 2024
14 changes: 5 additions & 9 deletions controllers/v2/unavailability/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,11 @@ def post(self, user_id):
if args['start'] >= args['end']:
return {"message": "Start time must be earlier than end time"}, 400 # HTTP 400 Bad Request

overlapping_events = self.event_repository.check_overlapping_events(user_id, args['start'], args['end'], args['periodicity'])
overlapping_events = self.event_repository.check_overlapping_events(user_id, args['start'], args['end'],
args['periodicity'])
if overlapping_events:
overlapping_details = []
for event in overlapping_events:
overlapping_details.append({
"eventId": event.eventId})
return {"message": "Time frames overlap with existing events",
"overlapping_events": overlapping_details}, 400 # HTTP 400 Bad Request
"overlapping events": overlapping_events}, 400

eventId = self.event_repository.create_event(
user_id,
Expand All @@ -94,9 +91,8 @@ def post(self, user_id):
return {"description": "Internal server error", "error": str(e)}, 500 # HTTP 500 Internal Server Error



v2_api.add_resource(SpecificVolunteerUnavailabilityV2, '/v2/volunteers/',
'/v2/volunteers/<user_id>/unavailability/<event_id>')
'/v2/volunteers/<user_id>/unavailability/<event_id>')

v2_api.add_resource(VolunteerUnavailabilityV2, '/v2/volunteers/',
'/v2/volunteers/<user_id>/unavailability')
'/v2/volunteers/<user_id>/unavailability')
21 changes: 16 additions & 5 deletions domain/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,22 @@

# Configure Session
Session = sessionmaker()
Engine = create_engine('mysql+mysqldb://{0}:{1}@{2}:{3}/{4}'.format(os.environ.get('username'),
os.environ.get('password'),
os.environ.get('host'),
os.environ.get('port'),
os.environ.get('dbname')), echo=False)
if os.environ.get("SQLALCHEMY_DATABASE_URI"):
Engine = create_engine(os.environ.get("SQLALCHEMY_DATABASE_URI"))


def enable_fk_listener(dbapi_connection, connection_record): # enabling foreign key constraint in the test database
dbapi_connection.execute('pragma foreign_keys=ON')


event.listen(Engine, 'connect', enable_fk_listener)

else:
Engine = create_engine('mysql+mysqldb://{0}:{1}@{2}:{3}/{4}'.format(os.environ.get('username'),
os.environ.get('password'),
os.environ.get('host'),
os.environ.get('port'),
os.environ.get('dbname')), echo=False)
Session.configure(bind=Engine)

# Configure Declarative Base for ORM
Expand Down
2 changes: 1 addition & 1 deletion domain/entity/diet_requirement.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
class DietRequirement(Base):
__tablename__ = 'diet_requirement'
diet_id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey('user.id'), primary_key=True, nullable=False)
user_id = Column(Integer, ForeignKey('user.id'), nullable=False)
halal = Column(Boolean, nullable=False, default=0)
vegetarian = Column(Boolean, nullable=False, default=0)
vegan = Column(Boolean, nullable=False, default=0)
Expand Down
3 changes: 1 addition & 2 deletions domain/entity/question.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from datetime import datetime
from sqlalchemy import Column, Integer, String, DateTime, Boolean, Enum, Text
from sqlalchemy.dialects.mysql import TINYINT
from domain.base import Base
from domain.type import QuestionType

Expand All @@ -14,7 +13,7 @@ class Question(Base):
role = Column(String(256), nullable=True)
description = Column(String(1024), nullable=False)
choice = Column(Text, nullable=False)
difficulty = Column(TINYINT, default=1, nullable=False)
difficulty = Column(Integer, default=1, nullable=False)
answer = Column(String(20), nullable=False)
status = Column(Boolean, default=True, nullable=False)
answered_time = Column(Integer, default=0, nullable=False)
Expand Down
2 changes: 1 addition & 1 deletion domain/entity/unavailability_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class UnavailabilityTime(Base):
__tablename__ = 'unavailability_time'
eventId = Column(Integer, primary_key=True, autoincrement=True)
userId = Column(Integer, ForeignKey('user.id'), primary_key=True, nullable=False)
userId = Column(Integer, ForeignKey('user.id'), nullable=False)
title = Column(String(256), nullable=True, default=None)
periodicity = Column(Integer, nullable=False, default=1)
start = Column(DateTime, nullable=False, default=datetime.now())
Expand Down
22 changes: 17 additions & 5 deletions repository/volunteer_unavailability_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
class EventRepository:
def __init__(self):
pass

def edit_event(self, userId, eventId, title=None, start=None, end=None, periodicity=None):
with session_scope() as session:
try:
event = session.query(UnavailabilityTime).filter(UnavailabilityTime.eventId == eventId,
UnavailabilityTime.userId == userId).first()
UnavailabilityTime.userId == userId).first()
if event is None:
return False
if title is not None:
Expand Down Expand Up @@ -43,7 +44,8 @@ def get_event(self, userId):
try:
# only show the unavailability time that is end in the future
events = session.query(UnavailabilityTime).filter(
UnavailabilityTime.userId == userId, UnavailabilityTime.status == 1, UnavailabilityTime.end > now).all()
UnavailabilityTime.userId == userId, UnavailabilityTime.status == 1,
UnavailabilityTime.end > now).all()
if events:
event_records = []
for event in events:
Expand Down Expand Up @@ -77,7 +79,7 @@ def create_event(self, userId, title, startTime, endTime, periodicity):
:param periodicity: Integer, Daily = 1, Weekly = 2, One-Off = 3
"""
event = UnavailabilityTime(userId=userId, title=title, start=startTime, end=endTime,
periodicity=periodicity)
periodicity=periodicity)
with session_scope() as session:
session.add(event)
# session.expunge(question)
Expand All @@ -102,7 +104,7 @@ def remove_event(self, userId, eventId):
return True
return False

# copy from post function in api.py written by Steven
# checks via base value comparison, returns the event Ids of overlapped events
def check_overlapping_events(self, userId, startTime, endTime, periodicity):
with session_scope() as session:
# checks if new time frame overlaps with any existing in the database for specific userId
Expand All @@ -112,4 +114,14 @@ def check_overlapping_events(self, userId, startTime, endTime, periodicity):
UnavailabilityTime.end > startTime,
UnavailabilityTime.periodicity == periodicity
).all()
return overlapping_events
# Convert overlapping events to a list of dictionaries
overlapping_details = []
for event in overlapping_events:
overlapping_details.append({
"eventId": event.eventId,
# Add any other attributes you need
})
return overlapping_details



2 changes: 1 addition & 1 deletion services/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def register(session: Session, email: str, password: str, given_name: str, last_
# Everything seems fine, so we go ahead and create the user & the linked account.
password_hash = passwordService.hash(password)
new_user = User(role=UserType.VOLUNTEER, password=password_hash, first_name=given_name, last_name=last_name,
mobile_number=phone, email=email, preferred_hours={}, experience_years=0, possibleRoles=["Basic"],
mobile_number=phone, email=email, preferred_hours=None, experience_years=0, possibleRoles=["Basic"],
qualifications=[],
availabilities={"Friday": [], "Monday": [], "Sunday": [], "Tuesday": [], "Saturday": [],
"Thursday": [], "Wednesday": []},
Expand Down
68 changes: 55 additions & 13 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,76 @@
import os

os.environ.setdefault('username', 'user')
os.environ.setdefault('password', 'password')
os.environ.setdefault('host', '127.0.0.1')
os.environ.setdefault('port', '3306')
os.environ.setdefault('dbname', 'db')
os.environ.setdefault("SQLALCHEMY_DATABASE_URI", 'sqlite:///:memory:')
import pytest
from application import app
from domain.base import Engine, Base, Session
from domain.entity.user import User
from domain.type.user_type import UserType
from datetime import datetime


@pytest.fixture(scope='session', autouse=True)
def create_test_database():
Base.metadata.drop_all(bind=Engine)
Base.metadata.create_all(bind=Engine)
yield
Base.metadata.drop_all(bind=Engine)


@pytest.fixture(autouse=True)
def transactional_test(create_test_database, request):
connection = Engine.connect()
transaction = connection.begin()

try:
nested = connection.begin_nested()

Session.configure(bind=connection)
yield

finally:
nested.rollback()
transaction.rollback()
connection.close()


@pytest.fixture(scope='module')
def test_client():
# Set the Testing configuration prior to creating the Flask application

with app.test_client() as testing_client:
# Establish an application context
with app.app_context():
yield testing_client


@pytest.fixture(scope='module')
def create_user():
session = Session()
test_user = User(
role=UserType.ROOT_ADMIN,
first_name="admin",
last_name="admin",
mobile_number="1234567890",
email="admin",
update_date_time=datetime.utcnow(),
insert_date_time=datetime.utcnow(),
password="$2a$12$BEOqNVY7cHlMztWNra87nuHAHqvex/ZgFfPmq5ZNNi4DxFHyflHau"
)
session.add(test_user)
session.commit()
user_id = test_user.id
yield user_id
session.delete(test_user)
session.commit()
session.close()


@pytest.fixture(scope='module')
def auth_token(test_client):
# Login with predefined admin credentials
login_payload = { # admin account details
'email': 'admin',
'password': 'admin'
login_payload = {
"email": "admin",
"password": "admin"
}
response = test_client.post('/authentication/login', json=login_payload)
assert response.status_code == 200, "Failed to log in with the given credential"
print(response.json)
token = response.json['access_token']
return token

Expand Down
28 changes: 15 additions & 13 deletions tests/functional/test_unavailability.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
def test_create_unavailability_consecutive_event_id(test_client):
user_id = 49 # admin id
def test_create_unavailability_consecutive_event_id(test_client, create_user):
user_id = create_user
payload_1 = {
"title": "All Day Event",
"periodicity": 0,
Expand All @@ -23,8 +23,8 @@ def test_create_unavailability_consecutive_event_id(test_client):
assert response_2.json["eventId"] - response.json["eventId"] == 1


def test_create_unavailability_same_time_interval(test_client):
user_id = 49
def test_create_unavailability_same_time_interval(test_client, create_user):
user_id = create_user
payload = {
"title": "All Day Event",
"periodicity": 0,
Expand All @@ -37,6 +37,8 @@ def test_create_unavailability_same_time_interval(test_client):
response_2 = test_client.post(f"/v2/volunteers/{user_id}/unavailability",
json=payload
)
print(response.json)

assert response.status_code == 200
assert response_2.status_code == 400

Expand All @@ -52,11 +54,11 @@ def test_create_unavailability_nonexistent_user_id(test_client):
response = test_client.post(f"/v2/volunteers/{user_id}/unavailability",
json=payload
)
response.status_code = 404
assert response.status_code == 404


def test_create_unavailability_end_before_start(test_client):
user_id = 49
def test_create_unavailability_end_before_start(test_client, create_user):
user_id = create_user
payload = {
"title": "All Day Event",
"periodicity": 0,
Expand All @@ -69,8 +71,8 @@ def test_create_unavailability_end_before_start(test_client):
assert response.status_code == 400


def test_create_unavailability_overlapped_time(test_client):
user_id = 49
def test_create_unavailability_overlapped_time(test_client, create_user):
user_id = create_user
payload_1 = {
"title": "All Day Event",
"periodicity": 0,
Expand All @@ -93,8 +95,8 @@ def test_create_unavailability_overlapped_time(test_client):
assert response_2.status_code == 400


def test_merge_overlapping_unavailability_intervals(test_client):
user_id = 49
def test_merge_overlapping_unavailability_intervals(test_client, create_user):
user_id = create_user
payload_1 = {
"title": "Morning Event",
"periodicity": 0,
Expand All @@ -115,8 +117,8 @@ def test_merge_overlapping_unavailability_intervals(test_client):
assert response.json["mergedIntervals"][0]["end"] == "2024-03-05T15:00:00Z"


def test_merge_adjacent_unavailability_intervals(test_client):
user_id = 49
def test_merge_adjacent_unavailability_intervals(test_client, create_user):
user_id = create_user
payload_1 = {
"title": "Morning Shift",
"periodicity": 0,
Expand Down
Loading