From 61fcda82ab3fe3460b296c650656c66c74dccb27 Mon Sep 17 00:00:00 2001 From: dominik24c Date: Mon, 16 Jan 2023 19:18:03 +0100 Subject: [PATCH] update functional test and add enrollments endpoints tests for coordinator view --- backend/app/coordinator/query/enrollments.py | 3 +- backend/app/coordinator/routes/enrollments.py | 10 +- .../app/coordinator/schemas/enrollments.py | 10 +- backend/tests/factory.py | 69 +- backend/tests/fake_data.py | 115 --- .../coordinator/test_enrollments.py | 707 ++++++++++++++++++ .../coordinator/test_examination_schedule.py | 156 ++-- .../coordinator/test_groups.py | 148 ++-- .../coordinator/test_project_supervisors.py | 281 ++----- .../coordinator/test_students.py | 57 +- .../coordinator/test_year_group.py | 46 +- .../project_supervisors/enrollments.py | 0 backend/tests/utils.py | 33 +- 13 files changed, 1024 insertions(+), 611 deletions(-) delete mode 100644 backend/tests/fake_data.py create mode 100644 backend/tests/functional_tests/project_supervisors/enrollments.py diff --git a/backend/app/coordinator/query/enrollments.py b/backend/app/coordinator/query/enrollments.py index 4f02cbd..8da1b0a 100644 --- a/backend/app/coordinator/query/enrollments.py +++ b/backend/app/coordinator/query/enrollments.py @@ -70,7 +70,7 @@ def get_and_check_the_project_supervisors_exists_in_db( ) if len(project_supervisors) != len(project_supervisors_ids): - abort(400, "Project Supervisors didn't exist!") + abort(404, "Not found project supervisors!") return project_supervisors @@ -92,7 +92,6 @@ def validate_enrollments_date( delta_time = end_date - start_date delta_time_in_minutes = delta_time.total_seconds() / 60 - print(delta_time_in_minutes, duration_time, delta_time_in_minutes != duration_time) if delta_time_in_minutes % duration_time != 0: abort(400, "Invalid duration time!") diff --git a/backend/app/coordinator/routes/enrollments.py b/backend/app/coordinator/routes/enrollments.py index dcb84b2..b1ef64a 100644 --- a/backend/app/coordinator/routes/enrollments.py +++ b/backend/app/coordinator/routes/enrollments.py @@ -27,7 +27,7 @@ bp = APIBlueprint("enrollments", __name__, url_prefix="/enrollments") @bp.post("//add") @bp.input(TermOfDefenceSchema) -@bp.output(MessageSchema) +@bp.output(MessageSchema, status_code=201) def create_term_of_defence(examination_schedule_id: int, data: dict) -> dict: chairman_of_committee_id = data.pop("chairman_of_committee") project_supervisors_ids = data.pop("project_supervisors") @@ -58,7 +58,7 @@ def create_term_of_defence(examination_schedule_id: int, data: dict) -> dict: @bp.post("//add-term-of-defences/") @bp.input(TermOfDefenceSchema) -@bp.output(MessageSchema) +@bp.output(MessageSchema, status_code=201) def create_many_term_of_defences(examination_schedule_id: int, data: dict) -> dict: chairman_of_committee_id = data.pop("chairman_of_committee") project_supervisors_ids = data.pop("project_supervisors") @@ -194,7 +194,7 @@ def list_of_assigned_group_to_term_of_defences(examination_schedule_id: int) -> "//term-of-defence//group/" ) @bp.input(GroupIdSchema) -@bp.output(MessageSchema) +@bp.output(MessageSchema, status_code=201) def add_group_to_term_of_defence( examination_schedule_id: int, term_of_defence_id: int, data: dict ) -> dict: @@ -202,7 +202,7 @@ def add_group_to_term_of_defence( examination_schedule_id, term_of_defence_id, data.get("group_id") ) db.session.commit() - return {"message": "Group was added to term of defences!"} + return {"message": "Group was added to term of defence!"} @bp.delete( @@ -217,7 +217,7 @@ def delete_group_to_term_of_defence( ) td.group_id = None db.session.commit() - return {"message": "Group was deleted from term of defences!"} + return {"message": "Group was deleted from this term of defence!"} @bp.put( diff --git a/backend/app/coordinator/schemas/enrollments.py b/backend/app/coordinator/schemas/enrollments.py index df9d29a..5274a2e 100644 --- a/backend/app/coordinator/schemas/enrollments.py +++ b/backend/app/coordinator/schemas/enrollments.py @@ -1,15 +1,9 @@ from marshmallow import Schema, fields, validate -from ..validators import validate_datetime_greater_than_now - class TermOfDefenceSchema(Schema): - start_date = fields.DateTime( - validate=validate_datetime_greater_than_now, required=True - ) - end_date = fields.DateTime( - validate=validate_datetime_greater_than_now, required=True - ) + start_date = fields.DateTime(required=True) + end_date = fields.DateTime(required=True) project_supervisors = fields.List( fields.Integer(required=True), validate=validate.Length(3, 3) ) diff --git a/backend/tests/factory.py b/backend/tests/factory.py index 040bea4..67a4dc2 100644 --- a/backend/tests/factory.py +++ b/backend/tests/factory.py @@ -4,10 +4,24 @@ from factory import Sequence, alchemy from factory.faker import Faker from factory.fuzzy import FuzzyDateTime, FuzzyInteger +from app.base.mode import ModeGroups from app.dependencies import db -from app.examination_schedule.models import ExaminationSchedule -from app.project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors -from app.students.models import Group, Student, YearGroupStudents +from app.examination_schedule.models import ( + ExaminationSchedule, + TemporaryAvailability, + TermOfDefence, +) +from app.project_supervisor.models import ProjectSupervisor +from app.students.models import Group, Student, YearGroup + + +class YearGroupFactory(alchemy.SQLAlchemyModelFactory): + class Meta: + model = YearGroup + sqlalchemy_session = db.session + + name = "2022/2023" + mode = ModeGroups.STATIONARY.value class ProjectSupervisorFactory(alchemy.SQLAlchemyModelFactory): @@ -18,13 +32,6 @@ class ProjectSupervisorFactory(alchemy.SQLAlchemyModelFactory): first_name = Faker("first_name") last_name = Faker("last_name") email = Faker("email") - - -class YearGroupProjectSupervisorsFactory(alchemy.SQLAlchemyModelFactory): - class Meta: - model = YearGroupProjectSupervisors - sqlalchemy_session = db.session - limit_group = 4 @@ -34,8 +41,10 @@ class GroupFactory(alchemy.SQLAlchemyModelFactory): sqlalchemy_session = db.session name = Sequence(lambda n: f"Group-{n}") - points_for_first_term = FuzzyInteger(1, 5) - points_for_second_term = FuzzyInteger(1, 5) + points_for_first_term = FuzzyInteger(1, 100) + points_for_second_term = FuzzyInteger(1, 100) + grade_for_first_term = FuzzyInteger(2, 5) + grade_for_second_term = FuzzyInteger(2, 5) class StudentFactory(alchemy.SQLAlchemyModelFactory): @@ -49,12 +58,6 @@ class StudentFactory(alchemy.SQLAlchemyModelFactory): index = Sequence(lambda n: 400_000 + n) -class YearGroupStudentsFactory(alchemy.SQLAlchemyModelFactory): - class Meta: - model = YearGroupStudents - sqlalchemy_session = db.session - - class ExaminationScheduleFactory(alchemy.SQLAlchemyModelFactory): class Meta: model = ExaminationSchedule @@ -70,3 +73,33 @@ class ExaminationScheduleFactory(alchemy.SQLAlchemyModelFactory): datetime.datetime(2020, 1, 10, tzinfo=datetime.timezone.utc), datetime.datetime(2020, 1, 20, tzinfo=datetime.timezone.utc), ) + + +class TermOfDefenceFactory(alchemy.SQLAlchemyModelFactory): + class Meta: + model = TermOfDefence + sqlalchemy_session = db.session + + start_date = Sequence( + lambda n: datetime.datetime(2020, 1, 1, tzinfo=datetime.timezone.utc) + + datetime.timedelta(n * 30) + ) + end_date = Sequence( + lambda n: datetime.datetime(2020, 1, 1, tzinfo=datetime.timezone.utc) + + datetime.timedelta(n * 30 + 30) + ) + + +class TemporaryAvailabilityFactory(alchemy.SQLAlchemyModelFactory): + class Meta: + model = TemporaryAvailability + sqlalchemy_session = db.session + + start_date = Sequence( + lambda n: datetime.datetime(2020, 1, 1, tzinfo=datetime.timezone.utc) + + datetime.timedelta(n * 30) + ) + end_date = Sequence( + lambda n: datetime.datetime(2020, 1, 1, tzinfo=datetime.timezone.utc) + + datetime.timedelta(n * 30 + 30) + ) diff --git a/backend/tests/fake_data.py b/backend/tests/fake_data.py deleted file mode 100644 index 2091a24..0000000 --- a/backend/tests/fake_data.py +++ /dev/null @@ -1,115 +0,0 @@ -from typing import List - -from app.base.mode import ModeGroups -from app.dependencies import db -from app.examination_schedule.models import ExaminationSchedule -from app.project_supervisor.models import ProjectSupervisor, YearGroup -from app.students.models import Group, Student, YearGroupStudents - -from .factory import ( - ExaminationScheduleFactory, - GroupFactory, - ProjectSupervisorFactory, - StudentFactory, - YearGroupProjectSupervisorsFactory, - YearGroupStudentsFactory, -) - - -def create_year_group(data: dict = None) -> YearGroup: - if data is None: - data = {"mode": ModeGroups.STATIONARY.value, "name": "2022/2023"} - yg = YearGroup(**data) - db.session.add(yg) - db.session.commit() - return yg - - -def create_project_supervisors( - yg: YearGroup, amount: int, limit_group: int = 3 -) -> List[ProjectSupervisorFactory]: - ps = [ProjectSupervisorFactory() for _ in range(amount)] - db.session.add_all(ps) - db.session.commit() - db.session.add_all( - [ - YearGroupProjectSupervisorsFactory( - limit_group=limit_group, year_group_id=yg.id, project_supervisor_id=p.id - ) - for p in ps - ] - ) - db.session.commit() - return ps - - -def create_dummy_ps(data: dict) -> ProjectSupervisor: - ps = ProjectSupervisor(**data) - db.session.add(ps) - db.session.commit() - return ps - - -def create_dummy_group(data: dict, project_supervisor_id: int) -> Group: - group = Group(**data, project_supervisor_id=project_supervisor_id) - db.session.add(group) - db.session.commit() - return group - - -def create_students(yg: YearGroup, amount: int) -> List[StudentFactory]: - students = [StudentFactory() for _ in range(amount)] - db.session.add_all(students) - db.session.commit() - db.session.add_all( - [ - YearGroupStudentsFactory(year_group_id=yg.id, student_index=s.index) - for s in students - ] - ) - db.session.commit() - return students - - -def create_student(data: dict, year_group_id: int = None) -> Student: - st = Student(**data) - db.session.add(st) - db.session.commit() - if year_group_id is not None: - db.session.add( - YearGroupStudents(year_group_id=year_group_id, student_index=st.index) - ) - db.session.commit() - return st - - -def create_groups(yg: YearGroup, amount: int) -> List[Group]: - groups = [GroupFactory(year_group_id=yg.id) for _ in range(amount)] - db.session.add_all(groups) - db.session.commit() - return groups - - -def create_group(data: dict, yg: YearGroup) -> Group: - group = Group(**data, year_group_id=yg.id) - 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_enrollments.py b/backend/tests/functional_tests/coordinator/test_enrollments.py index e69de29..d968791 100644 --- a/backend/tests/functional_tests/coordinator/test_enrollments.py +++ b/backend/tests/functional_tests/coordinator/test_enrollments.py @@ -0,0 +1,707 @@ +import datetime + +from app.base.mode import EnrollmentsMode +from app.dependencies import db +from app.examination_schedule.models import ExaminationSchedule, TermOfDefence + +from ...factory import ( + ExaminationScheduleFactory, + GroupFactory, + ProjectSupervisorFactory, + TemporaryAvailabilityFactory, + TermOfDefenceFactory, + YearGroupFactory, +) +from ...utils import ( + _test_case_client, + _test_case_client_without_response, + assert_model_changes, + create_many_models, + create_one_model, +) + + +def get_data_of_term_of_defence(timedelta_minutes: int = 30) -> dict: + ex = ExaminationSchedule.query.first() + if ex is None: + date = datetime.datetime.now() + else: + date = ex.start_date + return { + "start_date": (date + datetime.timedelta(days=1)).strftime( + "%Y-%m-%dT%H:%M:%S.000Z" + ), + "end_date": ( + date + datetime.timedelta(days=1, minutes=timedelta_minutes) + ).strftime("%Y-%m-%dT%H:%M:%S.000Z"), + } + + +def test_list_of_term_of_defences(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + create_many_models(32, TermOfDefenceFactory, examination_schedule_id=ex.id) + url = f"/api/coordinator/enrollments/{ex.id}/term-of-defences/" + data = _test_case_client_without_response(client, url, None, 200, method="get") + assert len(data.get("term_of_defences")) == 32 + + +def test_delete_term_of_defence(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/delete/{td.id}/", + None, + "Term of defence was deleted!", + 200, + method="delete", + ) + + +def test_delete_term_of_defence_if_term_of_defence_or_examination_schedule_doesnt_exist( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + _test_case_client( + client, + "/api/coordinator/enrollments/2/delete/1/", + None, + "Not found examination schedule or term of defence!", + 404, + method="delete", + key="error", + ) + + +def test_create_term_of_defence(test_app_with_context, monkeypatch) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + project_supervisors = create_many_models( + 3, ProjectSupervisorFactory, year_group_id=year_group.id + ) + + data = get_data_of_term_of_defence() + data["project_supervisors"] = [ps.id for ps in project_supervisors] + data["chairman_of_committee"] = project_supervisors[0].id + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/add", + data, + "Term of defence was created!", + 201, + method="post", + ) + td = TermOfDefence.query.first() + assert_model_changes( + td, {"start_date": data["start_date"], "end_date": data["end_date"]} + ) + assert {member.id for member in td.members_of_committee} == set( + data["project_supervisors"] + ) + + +def test_create_many_term_of_defences(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + project_supervisors = create_many_models( + 3, ProjectSupervisorFactory, year_group_id=year_group.id + ) + + data = get_data_of_term_of_defence(150) + data["project_supervisors"] = [ps.id for ps in project_supervisors] + data["chairman_of_committee"] = project_supervisors[0].id + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/add-term-of-defences/", + data, + "Term of defences was created!", + 201, + method="post", + ) + assert TermOfDefence.query.count() == 5 + + for td in TermOfDefence.query.all(): + assert {member.id for member in td.members_of_committee} == set( + data["project_supervisors"] + ) + + +def test_create_many_term_of_defences_with_invalid_id_of_chairman( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + project_supervisors = create_many_models( + 3, ProjectSupervisorFactory, year_group_id=year_group.id + ) + + data = get_data_of_term_of_defence(150) + data["project_supervisors"] = [ps.id for ps in project_supervisors] + data["chairman_of_committee"] = 353 + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/add-term-of-defences/", + data, + "Invalid id of chairman committee!", + 400, + method="post", + key="error", + ) + + +def test_create_many_term_of_defences_if_examination_schedule_doesnt_exist( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + project_supervisors = create_many_models( + 3, ProjectSupervisorFactory, year_group_id=year_group.id + ) + + data = get_data_of_term_of_defence(150) + data["project_supervisors"] = [ps.id for ps in project_supervisors] + data["chairman_of_committee"] = project_supervisors[0].id + _test_case_client( + client, + "/api/coordinator/enrollments/32/add-term-of-defences/", + data, + "Not found examination schedule!", + 404, + method="post", + key="error", + ) + + +def test_create_many_term_of_defences_if_project_supervisors_doesnt_exist( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + data = get_data_of_term_of_defence(150) + data["project_supervisors"] = [1, 2, 3] + data["chairman_of_committee"] = 1 + + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/add-term-of-defences/", + data, + "Not found project supervisors!", + 404, + method="post", + key="error", + ) + + +def test_create_many_term_of_defences_with_invalid_duration_time( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + project_supervisors = create_many_models( + 3, ProjectSupervisorFactory, year_group_id=year_group.id + ) + + data = get_data_of_term_of_defence(133) + data["project_supervisors"] = [ps.id for ps in project_supervisors] + data["chairman_of_committee"] = project_supervisors[0].id + + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/add-term-of-defences/", + data, + "Invalid duration time!", + 400, + method="post", + key="error", + ) + + +def test_create_many_term_of_defences_if_start_date_is_greater_than_end_date( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + project_supervisors = create_many_models( + 3, ProjectSupervisorFactory, year_group_id=year_group.id + ) + + data = get_data_of_term_of_defence(133) + data["project_supervisors"] = [ps.id for ps in project_supervisors] + data["chairman_of_committee"] = project_supervisors[0].id + data["start_date"], data["end_date"] = data["end_date"], data["start_date"] + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/add-term-of-defences/", + data, + "End date must be greater than start date!", + 400, + method="post", + key="error", + ) + + +def test_create_many_term_of_defences_with_invalid_date_range( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + project_supervisors = create_many_models( + 3, ProjectSupervisorFactory, year_group_id=year_group.id + ) + + data = get_data_of_term_of_defence(120) + data["project_supervisors"] = [ps.id for ps in project_supervisors] + data["chairman_of_committee"] = project_supervisors[0].id + data["end_date"] = (ex.end_date + datetime.timedelta(days=1)).strftime( + "%Y-%m-%dT%H:%M:%S.000Z" + ) + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/add-term-of-defences/", + data, + "Invalid date range!", + 400, + method="post", + key="error", + ) + + +def test_update_term_of_defence(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + project_supervisors = create_many_models( + 3, ProjectSupervisorFactory, year_group_id=year_group.id + ) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + td.members_of_committee = project_supervisors + td.chairman_of_committee = project_supervisors[0].id + db.session.commit() + data = get_data_of_term_of_defence(150) + data["project_supervisors"] = [ps.id for ps in project_supervisors] + data["chairman_of_committee"] = project_supervisors[2].id + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/update/{td.id}/", + data, + "Term of defence was updated!", + 200, + method="put", + ) + assert td.chairman_of_committee == project_supervisors[2].id + + +def test_update_term_of_defence_with_invalid_id_of_chairman( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + project_supervisors = create_many_models( + 3, ProjectSupervisorFactory, year_group_id=year_group.id + ) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + + data = get_data_of_term_of_defence(150) + data["project_supervisors"] = [ps.id for ps in project_supervisors] + data["chairman_of_committee"] = 353 + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/update/{td.id}/", + data, + "Invalid id of chairman committee!", + 400, + method="put", + key="error", + ) + + +def test_update_term_of_defence_if_examination_schedule_or_term_of_defence_doesnt_exist( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + data = get_data_of_term_of_defence(150) + data["project_supervisors"] = [1, 2, 3] + data["chairman_of_committee"] = 1 + _test_case_client( + client, + f"/api/coordinator/enrollments/32/update/23/", + data, + "Not found term of defence!", + 404, + method="put", + key="error", + ) + + +def test_update_term_of_defence_if_project_supervisors_doesnt_exist( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + data = get_data_of_term_of_defence(150) + data["project_supervisors"] = [1, 2, 3] + data["chairman_of_committee"] = 1 + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/update/{td.id}/", + data, + "Not found project supervisors!", + 404, + method="put", + key="error", + ) + + +def test_update_term_of_defence_with_invalid_duration_time( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + project_supervisors = create_many_models( + 3, ProjectSupervisorFactory, year_group_id=year_group.id + ) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + data = get_data_of_term_of_defence(133) + data["project_supervisors"] = [ps.id for ps in project_supervisors] + data["chairman_of_committee"] = project_supervisors[0].id + + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/update/{td.id}/", + data, + "Invalid duration time!", + 400, + method="put", + key="error", + ) + + +def test_update_term_of_defence_if_start_date_is_greater_than_end_date( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + project_supervisors = create_many_models( + 3, ProjectSupervisorFactory, year_group_id=year_group.id + ) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + + data = get_data_of_term_of_defence(133) + data["project_supervisors"] = [ps.id for ps in project_supervisors] + data["chairman_of_committee"] = project_supervisors[0].id + data["start_date"], data["end_date"] = data["end_date"], data["start_date"] + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/update/{td.id}/", + data, + "End date must be greater than start date!", + 400, + method="put", + key="error", + ) + + +def test_update_term_of_defence_with_invalid_date_range(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + project_supervisors = create_many_models( + 3, ProjectSupervisorFactory, year_group_id=year_group.id + ) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + + data = get_data_of_term_of_defence(120) + data["project_supervisors"] = [ps.id for ps in project_supervisors] + data["chairman_of_committee"] = project_supervisors[0].id + data["end_date"] = (ex.end_date + datetime.timedelta(days=1)).strftime( + "%Y-%m-%dT%H:%M:%S.000Z" + ) + _test_case_client( + client, + f"/api/coordinator/enrollments/{ex.id}/update/{td.id}/", + data, + "Invalid date range!", + 400, + method="put", + key="error", + ) + + +def test_list_temporary_availabilities(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + ps = create_one_model(ProjectSupervisorFactory, year_group_id=year_group.id) + amount = 24 + create_many_models( + amount, + TemporaryAvailabilityFactory, + examination_schedule_id=ex.id, + project_supervisor_id=ps.id, + ) + url = f"/api/coordinator/enrollments/{ex.id}/temporary-availabilities/" + data = _test_case_client_without_response(client, url, None, 200, method="get") + assert len(data.get("temporary_availabilities")) == amount + + +def test_list_temporary_availabilities_if_examination_schedule_doesnt_exist( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + url = "/api/coordinator/enrollments/43/temporary-availabilities/" + _test_case_client( + client, + url, + None, + "Not found examination schedule!", + 404, + method="get", + key="error", + ) + + +def test_list_of_assigned_group_to_term_of_defences(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + amount = 5 + groups = create_many_models(amount, GroupFactory) + tds = create_many_models( + 24, TermOfDefenceFactory, examination_schedule_id=ex.id + ) + for group, td in zip(groups, tds): + td.group_id = group.id + db.session.commit() + + url = ( + f"/api/coordinator/enrollments/{ex.id}/assigned-group-to-term-of-defences/" + ) + data = _test_case_client_without_response(client, url, None, 200, method="get") + term_of_defences = data.get("term_of_defences") + assert len(term_of_defences) == amount + + +def test_list_of_assigned_group_to_term_of_defences_if_examination_schedule_doesnt_exist( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + url = "/api/coordinator/enrollments/43/assigned-group-to-term-of-defences/" + _test_case_client( + client, + url, + None, + "Not found examination schedule!", + 404, + method="get", + key="error", + ) + + +def test_set_new_group_to_term_of_defence(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + group = create_one_model(GroupFactory) + + url = f"/api/coordinator/enrollments/{ex.id}/term-of-defence/{td.id}/group/" + _test_case_client( + client, + url, + {"group_id": group.id}, + "Group was added to term of defence!", + 201, + method="post", + ) + + +def test_set_new_group_to_term_of_defence_if_examination_schedule_or_term_of_defence_dont_exist( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + url = "/api/coordinator/enrollments/34/term-of-defence/4/group/" + _test_case_client( + client, + url, + {"group_id": 2}, + "Not found examination schedule or term of defence!", + 404, + method="post", + key="error", + ) + + +def test_set_new_group_to_term_of_defence_if_group_doesnt_exist( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + + url = f"/api/coordinator/enrollments/{ex.id}/term-of-defence/{td.id}/group/" + _test_case_client( + client, + url, + {"group_id": 1}, + "Not found group!", + 404, + method="post", + key="error", + ) + + +def test_set_new_group_to_term_of_defence_if_(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + group = create_one_model(GroupFactory) + create_one_model( + TermOfDefenceFactory, examination_schedule_id=ex.id, group_id=group.id + ) + + url = f"/api/coordinator/enrollments/{ex.id}/term-of-defence/{td.id}/group/" + _test_case_client( + client, + url, + {"group_id": group.id}, + "Group has already assigned to term of defence!", + 400, + method="post", + key="error", + ) + assert td.group_id is None + + +def test_delete_group_to_term_of_defence(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + group = create_one_model(GroupFactory) + + url = f"/api/coordinator/enrollments/{ex.id}/term-of-defence/{td.id}/group/" + _test_case_client( + client, + url, + {"group_id": group.id}, + "Group was deleted from this term of defence!", + 200, + method="delete", + ) + + assert td.group_id is None + + +def test_delete_group_to_term_of_defence_if_examination_schedule_doesnt_exist( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + url = "/api/coordinator/enrollments/3/term-of-defence/1/group/" + _test_case_client( + client, + url, + None, + "Not found examination schedule or term of defence!", + 404, + method="delete", + key="error", + ) + + +def test_update_group_for_term_of_defence(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + group2 = create_one_model(GroupFactory) + td = create_one_model( + TermOfDefenceFactory, examination_schedule_id=ex.id, group_id=group2.id + ) + group = create_one_model(GroupFactory) + + url = f"/api/coordinator/enrollments/{ex.id}/term-of-defence/{td.id}/group/" + _test_case_client( + client, + url, + {"group_id": group.id}, + "Group for term of defence was updated!", + 200, + method="put", + ) + assert td.group_id == group.id + + +def test_update_group_for_term_of_defence_if_examination_schedule_or_term_of_defence_dont_exist( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + url = "/api/coordinator/enrollments/34/term-of-defence/4/group/" + _test_case_client( + client, + url, + {"group_id": 2}, + "Not found examination schedule or term of defence!", + 404, + method="put", + key="error", + ) + + +def test_update_group_for_term_of_defence_if_group_doesnt_exist( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + + url = f"/api/coordinator/enrollments/{ex.id}/term-of-defence/{td.id}/group/" + _test_case_client( + client, + url, + {"group_id": 1}, + "Not found group!", + 404, + method="put", + key="error", + ) + + +def test_update_group_for_term_of_defence_of_defence_if_(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + td = create_one_model(TermOfDefenceFactory, examination_schedule_id=ex.id) + group = create_one_model(GroupFactory) + create_one_model( + TermOfDefenceFactory, examination_schedule_id=ex.id, group_id=group.id + ) + + url = f"/api/coordinator/enrollments/{ex.id}/term-of-defence/{td.id}/group/" + _test_case_client( + client, + url, + {"group_id": group.id}, + "Group has already assigned to term of defence!", + 400, + method="put", + key="error", + ) + assert td.group_id is None diff --git a/backend/tests/functional_tests/coordinator/test_examination_schedule.py b/backend/tests/functional_tests/coordinator/test_examination_schedule.py index ea9fb68..35f6e3b 100644 --- a/backend/tests/functional_tests/coordinator/test_examination_schedule.py +++ b/backend/tests/functional_tests/coordinator/test_examination_schedule.py @@ -1,25 +1,16 @@ import datetime -from app.dependencies import db +from app.base.mode import EnrollmentsMode -from ...fake_data import ( - create_examination_schedule, - create_examination_schedules, - create_year_group, -) +from ...factory import ExaminationScheduleFactory, YearGroupFactory from ...utils import ( _test_case_client, _test_case_client_without_response, assert_model_changes, + create_many_models, + create_one_model, ) -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( @@ -30,20 +21,11 @@ ex_data = { ), } -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) + year_group = create_one_model(YearGroupFactory) + create_many_models(34, ExaminationScheduleFactory, year_group_id=year_group.id) url = f"/api/coordinator/examination_schedule/{year_group.id}/?per_page=10" data = _test_case_client_without_response(client, url, None, 200, method="get") @@ -53,8 +35,8 @@ def test_list_examination_schedules(test_app_with_context) -> None: 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] + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) _test_case_client( client, f"/api/coordinator/examination_schedule/{ex.id}/", @@ -82,8 +64,8 @@ def test_delete_examination_schedule_if_examination_schedule_doesnt_exist( 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] + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) _test_case_client( client, f"/api/coordinator/examination_schedule/{ex.id}/", @@ -110,65 +92,9 @@ def test_update_examination_schedule_schedule_if_examination_schedule_doesnt_exi ) -def test_set_date_of_examination_schedule(test_app_with_context) -> None: +def test_create_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() + year_group = create_one_model(YearGroupFactory) _test_case_client( client, f"/api/coordinator/examination_schedule/{year_group.id}/", @@ -179,7 +105,7 @@ def test_create_project_supervisors(test_app_with_context) -> None: ) -def test_create_project_supervisors_if_year_group_doesnt_exist( +def test_create_examination_schedule_if_year_group_doesnt_exist( test_app_with_context, ) -> None: with test_app_with_context.test_client() as client: @@ -194,14 +120,14 @@ def test_create_project_supervisors_if_year_group_doesnt_exist( ) -def test_create_project_supervisors_with_invalid_dates(test_app_with_context) -> None: +def test_create_examination_schedule_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() + year_group = create_one_model(YearGroupFactory) _test_case_client( client, f"/api/coordinator/examination_schedule/{year_group.id}/", @@ -211,3 +137,55 @@ def test_create_project_supervisors_with_invalid_dates(test_app_with_context) -> method="post", key="error", ) + + +def test_create_examination_schedule_with_invalid_data( + test_app_with_context, +) -> None: + invalid_data = { + "title": "examination schedule winter", + "start_date": ex_data["end_date"], + "end_date": "30.03.2032 12:23.03.", + } + with test_app_with_context.test_client() as client: + response_data = _test_case_client( + client, + "/api/coordinator/examination_schedule/33/", + invalid_data, + "Validation error", + 400, + method="post", + ) + assert response_data["detail"]["json"]["end_date"][0] == "Not a valid datetime." + + +def test_open_enrollments(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + assert ex.open_enrollments == EnrollmentsMode.INIT.value + _test_case_client( + client, + f"/api/coordinator/examination_schedule/{ex.id}/open-enrollments/", + None, + "You open enrollments for this examination schedule!", + 200, + method="put", + ) + assert ex.open_enrollments == EnrollmentsMode.OPEN.value + + +def test_close_enrollments(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_group = create_one_model(YearGroupFactory) + ex = create_one_model(ExaminationScheduleFactory, year_group_id=year_group.id) + assert ex.open_enrollments == EnrollmentsMode.INIT.value + _test_case_client( + client, + f"/api/coordinator/examination_schedule/{ex.id}/close-enrollments/", + None, + "You close enrollments for this examination schedule!", + 200, + method="put", + ) + assert ex.open_enrollments == EnrollmentsMode.CLOSE.value diff --git a/backend/tests/functional_tests/coordinator/test_groups.py b/backend/tests/functional_tests/coordinator/test_groups.py index ac90d4c..a7c69a1 100644 --- a/backend/tests/functional_tests/coordinator/test_groups.py +++ b/backend/tests/functional_tests/coordinator/test_groups.py @@ -1,40 +1,36 @@ import copy -from flask import current_app - from app.dependencies import db -from app.project_supervisor.models import YearGroupProjectSupervisors from app.students.models import Group -from ...fake_data import ( - create_group, - create_groups, - create_project_supervisors, - create_students, - create_year_group, +from ...factory import ( + GroupFactory, + ProjectSupervisorFactory, + StudentFactory, + YearGroupFactory, ) from ...utils import ( _test_case_client, _test_case_client_without_response, _test_case_group, assert_model_changes, + create_many_models, + create_one_model, ) -valid_data = {"name": "System Pri"} - new_data = {"name": "Mobile app"} invalid_data = { "name": "Mobile app v2", - "students": [123_344, 455_444], + "students": [283, 12234], "project_supervisor_id": 1, } def test_list_groups(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - yg = create_year_group() - create_groups(yg, 33) + yg = create_one_model(YearGroupFactory) + create_many_models(33, GroupFactory, year_group_id=yg.id) data = _test_case_client_without_response( client, f"/api/coordinator/groups/{yg.id}/?per_page=10", @@ -48,8 +44,8 @@ def test_list_groups(test_app_with_context) -> None: def test_detail_group(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - yg = create_year_group() - group = create_group(valid_data, yg) + yg = create_one_model(YearGroupFactory) + group = create_one_model(GroupFactory, year_group_id=yg.id) data = _test_case_client_without_response( client, f"/api/coordinator/groups/{group.id}/detail/", @@ -75,8 +71,8 @@ def test_detail_group_if_group_doesnt_exist(test_app_with_context) -> None: def test_delete_group(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - yg = create_year_group() - group = create_group(valid_data, yg) + yg = create_one_model(YearGroupFactory) + group = create_one_model(GroupFactory, year_group_id=yg.id) _test_case_client( client, f"/api/coordinator/groups/{group.id}/", @@ -103,11 +99,11 @@ def test_delete_group_if_group_doesnt_exist(test_app_with_context) -> None: def test_edit_group(test_app_with_context) -> None: data = copy.copy(new_data) with test_app_with_context.test_client() as client: - yg = create_year_group() - students = create_students(yg, 3) - ps = create_project_supervisors(yg, 1)[0] - group = create_group(valid_data, yg) - data["students"] = [student.index for student in students] + yg = create_one_model(YearGroupFactory) + students = create_many_models(3, StudentFactory, year_group_id=yg.id) + ps = create_one_model(ProjectSupervisorFactory, year_group_id=yg.id) + group = create_one_model(GroupFactory, year_group_id=yg.id) + data["students"] = [student.id for student in students] data["project_supervisor_id"] = ps.id _test_case_client( @@ -124,10 +120,10 @@ def test_edit_group(test_app_with_context) -> None: def test_edit_group_with_invalid_project_supervisor_id(test_app_with_context) -> None: data = copy.copy(new_data) with test_app_with_context.test_client() as client: - yg = create_year_group() - students = create_students(yg, 3) - group = create_group(valid_data, yg) - data["students"] = [student.index for student in students] + yg = create_one_model(YearGroupFactory) + students = create_many_models(3, StudentFactory, year_group_id=yg.id) + group = create_one_model(GroupFactory, year_group_id=yg.id) + data["students"] = [student.id for student in students] data["project_supervisor_id"] = 10 _test_case_client( client, @@ -142,25 +138,27 @@ def test_edit_group_with_invalid_project_supervisor_id(test_app_with_context) -> def test_edit_group_with_invalid_data(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - yg = create_year_group() - group = create_group(valid_data, yg) - data = {"students": [123_4356, 243_533, 434_343]} - _test_case_client( + data = {"students": ["23", "hello", 3]} + response_data = _test_case_client( client, - f"/api/coordinator/groups/{group.id}/", + f"/api/coordinator/groups/3/", data, "Validation error", 400, method="put", ) + assert ( + response_data["detail"]["json"]["students"]["1"][0] + == "Not a valid integer." + ) -def test_edit_group_with_invalid_student_indexes(test_app_with_context) -> None: +def test_edit_group_with_invalid_student_ids(test_app_with_context) -> None: data = copy.deepcopy(new_data) with test_app_with_context.test_client() as client: - yg = create_year_group() - group = create_group(valid_data, yg) - data["students"] = [123_456, 243_533, 434_343] + yg = create_one_model(YearGroupFactory) + group = create_one_model(GroupFactory, year_group_id=yg.id) + data["students"] = [2, 6, 4] _test_case_client( client, f"/api/coordinator/groups/{group.id}/", @@ -201,10 +199,10 @@ def test_edit_group_if_you_pass_empty_data(test_app_with_context) -> None: def test_create_group(test_app_with_context) -> None: data = copy.deepcopy(new_data) with test_app_with_context.test_client() as client: - yg = create_year_group() - students = create_students(yg, 3) - ps = create_project_supervisors(yg, 1)[0] - data["students"] = [student.index for student in students] + yg = create_one_model(YearGroupFactory) + students = create_many_models(3, StudentFactory) + ps = create_one_model(ProjectSupervisorFactory) + data["students"] = [student.id for student in students] data["project_supervisor_id"] = ps.id _test_case_client( @@ -234,7 +232,7 @@ def test_create_group_if_year_group_doesnt_exist(test_app_with_context) -> None: def test_create_group_if_project_supervisor_doesnt_exist(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - yg = create_year_group() + yg = create_one_model(YearGroupFactory) _test_case_client( client, f"/api/coordinator/groups/{yg.id}/", @@ -246,33 +244,11 @@ def test_create_group_if_project_supervisor_doesnt_exist(test_app_with_context) ) -def test_create_group_if_you_exceed_the_group_limit(test_app_with_context) -> None: +def test_create_group_if_students_dont_exist(test_app_with_context) -> None: data = copy.deepcopy(invalid_data) with test_app_with_context.test_client() as client: - yg = create_year_group() - ps = create_project_supervisors(yg, 1)[0] - data["project_supervisor_id"] = ps.id - limit_group = current_app.config.get("LIMIT_STUDENTS_PER_GROUP") - - data["students"].extend([999_000 + i for i in range(limit_group + 4)]) - - _test_case_client( - client, - f"/api/coordinator/groups/{yg.id}/", - data, - f"Too much students you want add to group, The group can have only {limit_group}" - " students", - 400, - method="post", - key="error", - ) - - -def test_create_group_if_students_doesnt_exist(test_app_with_context) -> None: - data = copy.deepcopy(invalid_data) - with test_app_with_context.test_client() as client: - yg = create_year_group() - ps = create_project_supervisors(yg, 1)[0] + yg = create_one_model(YearGroupFactory) + ps = create_one_model(ProjectSupervisorFactory, year_group_id=yg.id) data["project_supervisor_id"] = ps.id _test_case_client( client, @@ -290,15 +266,15 @@ def test_create_group_if_at_least_one_student_belong_to_other_group( ) -> None: data = copy.deepcopy(invalid_data) with test_app_with_context.test_client() as client: - yg = create_year_group() - ps = create_project_supervisors(yg, 1)[0] - group = create_group(valid_data, yg) + yg = create_one_model(YearGroupFactory) + ps = create_one_model(ProjectSupervisorFactory, year_group_id=yg.id) + group = create_one_model(GroupFactory, year_group_id=yg.id) data["project_supervisor_id"] = ps.id - student = create_students(yg, 1)[0] + student = create_one_model(StudentFactory, year_group_id=yg.id) group.students.append(student) db.session.commit() - data["students"].extend([student.index]) + data["students"].extend([student.id]) _test_case_client( client, f"/api/coordinator/groups/{yg.id}/", @@ -308,33 +284,3 @@ def test_create_group_if_at_least_one_student_belong_to_other_group( method="post", key="error", ) - - -def test_create_group_if_limit_of_group_was_exceed_for_project_supervisor( - test_app_with_context, -) -> None: - data = copy.deepcopy(invalid_data) - with test_app_with_context.test_client() as client: - yg = create_year_group() - ps = create_project_supervisors(yg, 1)[0] - data["project_supervisor_id"] = ps.id - - ygps = YearGroupProjectSupervisors.query.filter_by( - project_supervisor_id=ps.id, year_group_id=yg.id - ).first() - limit_group = ygps.limit_group - - groups = create_groups(yg, limit_group) - for group in groups: - group.project_supervisor_id = ps.id - db.session.commit() - - _test_case_client( - client, - f"/api/coordinator/groups/{yg.id}/", - data, - "Can't create new group, project supervisor achieved a limit of groups", - 400, - method="post", - key="error", - ) diff --git a/backend/tests/functional_tests/coordinator/test_project_supervisors.py b/backend/tests/functional_tests/coordinator/test_project_supervisors.py index 14dfdbe..7e154e5 100644 --- a/backend/tests/functional_tests/coordinator/test_project_supervisors.py +++ b/backend/tests/functional_tests/coordinator/test_project_supervisors.py @@ -1,48 +1,27 @@ -from app.dependencies import db -from app.project_supervisor.models import YearGroupProjectSupervisors +from app.project_supervisor.models import ProjectSupervisor +from app.students.models import Group -from ...fake_data import ( - create_dummy_group, - create_dummy_ps, - create_project_supervisors, - create_year_group, -) +from ...factory import ProjectSupervisorFactory, YearGroupFactory from ...utils import ( _test_case_client, _test_case_client_without_response, assert_model_changes, + create_many_models, + create_one_model, ) valid_data = { "first_name": "John", "last_name": "Smith", "email": "johnsmith@gmail.com", + "limit_group": 5, } -year_group_ps_data = {"limit_group": 3} - def test_list_project_supervisors(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - year_group = create_year_group() - create_project_supervisors(year_group, 25) - data = _test_case_client_without_response( - client, - "/api/coordinator/project_supervisor/?per_page=10", - None, - 200, - method="get", - ) - assert data.get("max_pages") == 3 - assert len(data.get("project_supervisors")) == 10 - - -def test_list_project_supervisors_by_year_group(test_app_with_context) -> None: - with test_app_with_context.test_client() as client: - year_group = create_year_group() - year_group_2 = create_year_group() - create_project_supervisors(year_group, 12) - create_project_supervisors(year_group_2, 24) + year_group = create_one_model(YearGroupFactory) + create_many_models(12, ProjectSupervisorFactory, year_group_id=year_group.id) data = _test_case_client_without_response( client, f"/api/coordinator/project_supervisor/{year_group.id}/?per_page=10", @@ -56,37 +35,46 @@ def test_list_project_supervisors_by_year_group(test_app_with_context) -> None: def test_create_project_supervisors(test_app_with_context) -> None: with test_app_with_context.test_client() as client: + yg = create_one_model(YearGroupFactory) _test_case_client( client, - "/api/coordinator/project_supervisor/", + f"/api/coordinator/project_supervisor/{yg.id}/", valid_data, "Project Supervisor was created!", 201, method="post", ) + assert_model_changes(ProjectSupervisor.query.first(), valid_data) def test_create_project_supervisors_with_invalid_data(test_app_with_context) -> None: - data = {"first_name": "John", "last_name": "Smith", "email": "johnsmitl.com"} + data = { + "first_name": "John", + "last_name": "Smith", + "email": "johnsmitl.com", + "limit_group": 3, + } with test_app_with_context.test_client() as client: - _test_case_client( + message = _test_case_client( client, - "/api/coordinator/project_supervisor/", + "/api/coordinator/project_supervisor/3/", data, "Validation error", 400, method="post", ) + assert message["detail"]["json"]["email"][0] == "Not a valid email address." def test_create_project_supervisors_if_project_supervisor_has_already_exist( test_app_with_context, ) -> None: with test_app_with_context.test_client() as client: - create_dummy_ps(valid_data) + yg = create_one_model(YearGroupFactory) + create_one_model(ProjectSupervisor, valid_data, year_group_id=yg.id) _test_case_client( client, - "/api/coordinator/project_supervisor/", + f"/api/coordinator/project_supervisor/{yg.id}/", valid_data, "Project Supervisor has already exists!", 400, @@ -95,9 +83,24 @@ def test_create_project_supervisors_if_project_supervisor_has_already_exist( ) +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/project_supervisor/22/", + valid_data, + "Not found year group!", + 404, + method="post", + key="error", + ) + + def test_detail_project_supervisor(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - ps = create_dummy_ps(valid_data) + ps = create_one_model(ProjectSupervisorFactory) data = _test_case_client_without_response( client, f"/api/coordinator/project_supervisor/{ps.id}/detail/", @@ -125,7 +128,7 @@ def test_detail_project_supervisor_if_project_supervisor_doesnt_exist( def test_delete_project_supervisor(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - ps = create_dummy_ps(valid_data) + ps = create_one_model(ProjectSupervisorFactory) _test_case_client( client, f"/api/coordinator/project_supervisor/{ps.id}/", @@ -155,8 +158,8 @@ def test_delete_project_supervisor_if_project_supervisor_has_got_at_least_one_gr test_app_with_context, ) -> None: with test_app_with_context.test_client() as client: - ps = create_dummy_ps(valid_data) - create_dummy_group({"name": "new project"}, ps.id) + ps = create_one_model(ProjectSupervisorFactory) + create_one_model(Group, {"name": "new project"}, project_supervisor_id=ps.id) _test_case_client( client, f"/api/coordinator/project_supervisor/{ps.id}/", @@ -169,29 +172,39 @@ def test_delete_project_supervisor_if_project_supervisor_has_got_at_least_one_gr def test_edit_project_supervisor(test_app_with_context) -> None: - new_data = { - "first_name": "Albert", - "last_name": "Einstein", - "email": "albertmc2@gmail.com", - } with test_app_with_context.test_client() as client: - ps = create_dummy_ps(valid_data) + ps = create_one_model(ProjectSupervisorFactory) _test_case_client( client, f"/api/coordinator/project_supervisor/{ps.id}/", - new_data, + valid_data, "Project Supervisor was updated!", 200, method="put", ) - assert_model_changes(ps, new_data) + assert_model_changes(ps, valid_data) + + +def test_edit_project_supervisor_if_you_passed_empty_data( + test_app_with_context, +) -> None: + with test_app_with_context.test_client() as client: + _test_case_client( + client, + "/api/coordinator/project_supervisor/32/", + {}, + "You have passed empty data!", + 400, + method="put", + key="error", + ) def test_edit_project_supervisor_with_invalid_data(test_app_with_context) -> None: invalid_data = {"first_name": "Mark", "last_name": "Smith", "email": "invalidemail"} with test_app_with_context.test_client() as client: - ps = create_dummy_ps(valid_data) - _test_case_client( + ps = create_one_model(ProjectSupervisorFactory) + data = _test_case_client( client, f"/api/coordinator/project_supervisor/{ps.id}/", invalid_data, @@ -199,6 +212,7 @@ def test_edit_project_supervisor_with_invalid_data(test_app_with_context) -> Non 400, method="put", ) + assert data["detail"]["json"]["email"][0] == "Not a valid email address." def test_edit_project_supervisor_if_project_supervisor_doesnt_exist( @@ -214,172 +228,3 @@ def test_edit_project_supervisor_if_project_supervisor_doesnt_exist( method="put", key="error", ) - - -def test_add_project_supervisor_to_year_group(test_app_with_context) -> None: - with test_app_with_context.test_client() as client: - ps = create_dummy_ps(valid_data) - yg = create_year_group() - _test_case_client( - client, - f"/api/coordinator/project_supervisor/{ps.id}/year-group/{yg.id}/", - year_group_ps_data, - "Project Supervisor was added to year group!", - 201, - method="post", - ) - - -def test_add_project_supervisor_to_year_group_if_project_supervisor_doesnt_exist( - test_app_with_context, -) -> None: - with test_app_with_context.test_client() as client: - yg = create_year_group() - _test_case_client( - client, - f"/api/coordinator/project_supervisor/454/year-group/{yg.id}/", - year_group_ps_data, - "Not found project supervisor!", - 404, - method="post", - key="error", - ) - - -def test_add_project_supervisor_to_year_group_if_year_group_doesnt_exist( - test_app_with_context, -) -> None: - with test_app_with_context.test_client() as client: - ps = create_dummy_ps(valid_data) - _test_case_client( - client, - f"/api/coordinator/project_supervisor/{ps.id}/year-group/2/", - year_group_ps_data, - "Not found year group!", - 404, - method="post", - key="error", - ) - - -def test_add_project_supervisor_to_year_group_if_project_supervisor_has_already_assigned_to_year_group( - test_app_with_context, -) -> None: - with test_app_with_context.test_client() as client: - ps = create_dummy_ps(valid_data) - yg = create_year_group() - ygps = YearGroupProjectSupervisors( - project_supervisor_id=ps.id, year_group_id=yg.id, limit_group=2 - ) - db.session.add(ygps) - db.session.commit() - - _test_case_client( - client, - f"/api/coordinator/project_supervisor/{ps.id}/year-group/{yg.id}/", - year_group_ps_data, - "Project supervisor is assigned to this year group!", - 400, - method="post", - key="error", - ) - - -def test_delete_project_supervisor_to_year_group(test_app_with_context) -> None: - with test_app_with_context.test_client() as client: - ps = create_dummy_ps(valid_data) - yg = create_year_group() - _test_case_client( - client, - f"/api/coordinator/project_supervisor/{ps.id}/year-group/{yg.id}/", - None, - "Project Supervisor was removed from this year group!", - 200, - method="delete", - ) - assert len(YearGroupProjectSupervisors.query.all()) == 0 - - -def test_delete_project_supervisor_to_year_group_if_project_supervisor_doesnt_exist( - test_app_with_context, -) -> None: - with test_app_with_context.test_client() as client: - yg = create_year_group() - _test_case_client( - client, - f"/api/coordinator/project_supervisor/5/year-group/{yg.id}/", - None, - "Not found project supervisor!", - 404, - method="delete", - key="error", - ) - - -def test_delete_project_supervisor_to_year_group_if_year_group_doesnt_exist( - test_app_with_context, -) -> None: - with test_app_with_context.test_client() as client: - ps = create_dummy_ps(valid_data) - _test_case_client( - client, - f"/api/coordinator/project_supervisor/{ps.id}/year-group/23/", - None, - "Not found year group!", - 404, - method="delete", - key="error", - ) - - -def test_update_limit_of_group_for_project_supervisor(test_app_with_context) -> None: - with test_app_with_context.test_client() as client: - ps = create_dummy_ps(valid_data) - yg = create_year_group() - ygps = YearGroupProjectSupervisors( - project_supervisor_id=ps.id, year_group_id=yg.id, limit_group=6 - ) - db.session.add(ygps) - db.session.commit() - - _test_case_client( - client, - f"/api/coordinator/project_supervisor/{ps.id}/year-group/{yg.id}/", - year_group_ps_data, - "Limit of group was changed!", - 200, - method="put", - ) - assert_model_changes(ygps, year_group_ps_data) - - -def test_update_limit_of_group_for_project_supervisor_if_project_supervisor_doesnt_exist( - test_app_with_context, -) -> None: - with test_app_with_context.test_client() as client: - yg = create_year_group() - _test_case_client( - client, - f"/api/coordinator/project_supervisor/34/year-group/{yg.id}/", - year_group_ps_data, - "Not found project supervisor!", - 404, - method="put", - key="error", - ) - - -def test_update_limit_of_group_for_project_supervisor_if_year_group_doesnt_exist( - test_app_with_context, -) -> None: - with test_app_with_context.test_client() as client: - ps = create_dummy_ps(valid_data) - _test_case_client( - client, - f"/api/coordinator/project_supervisor/{ps.id}/year-group/34/", - year_group_ps_data, - "Not found year group!", - 404, - method="put", - key="error", - ) diff --git a/backend/tests/functional_tests/coordinator/test_students.py b/backend/tests/functional_tests/coordinator/test_students.py index f20b834..a7ddbe2 100644 --- a/backend/tests/functional_tests/coordinator/test_students.py +++ b/backend/tests/functional_tests/coordinator/test_students.py @@ -1,33 +1,29 @@ import copy -from ...fake_data import create_student, create_students, create_year_group +from app.students.models import Student, YearGroup + +from ...factory import StudentFactory, YearGroupFactory from ...utils import ( _test_case_client, _test_case_client_without_response, assert_model_changes, + create_many_models, + create_one_model, ) -valid_data = { - "first_name": "Albert", - "last_name": "Rose", - "index": 234_343, - "email": "albert@gmail.com", -} - -new_data = {"first_name": "Martin", "last_name": "Green", "pesel": "93030312894"} +new_data = {"first_name": "Martin", "last_name": "Green"} data_to_create_student = { "first_name": "Albert", "last_name": "Marcus", - "pesel": "93030312896", "index": 123_456, } def test_list_students(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - yg = create_year_group() - create_students(yg, 45) + yg = create_one_model(YearGroupFactory) + create_many_models(45, StudentFactory, year_group_id=yg.id) data = _test_case_client_without_response( client, f"/api/coordinator/students/{yg.id}/?per_page=10", @@ -41,11 +37,10 @@ def test_list_students(test_app_with_context) -> None: def test_detail_student(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - yg = create_year_group() - st = create_student(valid_data, yg.id) + st = create_one_model(StudentFactory) data = _test_case_client_without_response( client, - f"/api/coordinator/students/{st.index}/detail/", + f"/api/coordinator/students/{st.id}/detail/", None, 200, method="get", @@ -68,16 +63,16 @@ def test_detail_student_if_student_doesnt_exist(test_app_with_context) -> None: def test_delete_student(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - yg = create_year_group() - st = create_student(valid_data, yg.id) + st = create_one_model(StudentFactory) _test_case_client( client, - f"/api/coordinator/students/{st.index}/", + f"/api/coordinator/students/{st.id}/", None, "Student was deleted!", 202, method="delete", ) + assert len(Student.query.all()) == 0 def test_delete_student_if_student_doesnt_exist(test_app_with_context) -> None: @@ -95,11 +90,10 @@ def test_delete_student_if_student_doesnt_exist(test_app_with_context) -> None: def test_edit_student(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - yg = create_year_group() - st = create_student(valid_data, yg.id) + st = create_one_model(StudentFactory) _test_case_client( client, - f"/api/coordinator/students/{st.index}/", + f"/api/coordinator/students/{st.id}/", new_data, "Student was updated!", 200, @@ -109,13 +103,12 @@ def test_edit_student(test_app_with_context) -> None: def test_edit_student_with_invalid_data(test_app_with_context) -> None: data = copy.copy(new_data) - data["pesel"] = "43333333333433443" + data["index"] = 3_232_323 with test_app_with_context.test_client() as client: - yg = create_year_group() - st = create_student(valid_data, yg.id) + st = create_one_model(StudentFactory) _test_case_client( client, - f"/api/coordinator/students/{st.index}/", + f"/api/coordinator/students/{st.id}/", data, "Validation error", 400, @@ -139,7 +132,7 @@ def test_edit_student_if_student_doesnt_exist(test_app_with_context) -> None: def test_create_student(test_app_with_context) -> None: data = copy.copy(data_to_create_student) with test_app_with_context.test_client() as client: - yg = create_year_group() + yg = create_one_model(YearGroupFactory) data["year_group_id"] = yg.id _test_case_client( client, @@ -153,9 +146,9 @@ def test_create_student(test_app_with_context) -> None: def test_create_student_with_invalid_data(test_app_with_context) -> None: data = copy.copy(data_to_create_student) - data["pesel"] = "434343434343344" + data["index"] = 1_123_432 with test_app_with_context.test_client() as client: - yg = create_year_group() + yg = create_one_model(YearGroupFactory) data["year_group_id"] = yg.id _test_case_client( client, @@ -182,19 +175,19 @@ def test_create_student_if_year_group_doesnt_exist(test_app_with_context) -> Non ) -def test_create_student_if_student_has_already_assigned_to_this_group( +def test_create_student_if_student_has_already_assigned_to_this_year_group( test_app_with_context, ) -> None: data = copy.copy(data_to_create_student) with test_app_with_context.test_client() as client: - yg = create_year_group() - create_student(data, yg.id) + yg = create_one_model(YearGroupFactory) + create_one_model(Student, data, year_group_id=yg.id, email="tmp@gmail.com") data["year_group_id"] = yg.id _test_case_client( client, "/api/coordinator/students/", data, - "You are assigned to this year group!", + "Student has already assigned to this year group!", 400, method="post", key="error", diff --git a/backend/tests/functional_tests/coordinator/test_year_group.py b/backend/tests/functional_tests/coordinator/test_year_group.py index fe02d0c..965637e 100644 --- a/backend/tests/functional_tests/coordinator/test_year_group.py +++ b/backend/tests/functional_tests/coordinator/test_year_group.py @@ -1,24 +1,25 @@ from app.base.mode import ModeGroups +from app.students.models import YearGroup -from ...fake_data import create_year_group from ...utils import ( _test_case_client, _test_case_client_without_response, assert_model_changes, + create_one_model, ) -valid_data = {"mode": ModeGroups.STATIONARY.value, "name": "2022/2023"} +year_group_valid_data_1 = {"mode": ModeGroups.STATIONARY.value, "name": "2022/2023"} -new_data = {"mode": ModeGroups.NON_STATIONARY.value, "name": "2021/2022"} +year_group_valid_data_2 = {"mode": ModeGroups.NON_STATIONARY.value, "name": "2021/2022"} -example_data = {"mode": ModeGroups.STATIONARY.value, "name": "2021/2022"} +year_group_valid_data_3 = {"mode": ModeGroups.STATIONARY.value, "name": "2021/2022"} def test_create_year_group(test_client) -> None: _test_case_client( test_client, "/api/coordinator/year-group/", - valid_data, + year_group_valid_data_1, "Year group was created!", 201, ) @@ -40,11 +41,11 @@ def test_create_year_group_with_invalid_mode(test_client) -> None: def test_create_year_group_if_year_group_already_exists(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - create_year_group(valid_data) + create_one_model(YearGroup, year_group_valid_data_1) _test_case_client( client, "/api/coordinator/year-group/", - valid_data, + year_group_valid_data_1, "Year group has already exists!", 400, "error", @@ -53,7 +54,7 @@ def test_create_year_group_if_year_group_already_exists(test_app_with_context) - def test_delete_year_group(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - yg = create_year_group(valid_data) + yg = create_one_model(YearGroup, year_group_valid_data_1) _test_case_client( client, f"/api/coordinator/year-group/{yg.id}/", @@ -79,22 +80,22 @@ def test_delete_year_group_if_year_group_not_exists(test_app_with_context) -> No def test_update_year_group(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - yg = create_year_group(valid_data) + yg = create_one_model(YearGroup, year_group_valid_data_1) _test_case_client( client, f"/api/coordinator/year-group/{yg.id}/", - new_data, + year_group_valid_data_2, "Year group was updated!", 200, method="put", key="message", ) - assert_model_changes(yg, new_data) + assert_model_changes(yg, year_group_valid_data_2) def test_update_year_group_with_invalid_data(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - yg = create_year_group(valid_data) + yg = create_one_model(YearGroup, year_group_valid_data_1) _test_case_client( client, f"/api/coordinator/year-group/{yg.id}/", @@ -104,7 +105,7 @@ def test_update_year_group_with_invalid_data(test_app_with_context) -> None: method="put", key="message", ) - assert_model_changes(yg, valid_data) + assert_model_changes(yg, year_group_valid_data_1) def test_update_year_group_with_invalid_route_param_year_group_id( @@ -114,7 +115,7 @@ def test_update_year_group_with_invalid_route_param_year_group_id( _test_case_client( client, f"/api/coordinator/year-group/23/", - new_data, + year_group_valid_data_2, "Not found year group!", 404, method="put", @@ -126,23 +127,30 @@ def test_update_year_group_with_valid_data_and_year_group_which_has_already_exis test_app_with_context, ) -> None: with test_app_with_context.test_client() as client: - create_year_group(new_data) - yg = create_year_group(valid_data) + create_one_model(YearGroup, year_group_valid_data_2) + yg = create_one_model(YearGroup, year_group_valid_data_1) _test_case_client( client, f"/api/coordinator/year-group/{yg.id}/", - new_data, + year_group_valid_data_2, "Year group has already exists!", 400, method="put", key="error", ) - assert_model_changes(yg, valid_data) + assert_model_changes(yg, year_group_valid_data_1) def test_list_year_group(test_app_with_context) -> None: with test_app_with_context.test_client() as client: - ygs = [create_year_group(data) for data in (valid_data, new_data, example_data)] + ygs = [ + create_one_model(YearGroup, data) + for data in ( + year_group_valid_data_1, + year_group_valid_data_2, + year_group_valid_data_3, + ) + ] data = _test_case_client_without_response( client, "/api/coordinator/year-group/", None, 200, method="get" ) diff --git a/backend/tests/functional_tests/project_supervisors/enrollments.py b/backend/tests/functional_tests/project_supervisors/enrollments.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/tests/utils.py b/backend/tests/utils.py index 78b831a..5150c83 100644 --- a/backend/tests/utils.py +++ b/backend/tests/utils.py @@ -1,6 +1,7 @@ import datetime -from typing import Union +from typing import List, Type, Union +from factory.alchemy import SQLAlchemyModelFactory from flask.testing import FlaskClient from app.dependencies import db @@ -27,7 +28,7 @@ def _test_case_client_without_response( response = method_func(url, json=data) else: response = method_func(url) - + # raise Exception(response.status_code, response.json) assert response.status_code == status_code return response.json @@ -40,12 +41,13 @@ def _test_case_client( status_code: int, key: str = "message", method: str = "post", -) -> None: +) -> dict: response_data = _test_case_client_without_response( test_client, url, data, status_code, method ) assert key in response_data.keys() assert response_data.get(key) == message + return response_data def _test_case_group(group: Group, data: dict) -> None: @@ -53,4 +55,27 @@ def _test_case_group(group: Group, data: dict) -> None: assert group.project_supervisor_id == data["project_supervisor_id"] for st in group.students: - assert st.index in data["students"] + assert st.id in data["students"] + + +def create_many_models( + amount: int, factory: Type[SQLAlchemyModelFactory], **kwargs +) -> List[SQLAlchemyModelFactory]: + models = [factory(**kwargs) for _ in range(amount)] + db.session.add_all(models) + db.session.commit() + return models + + +def create_one_model( + model: Union[Type[db.Model], Type[SQLAlchemyModelFactory]], + data: dict = None, + **kwargs +) -> Union[db.Model, SQLAlchemyModelFactory]: + if issubclass(model, SQLAlchemyModelFactory): + m = model(**kwargs) # it's a factory + else: + m = model(**data, **kwargs) + db.session.add(m) + db.session.commit() + return m