diff --git a/backend/app/coordinator/routes/examination_schedule.py b/backend/app/coordinator/routes/examination_schedule.py index fafbb4b..67b89e9 100644 --- a/backend/app/coordinator/routes/examination_schedule.py +++ b/backend/app/coordinator/routes/examination_schedule.py @@ -29,7 +29,7 @@ def list_examination_schedule(year_group_id: int, query: dict) -> dict: @bp.post('//') @bp.input(ExaminationScheduleSchema) -@bp.output(MessageSchema) +@bp.output(MessageSchema, status_code=201) def create_examination_schedule(year_group_id: int, data: dict) -> dict: yg = YearGroup.query.filter(YearGroup.id == year_group_id).first() if yg is None: @@ -56,7 +56,7 @@ def create_examination_schedule(year_group_id: int, data: dict) -> dict: @bp.put('//') @bp.input(ExaminationScheduleSchema) @bp.output(MessageSchema) -def update_title_examination_schedule(id: int, data: dict) -> dict: +def update_examination_schedule(id: int, data: dict) -> dict: examination_schedule_query = db.session.query(ExaminationSchedule).filter(ExaminationSchedule.id == id) examination_schedule = examination_schedule_query.first() @@ -78,7 +78,7 @@ def delete_examination_schedule(id: int) -> dict: return {"message": "Examination schedule was deleted!"} -@bp.put('//date') +@bp.put('//date/') @bp.input(ExaminationScheduleUpdateSchema) @bp.output(MessageSchema) def set_date_of_examination_schedule(id: int, data: dict) -> dict: diff --git a/backend/tests/factory.py b/backend/tests/factory.py index e1bd2be..1df0a8f 100644 --- a/backend/tests/factory.py +++ b/backend/tests/factory.py @@ -1,10 +1,13 @@ +import datetime + from factory import alchemy, Sequence from factory.faker import Faker -from factory.fuzzy import FuzzyInteger +from factory.fuzzy import FuzzyInteger, FuzzyDateTime from app.dependencies import db from app.students.models import Student, Group, YearGroupStudents from app.project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors +from app.examination_schedule.models import ExaminationSchedule class ProjectSupervisorFactory(alchemy.SQLAlchemyModelFactory): @@ -50,3 +53,16 @@ class YearGroupStudentsFactory(alchemy.SQLAlchemyModelFactory): class Meta: model = YearGroupStudents sqlalchemy_session = db.session + + +class ExaminationScheduleFactory(alchemy.SQLAlchemyModelFactory): + class Meta: + model = ExaminationSchedule + sqlalchemy_session = db.session + + title = Sequence(lambda n: f'Examination schedule {n}') + duration_time = 30 + start_date = FuzzyDateTime(datetime.datetime(2020, 1, 1, tzinfo=datetime.timezone.utc), + datetime.datetime(2020, 1, 5, tzinfo=datetime.timezone.utc)) + end_date = FuzzyDateTime(datetime.datetime(2020, 1, 10, tzinfo=datetime.timezone.utc), + datetime.datetime(2020, 1, 20, tzinfo=datetime.timezone.utc)) diff --git a/backend/tests/fake_data.py b/backend/tests/fake_data.py index 35cf3d4..60c740b 100644 --- a/backend/tests/fake_data.py +++ b/backend/tests/fake_data.py @@ -1,10 +1,11 @@ from typing import List from .factory import ProjectSupervisorFactory, YearGroupProjectSupervisorsFactory, \ - StudentFactory, YearGroupStudentsFactory, GroupFactory + StudentFactory, YearGroupStudentsFactory, GroupFactory, ExaminationScheduleFactory from app.dependencies import db from app.project_supervisor.models import YearGroup, ProjectSupervisor from app.students.models import Group, Student, YearGroupStudents +from app.examination_schedule.models import ExaminationSchedule from app.base.mode import ModeGroups @@ -73,3 +74,17 @@ def create_group(data: dict, yg: YearGroup) -> Group: db.session.add(group) db.session.commit() return group + + +def create_examination_schedules(yg: YearGroup, amount: int) -> List[ExaminationScheduleFactory]: + examination_schedules = [ExaminationScheduleFactory(year_group_id=yg.id) for _ in range(amount)] + db.session.add_all(examination_schedules) + db.session.commit() + return examination_schedules + + +def create_examination_schedule(data: dict, yg: YearGroup) -> ExaminationSchedule: + ex = ExaminationSchedule(**data, year_group_id=yg.id) + db.session.add(ex) + db.session.commit() + return ex diff --git a/backend/tests/functional_tests/coordinator/test_examination_schedule.py b/backend/tests/functional_tests/coordinator/test_examination_schedule.py new file mode 100644 index 0000000..fe48b1e --- /dev/null +++ b/backend/tests/functional_tests/coordinator/test_examination_schedule.py @@ -0,0 +1,119 @@ +import datetime + +from ...utils import _test_case_client, _test_case_client_without_response, assert_model_changes +from ...fake_data import create_examination_schedule, create_year_group, create_examination_schedules +from app.dependencies import db + +valid_data = { + 'title': 'examination schedule summer', + 'start_date': datetime.datetime.now() + datetime.timedelta(days=5), + 'end_date': datetime.datetime.now() + datetime.timedelta(days=10), + 'duration_time': 30 + +} + +ex_data = { + 'title': 'new title', + 'start_date': (datetime.datetime.now() + datetime.timedelta(days=5)).strftime("%Y-%m-%dT%H:%M:%S.000Z"), + 'end_date': (datetime.datetime.now() + datetime.timedelta(days=10)).strftime("%Y-%m-%dT%H:%M:%S.000Z") +} + +enrollments_data = { + 'start_date_for_enrollment_students': (datetime.datetime.now() + datetime.timedelta(days=2)).strftime( + "%Y-%m-%dT%H:%M:%S.000Z"), + 'end_date_for_enrollment_students': (datetime.datetime.now() + datetime.timedelta(days=4)).strftime( + "%Y-%m-%dT%H:%M:%S.000Z") +} + + +def test_list_examination_schedules(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_year_group() + create_examination_schedules(year_group, 34) + + url = f'/api/coordinator/examination_schedule/{year_group.id}/?per_page=10' + data = _test_case_client_without_response(client, url, None, 200, method='get') + assert data.get('max_pages') == 4 + assert len(data.get('examination_schedules')) == 10 + + +def test_delete_examination_schedule(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_year_group() + ex = create_examination_schedules(year_group, 1)[0] + _test_case_client(client, f'/api/coordinator/examination_schedule/{ex.id}/', None, + 'Examination schedule was deleted!', 200, method='delete') + + +def test_delete_examination_schedule_if_examination_schedule_doesnt_exist(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + _test_case_client(client, '/api/coordinator/examination_schedule/32/', None, + "Examination schedule doesn't exist!", 404, method='delete', key='error') + + +def test_update_examination_schedule(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_year_group() + ex = create_examination_schedules(year_group, 1)[0] + _test_case_client(client, f'/api/coordinator/examination_schedule/{ex.id}/', ex_data, + 'Examination schedule was updated!', 200, method='put') + assert_model_changes(ex, ex_data) + + +def test_update_examination_schedule_schedule_if_examination_schedule_doesnt_exist(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + _test_case_client(client, '/api/coordinator/examination_schedule/32/', ex_data, + "Examination schedule doesn't exist!", 404, method='put', key='error') + + +def test_set_date_of_examination_schedule(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_year_group() + ex = create_examination_schedule(valid_data, year_group) + _test_case_client(client, f'/api/coordinator/examination_schedule/{ex.id}/date/', enrollments_data, + 'You set date of examination schedule!', 200, method='put') + assert_model_changes(ex, enrollments_data) + + +def test_set_date_of_examination_schedule_if_examination_schedule_doesnt_exist(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + _test_case_client(client, '/api/coordinator/examination_schedule/43/date/', enrollments_data, + 'Examination schedule doesn\'t exist!', 404, method='put', key='error') + + +def test_set_date_of_examination_schedule_with_invalid_date(test_app_with_context) -> None: + invalid_dates = { + 'start_date_for_enrollment_students': enrollments_data['end_date_for_enrollment_students'], + 'end_date_for_enrollment_students': enrollments_data['start_date_for_enrollment_students'], + } + + with test_app_with_context.test_client() as client: + year_group = create_year_group() + ex = create_examination_schedule(valid_data, year_group) + _test_case_client(client, f'/api/coordinator/examination_schedule/{ex.id}/date/', invalid_dates, + 'Invalid data! End date must be greater than start date!', 400, method='put', key='error') + + +def test_create_project_supervisors(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_year_group() + _test_case_client(client, f'/api/coordinator/examination_schedule/{year_group.id}/', ex_data, + 'Examination schedule was created!', 201, method='post') + + +def test_create_project_supervisors_if_year_group_doesnt_exist(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + _test_case_client(client, '/api/coordinator/examination_schedule/33/', ex_data, + 'Year group doesn\'t exist!', 404, method='post', key='error') + + +def test_create_project_supervisors_with_invalid_dates(test_app_with_context) -> None: + invalid_data = { + 'title': 'examination schedule winter', + 'start_date': ex_data['end_date'], + 'end_date': ex_data['start_date'] + } + with test_app_with_context.test_client() as client: + year_group = create_year_group() + _test_case_client(client, f'/api/coordinator/examination_schedule/{year_group.id}/', invalid_data, + 'Invalid data! End date must be greater than start date!', 400, method='post', key='error') diff --git a/backend/tests/utils.py b/backend/tests/utils.py index 9d536e6..c0aa8ed 100644 --- a/backend/tests/utils.py +++ b/backend/tests/utils.py @@ -1,3 +1,4 @@ +import datetime from typing import Union from flask.testing import FlaskClient @@ -8,7 +9,10 @@ from app.students.models import Group def assert_model_changes(model: db.Model, expected_data: dict) -> None: for key, val in expected_data.items(): - assert getattr(model, key) == val + value = getattr(model, key) + if isinstance(value, datetime.datetime): + value = value.strftime("%Y-%m-%dT%H:%M:%S.000Z") + assert value == val def _test_case_client_without_response(test_client: FlaskClient, url: str, data: Union[dict, None], status_code: int,