From 9fe21448275453e53226f78bc0ff2fc70700326a Mon Sep 17 00:00:00 2001 From: Jipson Murillo Date: Tue, 30 Nov 2021 14:22:53 -0500 Subject: [PATCH] test: TT-414 add test to get latest projects --- .../api/azure/project_azure_endpoints_test.py | 37 ++++++++++++++++++ .../azure/time_entry_azure_endpoints_test.py | 38 +++++-------------- V2/tests/conftest.py | 2 +- V2/tests/fixtures.py | 20 ++++++++++ .../integration/daos/projects_dao_test.py | 12 ++++++ .../integration/daos/time_entries_dao_test.py | 36 +++--------------- .../unit/services/project_service_test.py | 15 ++++++++ .../unit/services/time_entry_service_test.py | 15 -------- .../unit/use_cases/projects_use_case_test.py | 13 +++++++ .../use_cases/time_entries_use_case_test.py | 13 ------- .../_projects/_get_latest_projects.py | 2 +- .../_data_persistence/_projects_dao.py | 30 ++++----------- .../_domain/_services/_time_entry.py | 4 -- .../_time_entries_sql_dao.py | 14 ------- 14 files changed, 123 insertions(+), 128 deletions(-) diff --git a/V2/tests/api/azure/project_azure_endpoints_test.py b/V2/tests/api/azure/project_azure_endpoints_test.py index 1976944a..b48a13dc 100644 --- a/V2/tests/api/azure/project_azure_endpoints_test.py +++ b/V2/tests/api/azure/project_azure_endpoints_test.py @@ -232,3 +232,40 @@ def test__project_azure_endpoint__returns_a_status_code_500__when_project_receiv assert response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR assert response.get_body() == b"could not be created" + + +def test__get_latest_projects_azure_endpoint__returns_a_list_of_latest_projects__when_an_owner_id_match( + insert_time_entry +): + inserted_time_entry = insert_time_entry().__dict__ + + req = func.HttpRequest( + method='GET', + body=None, + url=PROJECT_URL+"latest/", + params={"owner_id": inserted_time_entry["owner_id"]}, + ) + + response = azure_projects._get_latest_projects.get_latest_projects(req) + projects_json_data = json.loads(response.get_body().decode("utf-8")) + + assert response.status_code == HTTPStatus.OK + assert inserted_time_entry["project_id"] == projects_json_data[0]["id"] + + +def test__get_latest_projects_azure_endpoint__returns_an_empty_list__when_an_owner_id_not_match( + insert_time_entry +): + insert_time_entry().__dict__ + + req = func.HttpRequest( + method='GET', + body=None, + url=PROJECT_URL+"latest/", + ) + + response = azure_projects._get_latest_projects.get_latest_projects(req) + projects_json_data = json.loads(response.get_body().decode("utf-8")) + + assert response.status_code == HTTPStatus.OK + assert projects_json_data == [] diff --git a/V2/tests/api/azure/time_entry_azure_endpoints_test.py b/V2/tests/api/azure/time_entry_azure_endpoints_test.py index d1168e49..13e3e875 100644 --- a/V2/tests/api/azure/time_entry_azure_endpoints_test.py +++ b/V2/tests/api/azure/time_entry_azure_endpoints_test.py @@ -83,10 +83,11 @@ def test__delete_time_entries_azure_endpoint__returns_a_status_code_400__when_ti def test__time_entry_azure_endpoint__returns_all_time_entries( - test_db, time_entry_factory, insert_time_entry, activity_factory, insert_activity + test_db, time_entry_factory, insert_time_entry, activity_factory, insert_activity, insert_project ): + inserted_project = insert_project() inserted_activity = insert_activity(activity_factory(), test_db) - time_entries_to_insert = time_entry_factory(activity_id=inserted_activity.id) + time_entries_to_insert = time_entry_factory(activity_id=inserted_activity.id, project_id=inserted_project.id) inserted_time_entries = insert_time_entry(time_entries_to_insert, test_db).__dict__ req = func.HttpRequest(method="GET", body=None, url=TIME_ENTRY_URL) @@ -100,10 +101,11 @@ def test__time_entry_azure_endpoint__returns_all_time_entries( def test__time_entry_azure_endpoint__returns_an_time_entry__when_time_entry_matches_its_id( - test_db, time_entry_factory, insert_time_entry, activity_factory, insert_activity + test_db, time_entry_factory, insert_time_entry, activity_factory, insert_activity, insert_project ): + inserted_project = insert_project() inserted_activity = insert_activity(activity_factory(), test_db) - time_entries_to_insert = time_entry_factory(activity_id=inserted_activity.id) + time_entries_to_insert = time_entry_factory(activity_id=inserted_activity.id, project_id=inserted_project.id) inserted_time_entries = insert_time_entry(time_entries_to_insert, test_db).__dict__ req = func.HttpRequest( @@ -121,10 +123,11 @@ def test__time_entry_azure_endpoint__returns_an_time_entry__when_time_entry_matc def test__get_time_entries_azure_endpoint__returns_a_status_code_400__when_time_entry_recive_invalid_id( - test_db, time_entry_factory, insert_time_entry, activity_factory, insert_activity + test_db, time_entry_factory, insert_time_entry, activity_factory, insert_activity, insert_project ): + inserted_project = insert_project() inserted_activity = insert_activity(activity_factory(), test_db) - time_entries_to_insert = time_entry_factory(activity_id=inserted_activity.id) + time_entries_to_insert = time_entry_factory(activity_id=inserted_activity.id, project_id=inserted_project.id) insert_time_entry(time_entries_to_insert, test_db).__dict__ req = func.HttpRequest( @@ -177,7 +180,7 @@ def test__get_latest_entries_azure_endpoint__returns_no_time_entries_found__when response = azure_time_entries._get_latest_entries.get_latest_entries(req) assert response.status_code == 404 - assert response.get_body() == b'No time entries found' + assert response.get_body() == b'Not found' def test__update_time_entry_azure_endpoint__returns_an_time_entry__when_found_an_time_entry_to_update( @@ -253,27 +256,6 @@ def test__update_time_entries_azure_endpoint__returns_a_status_code_400__when_ti assert response.get_body() == b'Incorrect time entry body' -def test__get_latest_entries_azure_endpoint__returns_a_list_of_latest_time_entries__when_an_owner_id_match( - test_db, time_entry_factory, insert_time_entry, insert_activity, activity_factory, -): - inserted_activity = insert_activity(activity_factory(), test_db).__dict__ - time_entry_body = time_entry_factory(activity_id=inserted_activity["id"], technologies="[jira,sql]") - inserted_time_entry = insert_time_entry(time_entry_body, test_db).__dict__ - - req = func.HttpRequest( - method='GET', - body=None, - url=TIME_ENTRY_URL+"latest/", - params={"owner_id": inserted_time_entry["owner_id"]}, - ) - - response = azure_time_entries._get_latest_entries.get_latest_entries(req) - time_entry_json_data = json.loads(response.get_body().decode("utf-8")) - - assert response.status_code == HTTPStatus.OK - assert time_entry_json_data == [inserted_time_entry] - - def test__get_latest_entries_azure_endpoint__returns_not_found__when_recieve_an_invalid_owner_id( test_db, insert_activity, activity_factory, ): diff --git a/V2/tests/conftest.py b/V2/tests/conftest.py index b443b0ab..c11fc951 100644 --- a/V2/tests/conftest.py +++ b/V2/tests/conftest.py @@ -1,5 +1,5 @@ # flake8: noqa from fixtures import _activity_factory, _test_db, _insert_activity -from fixtures import _time_entry_factory +from fixtures import _time_entry_factory, _insert_time_entry from fixtures import _customer_factory, _insert_customer from fixtures import _project_factory, _insert_project diff --git a/V2/tests/fixtures.py b/V2/tests/fixtures.py index 1e851b16..82391ebf 100644 --- a/V2/tests/fixtures.py +++ b/V2/tests/fixtures.py @@ -3,6 +3,7 @@ import time_tracker.activities._domain as activities_domain import time_tracker.time_entries._domain as time_entries_domain +import time_tracker.time_entries._infrastructure as time_entries_infrastructure import time_tracker.customers._domain as customers_domain import time_tracker.activities._infrastructure as activities_infrastructure import time_tracker.customers._infrastructure as customers_infrastructure @@ -146,3 +147,22 @@ def _new_project(): inserted_project = dao.create(project_to_insert) return inserted_project return _new_project + + +@pytest.fixture(name='insert_time_entry') +def _insert_time_entry( + test_db, insert_project, activity_factory, insert_activity, time_entry_factory +) -> time_entries_domain.TimeEntry: + + inserted_project = insert_project() + inserted_activity = insert_activity(activity_factory(), test_db) + + def _new_time_entry(owner_id: int = Faker().pyint()): + dao = time_entries_infrastructure.TimeEntriesSQLDao(test_db) + time_entries_to_insert = time_entry_factory( + activity_id=inserted_activity.id, project_id=inserted_project.id, owner_id=owner_id + ) + + inserted_time_entries = dao.create(time_entries_to_insert) + return inserted_time_entries + return _new_time_entry diff --git a/V2/tests/integration/daos/projects_dao_test.py b/V2/tests/integration/daos/projects_dao_test.py index fb67b41a..01f5a1a3 100644 --- a/V2/tests/integration/daos/projects_dao_test.py +++ b/V2/tests/integration/daos/projects_dao_test.py @@ -139,3 +139,15 @@ def test_delete__returns_none__when_no_project_matching_its_id_is_found_with_sql results = dao.delete(project_to_insert.id) assert results is None + + +def test_get_latest_projects__returns_a_list_of_project_dto_objects__when_find_projects_in_the_latest_time_entries( + create_fake_dao, insert_time_entry +): + dao = create_fake_dao + owner_id = Faker().pyint() + inserted_time_entries = insert_time_entry(owner_id) + latest_projects = dao.get_latest(owner_id) + + assert isinstance(latest_projects, typing.List) + assert latest_projects[0].id == inserted_time_entries.project_id diff --git a/V2/tests/integration/daos/time_entries_dao_test.py b/V2/tests/integration/daos/time_entries_dao_test.py index 3cb17417..3c17f7e9 100644 --- a/V2/tests/integration/daos/time_entries_dao_test.py +++ b/V2/tests/integration/daos/time_entries_dao_test.py @@ -88,17 +88,6 @@ def test_get_latest_entries__returns_a_list_of_latest_time_entries__when_an_owne assert result == [inserted_time_entry] -def test_get_latest_entries__returns_none__when_an_owner_id_is_not_found( - create_fake_dao, test_db, insert_activity, activity_factory -): - dao = create_fake_dao(test_db) - insert_activity(activity_factory(), dao.db) - - result = dao.get_latest_entries(Faker().pyint()) - - assert result is None - - def test_update__returns_an_time_entry_dto__when_found_one_time_entry_to_update( test_db, create_fake_dao, time_entry_factory, insert_activity, activity_factory, insert_project ): @@ -132,12 +121,13 @@ def test_update__returns_none__when_doesnt_found_one_time_entry_to_update( def test__get_all__returns_a_list_of_time_entries_dto_objects__when_one_or_more_time_entries_are_found_in_sql_database( - test_db, create_fake_dao, time_entry_factory, insert_activity, activity_factory + test_db, create_fake_dao, time_entry_factory, insert_activity, activity_factory, insert_project ): dao = create_fake_dao(test_db) + inserted_project = insert_project() inserted_activity = insert_activity(activity_factory(), dao.db) - time_entries_to_insert = time_entry_factory(activity_id=inserted_activity.id) + time_entries_to_insert = time_entry_factory(activity_id=inserted_activity.id, project_id=inserted_project.id) inserted_time_entries = [dao.create(time_entries_to_insert)] time_entry = dao.get_all() @@ -157,11 +147,12 @@ def test__get_all__returns_an_empty_list__when_doesnt_found_any_time_entries_in_ def test__get_by_id__returns_a_time_entry_dto__when_found_one_time_entry_that_match_id_with_sql_database( - test_db, create_fake_dao, time_entry_factory, insert_activity, activity_factory + test_db, create_fake_dao, time_entry_factory, insert_activity, activity_factory, insert_project ): dao = create_fake_dao(test_db) + inserted_project = insert_project() inserted_activity = insert_activity(activity_factory(), dao.db) - time_entries_to_insert = time_entry_factory(activity_id=inserted_activity.id) + time_entries_to_insert = time_entry_factory(activity_id=inserted_activity.id, project_id=inserted_project.id) inserted_time_entries = dao.create(time_entries_to_insert) time_entry = dao.get_by_id(time_entries_to_insert.id) @@ -184,21 +175,6 @@ def test__get_by_id__returns_none__when_no_time_entry_matches_by_id( assert time_entry is None -def test_get_latest_entries__returns_a_list_of_latest_time_entries__when_an_owner_id_match( - create_fake_dao, time_entry_factory, insert_activity, activity_factory, test_db -): - dao = create_fake_dao(test_db) - inserted_activity = insert_activity(activity_factory(), dao.db) - time_entry_to_insert = time_entry_factory( - activity_id=inserted_activity.id, - technologies="[jira,sql]") - inserted_time_entry = dao.create(time_entry_to_insert) - - result = dao.get_latest_entries(int(inserted_time_entry.owner_id)) - - assert result == [inserted_time_entry.__dict__] - - def test_get_latest_entries__returns_none__when_an_owner_id_is_not_found( create_fake_dao, test_db, insert_activity, activity_factory ): diff --git a/V2/tests/unit/services/project_service_test.py b/V2/tests/unit/services/project_service_test.py index 9baf657e..913bd40f 100644 --- a/V2/tests/unit/services/project_service_test.py +++ b/V2/tests/unit/services/project_service_test.py @@ -72,3 +72,18 @@ def test__create_project__uses_the_project_dao__to_create_an_project(mocker, pro assert project_dao.create.called assert expected_project == actual_project + + +def test__get_latest_projects__uses_the_project_dao__to_get_last_projects( + mocker, +): + expected_latest_projects = mocker.Mock() + project_dao = mocker.Mock( + get_latest=mocker.Mock(return_value=expected_latest_projects) + ) + + project_service = ProjectService(project_dao) + latest_projects = project_service.get_latest(Faker().pyint()) + + assert expected_latest_projects == latest_projects + assert project_dao.get_latest.called diff --git a/V2/tests/unit/services/time_entry_service_test.py b/V2/tests/unit/services/time_entry_service_test.py index 9d18b25b..d1596471 100644 --- a/V2/tests/unit/services/time_entry_service_test.py +++ b/V2/tests/unit/services/time_entry_service_test.py @@ -31,21 +31,6 @@ def test__delete_time_entry__uses_the_time_entry_dao__to_delete_time_entry_selec assert expected_time_entry == deleted_time_entry -def test__get_latest_entries__uses_the_time_entry_dao__to_get_last_entries( - mocker, -): - expected_latest_time_entries = mocker.Mock() - time_entry_dao = mocker.Mock( - get_latest_entries=mocker.Mock(return_value=expected_latest_time_entries) - ) - - time_entry_service = TimeEntryService(time_entry_dao) - latest_time_entries = time_entry_service.get_latest_entries(Faker().pyint(), Faker().pyint()) - - assert expected_latest_time_entries == latest_time_entries - assert time_entry_dao.get_latest_entries.called - - def test__update_time_entry__uses_the_time_entry_dao__to_update_one_time_entry( mocker, ): diff --git a/V2/tests/unit/use_cases/projects_use_case_test.py b/V2/tests/unit/use_cases/projects_use_case_test.py index 22167418..9f5d5f5c 100644 --- a/V2/tests/unit/use_cases/projects_use_case_test.py +++ b/V2/tests/unit/use_cases/projects_use_case_test.py @@ -78,3 +78,16 @@ def test__update_project_function__uses_the_projects_service__to_update_an_proje assert project_service.update.called assert expected_project == updated_project + + +def test__get_latest_projects_function__uses_the_project_service__to_get_latest_project( + mocker: MockFixture, +): + expected_latest_projects = mocker.Mock() + project_service = mocker.Mock(get_latest=mocker.Mock(return_value=expected_latest_projects)) + + project_use_case = _use_cases.GetLatestProjectsUseCase(project_service) + latest_projects = project_use_case.get_latest(Faker().pyint()) + + assert project_service.get_latest.called + assert expected_latest_projects == latest_projects diff --git a/V2/tests/unit/use_cases/time_entries_use_case_test.py b/V2/tests/unit/use_cases/time_entries_use_case_test.py index cda62314..f96666cb 100644 --- a/V2/tests/unit/use_cases/time_entries_use_case_test.py +++ b/V2/tests/unit/use_cases/time_entries_use_case_test.py @@ -34,19 +34,6 @@ def test__delete_time_entry_function__uses_the_time_entry_service__to_delete_tim assert expected_time_entry == deleted_time_entry -def test__get_latest_entries_function__uses_the_time_entry_service__to_get_last_entries( - mocker: MockFixture, -): - expected_latest_time_entries = mocker.Mock() - time_entry_service = mocker.Mock(get_latest_entries=mocker.Mock(return_value=expected_latest_time_entries)) - - time_entry_use_case = _use_cases.GetLastestTimeEntryUseCase(time_entry_service) - latest_time_entries = time_entry_use_case.get_latest_entries(Faker().pyint(), Faker().pyint()) - - assert time_entry_service.get_latest_entries.called - assert expected_latest_time_entries == latest_time_entries - - def test__update_time_entries_function__uses_the_time_entry_service__to_update_an_time_entry( mocker: MockFixture, ): diff --git a/V2/time_tracker/projects/_application/_projects/_get_latest_projects.py b/V2/time_tracker/projects/_application/_projects/_get_latest_projects.py index 5792670f..0aa9badc 100644 --- a/V2/time_tracker/projects/_application/_projects/_get_latest_projects.py +++ b/V2/time_tracker/projects/_application/_projects/_get_latest_projects.py @@ -13,7 +13,7 @@ def get_latest_projects(req: func.HttpRequest) -> func.HttpResponse: project_service = _domain.ProjectService(project_dao) use_case = _domain._use_cases.GetLatestProjectsUseCase(project_service) - owner_id = 2 + owner_id = req.params.get('owner_id') response = [ project.__dict__ for project in use_case.get_latest(owner_id) diff --git a/V2/time_tracker/projects/_infrastructure/_data_persistence/_projects_dao.py b/V2/time_tracker/projects/_infrastructure/_data_persistence/_projects_dao.py index 93280fbf..63e65972 100644 --- a/V2/time_tracker/projects/_infrastructure/_data_persistence/_projects_dao.py +++ b/V2/time_tracker/projects/_infrastructure/_data_persistence/_projects_dao.py @@ -44,41 +44,26 @@ def create(self, project_data: domain.Project) -> domain.Project: return None def get_by_id(self, id: int) -> domain.Project: - """ - query = sq.sql.text( - "SELECT project.*, json_array((customer.*)) AS customer FROM project " - "JOIN customer ON customer.id=project.customer_id " - "WHERE project.id=:id GROUP BY project.id " - ) - """ query = sq.sql.select(self.project).where(self.project.c.id == id) project = self.db.get_session().execute(query).one_or_none() if project: - customer_model = CustomersSQLDao(self.db).customer - query_customer = sq.sql.select(customer_model).where(customer_model.c.id == project["customer_id"]) - customer = self.db.get_session().execute(query_customer).one_or_none() + customer_dao = CustomersSQLDao(self.db) + customer = customer_dao.get_by_id(project["customer_id"]) project = dict(project) - project.update({"customer": dict(customer)if customer else None}) + project.update({"customer": customer.__dict__ if customer else None}) return self.__create_project_dto(project) if project else None def get_all(self) -> typing.List[domain.Project]: - """ - query = sq.sql.text( - "SELECT project.*, json_array((customer.*)) AS customer FROM project " - "JOIN customer ON customer.id=project.customer_id GROUP BY project.id" - ) - """ - customer_model = CustomersSQLDao(self.db).customer - query = sq.sql.select(self.project, customer_model).join(customer_model) + query = sq.sql.select(self.project) result = self.db.get_session().execute(query).all() projects = [] for project in result: - query_customer = sq.sql.select(customer_model).where(customer_model.c.id == project["customer_id"]) - customer = self.db.get_session().execute(query_customer).one_or_none() + customer_dao = CustomersSQLDao(self.db) + customer = customer_dao.get_by_id(project["customer_id"]) project = dict(project) - project.update({"customer": dict(customer)if customer else None}) + project.update({"customer": customer.__dict__ if customer else None}) projects.append(project) return [ @@ -107,6 +92,7 @@ def get_latest(self, owner_id: int) -> typing.List[domain.Project]: time_entries_dao = TimeEntriesSQLDao(self.db) latest_time_entries = time_entries_dao.get_latest_entries(owner_id) latest_projects = [] + if latest_time_entries: filter_project = typing.Counter(time_entry['project_id'] for time_entry in latest_time_entries) latest_projects = [self.get_by_id(project_id) for project_id in filter_project] diff --git a/V2/time_tracker/time_entries/_domain/_services/_time_entry.py b/V2/time_tracker/time_entries/_domain/_services/_time_entry.py index 0cdcde28..0c2b8b9b 100644 --- a/V2/time_tracker/time_entries/_domain/_services/_time_entry.py +++ b/V2/time_tracker/time_entries/_domain/_services/_time_entry.py @@ -1,7 +1,6 @@ import typing from time_tracker.time_entries._domain import TimeEntry, TimeEntriesDao -import typing class TimeEntryService: @@ -14,9 +13,6 @@ def create(self, time_entry_data: TimeEntry) -> TimeEntry: def delete(self, id: int) -> TimeEntry: return self.time_entry_dao.delete(id) - def get_latest_entries(self, owner_id: int, limit: int) -> typing.List[TimeEntry]: - return self.time_entry_dao.get_latest_entries(owner_id, limit) - def update(self, time_entry_id: int, new_time_entry: dict) -> TimeEntry: return self.time_entry_dao.update(time_entry_id, new_time_entry) diff --git a/V2/time_tracker/time_entries/_infrastructure/_data_persistence/_time_entries_sql_dao.py b/V2/time_tracker/time_entries/_infrastructure/_data_persistence/_time_entries_sql_dao.py index 8b6db8da..59988205 100644 --- a/V2/time_tracker/time_entries/_infrastructure/_data_persistence/_time_entries_sql_dao.py +++ b/V2/time_tracker/time_entries/_infrastructure/_data_persistence/_time_entries_sql_dao.py @@ -84,20 +84,6 @@ def delete(self, time_entry_id: int) -> domain.TimeEntry: time_entry = self.db.get_session().execute(query_deleted_time_entry).one_or_none() return self.__create_time_entry_dto(dict(time_entry)) if time_entry else None - def get_latest_entries(self, owner_id: int, limit: int = 20) -> typing.List[domain.TimeEntry]: - query = ( - self.time_entry.select() - .where(sqlalchemy.and_( - self.time_entry.c.owner_id == owner_id, - self.time_entry.c.deleted.is_(False) - )) - .order_by(self.time_entry.c.start_date.desc()) - .limit(limit) - ) - time_entries_data = self.db.get_session().execute(query) - list_time_entries = [dict(entry) for entry in time_entries_data] - return list_time_entries if len(list_time_entries) > 0 else None - def __create_time_entry_dto(self, time_entry: dict) -> domain.TimeEntry: time_entry.update({ "start_date": str(time_entry.get("start_date")),