import pytest from backend.model.student import Student from backend.model.tribe import Tribe from backend.repository.abstract_repository import AbstractRepository from backend.repository.student_sqlite_repository import StudentRepositoryError from backend.repository.tribe_sqlite_repository import TribeRepositoryError from backend.service import services from backend.service.services import ( StudentDoesExist, StudentExists, TribeDoesNotExist, TribeExists, ) from tests.model.fakes import build_student, build_tribes class FakeTribeRepository(AbstractRepository): def __init__(self, tribes: list[Tribe] = []) -> None: self._tribes = {t.name: t for t in tribes} def add(self, tribe: Tribe) -> None: if tribe.name not in self._tribes.keys(): self._tribes[tribe.name] = tribe else: raise TribeRepositoryError(f"{tribe} already exists") def update(self, name: str, tribe: Tribe) -> None: try: self._tribes.pop(name) self._tribes[tribe.name] = tribe except KeyError: raise TribeRepositoryError(f"The tribe {tribe} does not exists") def list(self) -> list[Tribe]: return list(self._tribes.values()) def get(self, name: str) -> Tribe: try: return self._tribes[name] except KeyError: raise TribeRepositoryError(f"The tribe {name} does not exists") def delete(self, name: str) -> None: try: self._tribes.pop(name) except KeyError: raise TribeRepositoryError(f"The tribe {name} does not exists") class FakeStudentRepository(AbstractRepository): def __init__(self, students: list[Student] = []) -> None: self._students = {s.id: s for s in students} def add(self, student: Student) -> None: if student.id not in self._students.keys(): self._students[student.id] = student else: raise StudentRepositoryError(f"{student} already exists") def update(self, student: Student) -> None: if student.id not in self._students.keys(): raise StudentRepositoryError(f"The student {student} does not exists") self._students[student.id] = student def list(self) -> list[Student]: return list(self._students.values()) def get(self, id: str) -> Student: try: return self._students[id] except KeyError: raise KeyError(f"The student ({id=}) does not exists") def delete(self, id: str) -> None: try: self._students.pop(id) except KeyError: raise StudentRepositoryError(f"The student {student} does not exists") class FakeConn: committed = False def commit(self): self.committed = True def reset_commit(self): self.committed = False def test_add_tribe(): tribe_repo = FakeTribeRepository() tribe = build_tribes(1)[0] conn = FakeConn() services.add_tribe( name=tribe.name, level=tribe.level, tribe_repo=tribe_repo, conn=conn ) assert conn.committed is True assert tribe_repo.list() == [tribe] def test_add_tribe_fail_exists(): tribe_repo = FakeTribeRepository() tribe = build_tribes(1)[0] conn = FakeConn() services.add_tribe( name=tribe.name, level=tribe.level, tribe_repo=tribe_repo, conn=conn ) conn.reset_commit() with pytest.raises(TribeExists): services.add_tribe( name=tribe.name, level=tribe.level, tribe_repo=tribe_repo, conn=conn ) assert conn.committed == False def test_update_tribe(): tribes = build_tribes(3) tribe_repo = FakeTribeRepository(tribes) conn = FakeConn() other_level = "iouiouiou" tribes[0].level = other_level services.update_tribe( name=tribes[0].name, level=other_level, tribe_repo=tribe_repo, conn=conn ) assert conn.committed is True assert set(tribe_repo.list()) == set(tribes) def test_update_tribe_fail_not_exists(): tribes = build_tribes(3) tribe_repo = FakeTribeRepository(tribes) conn = FakeConn() with pytest.raises(TribeDoesNotExist): services.update_tribe( name="azerty", level="jkl", tribe_repo=tribe_repo, conn=conn ) assert conn.committed == False def test_delete_tribe(): tribes = build_tribes(3) tribe_repo = FakeTribeRepository(tribes) conn = FakeConn() tribe = tribes.pop() services.delete_tribe(name=tribe.name, tribe_repo=tribe_repo, conn=conn) assert conn.committed is True assert set(tribe_repo.list()) == set(tribes) def test_delete_tribe_fail_not_exists(): tribes = build_tribes(3) tribe_repo = FakeTribeRepository(tribes) conn = FakeConn() with pytest.raises(TribeDoesNotExist): services.delete_tribe(name="azerty", tribe_repo=tribe_repo, conn=conn) assert conn.committed == False def test_add_student(): tribes = build_tribes(1) tribe_repo = FakeTribeRepository(tribes) student = build_student(tribes, 1)[0] student_repo = FakeStudentRepository() conn = FakeConn() saved_student = services.add_student( name=student.name, tribe=student.tribe.name, student_repo=student_repo, tribe_repo=tribe_repo, conn=conn, ) assert conn.committed is True listed_student = student_repo.list()[0] assert student.name == listed_student.name assert student.tribe.name == listed_student.tribe.name # The id is not passed to the service, they can't have the same. assert student.id != listed_student.id assert saved_student == listed_student def test_add_student_tribe_doesnt_exist(): tribes = build_tribes(1) tribe_repo = FakeTribeRepository(tribes) students = build_student(tribes, 1) student_repo = FakeStudentRepository() conn = FakeConn() student = students[0] with pytest.raises(TribeDoesNotExist): services.add_student( name=student.name, tribe="iuouiouiouio", student_repo=student_repo, tribe_repo=tribe_repo, conn=conn, ) assert conn.committed is False def test_update_student(): tribes = build_tribes(2) tribe_repo = FakeTribeRepository(tribes) students = build_student(tribes, 1) student_repo = FakeStudentRepository(students) conn = FakeConn() id = students[0].id new_name = "new name" new_tribe_name = tribes[1].name saved_student = services.update_student( id=id, name=new_name, tribe=new_tribe_name, student_repo=student_repo, tribe_repo=tribe_repo, conn=conn, ) assert conn.committed is True mod_student = student_repo.get(id) assert mod_student.name == new_name assert mod_student.tribe.name == new_tribe_name listed_student = student_repo.list() assert len(listed_student) == 2 def test_update_student_tribe_doesnt_exists(): tribes = build_tribes(2) tribe_repo = FakeTribeRepository(tribes) students = build_student(tribes, 1) student_repo = FakeStudentRepository(students) conn = FakeConn() id = students[0].id new_name = "new name" new_tribe_name = "not existing tribe" with pytest.raises(TribeDoesNotExist): services.update_student( id=id, name=new_name, tribe=new_tribe_name, student_repo=student_repo, tribe_repo=tribe_repo, conn=conn, ) assert conn.committed is False mod_student = student_repo.get(id) assert mod_student.name == students[0].name assert mod_student.tribe.name == students[0].tribe.name listed_student = student_repo.list() assert len(listed_student) == 2 def test_update_student_doesnt_exists(): tribes = build_tribes(2) tribe_repo = FakeTribeRepository(tribes) students = build_student(tribes, 1) student_repo = FakeStudentRepository(students) conn = FakeConn() id = "not existing id" new_name = students[0].name new_tribe_name = students[0].tribe.name with pytest.raises(StudentDoesExist): services.update_student( id=id, name=new_name, tribe=new_tribe_name, student_repo=student_repo, tribe_repo=tribe_repo, conn=conn, ) assert conn.committed is False original_student = student_repo.get(students[0].id) assert original_student.name == students[0].name assert original_student.tribe.name == students[0].tribe.name listed_student = student_repo.list() assert len(listed_student) == 2