Skip to content

Commit 811d271

Browse files
committed
feat: TT-404 get time entries
1 parent 60a0dc7 commit 811d271

File tree

23 files changed

+368
-25
lines changed

23 files changed

+368
-25
lines changed

V2/serverless.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ functions:
6363
- http: true
6464
x-azure-settings:
6565
methods:
66-
- PUT
66+
- PUT
6767
route: activities/{id}
68-
authLevel: anonymous
68+
authLevel: anonymous
6969

7070
create_activity:
7171
handler: time_tracker/activities/interface.create_activity
@@ -87,6 +87,16 @@ functions:
8787
route: time-entries/
8888
authLevel: anonymous
8989

90+
get_time_entries:
91+
handler: time_tracker/time_entries/interface.get_time_entries
92+
events:
93+
- http: true
94+
x-azure-settings:
95+
methods:
96+
- GET
97+
route: time_entries/{id:?}
98+
authLevel: anonymous
99+
90100
delete_time_entry:
91101
handler: time_tracker/time_entries/interface.delete_time_entry
92102
events:

V2/tests/api/azure/time_entry_azure_endpoints_test.py

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pytest
22
import json
3+
import pytest
34

45
import azure.functions as func
56

@@ -9,7 +10,7 @@
910
from time_tracker.time_entries import _infrastructure as infrastructure_time_entries
1011

1112

12-
TIME_ENTRY_URL = "/api/time-entries/"
13+
TIME_ENTRY_URL = "/api/time_entries/"
1314

1415

1516
@pytest.fixture(name='insert_time_entry')
@@ -76,3 +77,65 @@ def test__delete_time_entries_azure_endpoint__returns_a_status_code_400__when_ti
7677

7778
assert response.status_code == 400
7879
assert response.get_body() == b'Invalid Format ID'
80+
81+
82+
def test__time_entry_azure_endpoint__returns_all_time_entries(
83+
create_fake_database, time_entry_factory, insert_time_entry, activity_factory, insert_activity
84+
):
85+
fake_database = create_fake_database
86+
inserted_activity = insert_activity(activity_factory(), fake_database)
87+
existent_time_entries = time_entry_factory(activity_id=inserted_activity.id, technologies="[jira,sql]")
88+
inserted_time_entries = [insert_time_entry(existent_time_entries, fake_database)]
89+
90+
azure_time_entries._get_time_entries.DATABASE = fake_database
91+
req = func.HttpRequest(method="GET", body=None, url=TIME_ENTRY_URL)
92+
93+
response = azure_time_entries.get_time_entries(req)
94+
time_entries_json_data = response.get_body().decode("utf-8")
95+
96+
assert response.status_code == 200
97+
assert time_entries_json_data == json.dumps(inserted_time_entries)
98+
99+
100+
def test__time_entry_azure_endpoint__returns_an_time_entry__when_time_entry_matches_its_id(
101+
create_fake_database, time_entry_factory, insert_time_entry, activity_factory, insert_activity
102+
):
103+
fake_database = create_fake_database
104+
inserted_activity = insert_activity(activity_factory(), fake_database)
105+
existent_time_entries = time_entry_factory(activity_id=inserted_activity.id, technologies="[jira,sql]")
106+
inserted_time_entries = insert_time_entry(existent_time_entries, fake_database)
107+
108+
azure_time_entries._get_time_entries.DATABASE = fake_database
109+
110+
req = func.HttpRequest(
111+
method="GET",
112+
body=None,
113+
url=TIME_ENTRY_URL,
114+
route_params={"id": inserted_time_entries["id"]},
115+
)
116+
117+
response = azure_time_entries.get_time_entries(req)
118+
time_entry_json_data = response.get_body().decode("utf-8")
119+
120+
assert response.status_code == 200
121+
assert time_entry_json_data == json.dumps(inserted_time_entries)
122+
123+
124+
def test__get_time_entries_azure_endpoint__returns_a_status_code_400__when_time_entry_recive_invalid_id(
125+
test_db, time_entry_factory, insert_time_entry, activity_factory, insert_activity
126+
):
127+
inserted_activity = insert_activity(activity_factory(), test_db)
128+
existent_time_entries = time_entry_factory(activity_id=inserted_activity.id, technologies="[jira,sql]")
129+
insert_time_entry(existent_time_entries, test_db)
130+
131+
req = func.HttpRequest(
132+
method="GET",
133+
body=None,
134+
url=TIME_ENTRY_URL,
135+
route_params={"id": "invalid id"},
136+
)
137+
138+
response = azure_time_entries.get_time_entries(req)
139+
140+
assert response.status_code == 400
141+
assert response.get_body() == b'Invalid Format ID'

V2/tests/conftest.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
# flake8: noqa
2-
from fixtures import _activity_factory, _test_db, _insert_activity
3-
from fixtures import _time_entry_factory
2+
from fixtures import _activity_factory, _test_db, _create_fake_database, _create_fake_dao, _time_entry_factory,_insert_activity

V2/tests/fixtures.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import pytest
22
from faker import Faker
33

4-
import time_tracker.activities._domain as activities_domain
5-
import time_tracker.activities._infrastructure as activities_infrastructure
6-
import time_tracker.time_entries._domain as time_entries_domain
4+
import time_tracker.activities._domain as domain_activities
5+
import time_tracker.activities._infrastructure as infrastructure_activities
6+
import time_tracker.time_entries._domain as domain_time_entries
77
from time_tracker._infrastructure import DB
88

99

1010
@pytest.fixture(name='activity_factory')
11-
def _activity_factory() -> activities_domain.Activity:
11+
def _activity_factory() -> domain_activities.Activity:
1212
def _make_activity(
1313
name: str = Faker().name(),
1414
description: str = Faker().sentence(),
1515
deleted: bool = False,
1616
status: int = 1,
1717
):
18-
activity = activities_domain.Activity(
18+
activity = domain_activities.Activity(
1919
id=None,
2020
name=name,
2121
description=description,
@@ -33,9 +33,21 @@ def _test_db() -> DB:
3333
db_fake.get_session().execute("pragma foreign_keys=ON")
3434
return db_fake
3535

36+
@pytest.fixture(name='create_fake_dao')
37+
def _create_fake_dao() -> domain_activities.ActivitiesDao:
38+
db_fake = DB('sqlite:///:memory:')
39+
dao = infrastructure_activities.ActivitiesSQLDao(db_fake)
40+
return dao
41+
42+
43+
@pytest.fixture(name='create_fake_database')
44+
def _create_fake_database() -> DB:
45+
db_fake = DB('sqlite:///:memory:')
46+
return db_fake
47+
3648

3749
@pytest.fixture(name='time_entry_factory')
38-
def _time_entry_factory() -> time_entries_domain.TimeEntry:
50+
def _time_entry_factory() -> domain_time_entries.TimeEntry:
3951
def _make_time_entry(
4052
id=Faker().random_int(),
4153
start_date=str(Faker().date_time()),
@@ -49,7 +61,7 @@ def _make_time_entry(
4961
timezone_offset="300",
5062
project_id=Faker().random_int(),
5163
):
52-
time_entry = time_entries_domain.TimeEntry(
64+
time_entry = domain_time_entries.TimeEntry(
5365
id=id,
5466
start_date=start_date,
5567
owner_id=owner_id,
@@ -68,8 +80,8 @@ def _make_time_entry(
6880

6981
@pytest.fixture(name='insert_activity')
7082
def _insert_activity() -> dict:
71-
def _new_activity(activity: activities_domain.Activity, database: DB):
72-
dao = activities_infrastructure.ActivitiesSQLDao(database)
83+
def _new_activity(activity: domain_activities.Activity, database: DB):
84+
dao = infrastructure_activities.ActivitiesSQLDao(database)
7385
new_activity = dao.create(activity)
7486
return new_activity
7587
return _new_activity
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import pytest
2+
import typing
3+
4+
from faker import Faker
5+
6+
import time_tracker.activities._infrastructure as infrastructure_activities
7+
8+
from time_tracker.time_entries._infrastructure import TimeEntriesSQLDao
9+
from time_tracker.time_entries._domain import TimeEntry
10+
11+
from time_tracker._infrastructure import DB
12+
13+
14+
@pytest.fixture(name='create_time_enty_fake_dao')
15+
def _create_fake_dao() -> TimeEntriesSQLDao:
16+
db_fake = DB('sqlite:///:memory:')
17+
dao = TimeEntriesSQLDao(db_fake)
18+
return dao
19+
20+
21+
@pytest.fixture(name='clean_database', autouse=True)
22+
def _clean_database():
23+
yield
24+
db_fake = DB('sqlite:///:memory:')
25+
dao = infrastructure_activities.ActivitiesSQLDao(db_fake)
26+
query = dao.activity.delete()
27+
dao.db.get_session().execute(query)
28+
29+
30+
def test__get_all__returns_a_list_of_time_entries_dto_objects__when_one_or_more_time_entries_are_found_in_sql_database(
31+
create_time_enty_fake_dao, time_entry_factory, insert_activity, activity_factory
32+
):
33+
34+
dao = create_time_enty_fake_dao
35+
inserted_activity = insert_activity(activity_factory(), dao.db)
36+
existent_time_entries = time_entry_factory(activity_id=inserted_activity.id, technologies="[jira,sql]")
37+
inserted_time_entries = [dao.create(existent_time_entries)]
38+
39+
time_entry = dao.get_all()
40+
41+
assert isinstance(time_entry, typing.List)
42+
assert time_entry == inserted_time_entries
43+
44+
45+
def test__get_all__returns_an_empty_list__when_doesnt_found_any_time_entries_in_sql_database(
46+
create_time_enty_fake_dao, insert_activity, activity_factory
47+
):
48+
dao = create_time_enty_fake_dao
49+
insert_activity(activity_factory(), dao.db)
50+
51+
time_entry = dao.get_all()
52+
assert time_entry == []
53+
54+
55+
def test__get_by_id__returns_a_time_entry_dto__when_found_one_time_entry_that_match_id_with_sql_database(
56+
create_time_enty_fake_dao, time_entry_factory, insert_activity, activity_factory
57+
):
58+
dao = create_time_enty_fake_dao
59+
inserted_activity = insert_activity(activity_factory(), dao.db)
60+
existent_time_entries = time_entry_factory(activity_id=inserted_activity.id, technologies="[jira,sql]")
61+
inserted_time_entries = dao.create(existent_time_entries)
62+
63+
time_entry = dao.get_by_id(existent_time_entries.id)
64+
65+
assert isinstance(time_entry, TimeEntry)
66+
assert time_entry.id == inserted_time_entries.id
67+
assert time_entry == inserted_time_entries
68+
69+
70+
def test__get_by_id__returns_none__when_no_time_entry_matches_by_id(
71+
create_time_enty_fake_dao, time_entry_factory, insert_activity, activity_factory
72+
):
73+
dao = create_time_enty_fake_dao
74+
inserted_activity = insert_activity(activity_factory(), dao.db)
75+
existent_time_entries = time_entry_factory(activity_id=inserted_activity.id, technologies="[jira,sql]")
76+
dao.create(existent_time_entries)
77+
78+
time_entry = dao.get_by_id(Faker().pyint())
79+
80+
assert time_entry is None

V2/tests/unit/services/time_entry_service_test.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,29 @@ def test__delete_time_entry__uses_the_time_entry_dao__to_delete_time_entry_selec
2929

3030
assert time_entry_dao.delete.called
3131
assert expected_time_entry == deleted_time_entry
32+
33+
34+
def test__get_all__uses_the_time_entry_dao__to_retrieve_time_entries(mocker):
35+
expected_time_entries = mocker.Mock()
36+
time_entry_dao = mocker.Mock(
37+
get_all=mocker.Mock(return_value=expected_time_entries)
38+
)
39+
time_activity_service = TimeEntryService(time_entry_dao)
40+
41+
actual_activities = time_activity_service.get_all()
42+
43+
assert time_entry_dao.get_all.called
44+
assert expected_time_entries == actual_activities
45+
46+
47+
def test__get_by_id__uses_the_time_entry_dao__to_retrieve_one_time_entry(mocker):
48+
expected_time_entry = mocker.Mock()
49+
time_entry_dao = mocker.Mock(
50+
get_by_id=mocker.Mock(return_value=expected_time_entry)
51+
)
52+
time_entry_service = TimeEntryService(time_entry_dao)
53+
54+
actual_time_entry = time_entry_service.get_by_id(Faker().uuid4())
55+
56+
assert time_entry_dao.get_by_id.called
57+
assert expected_time_entry == actual_time_entry

V2/tests/unit/use_cases/time_entries_use_case_test.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
from time_tracker.time_entries._domain import _use_cases
55

6+
fake = Faker()
7+
68

79
def test__create_time_entry_function__uses_the_time_entries_service__to_create_time_entry(
810
mocker: MockFixture, time_entry_factory
@@ -30,3 +32,33 @@ def test__delete_time_entry_function__uses_the_time_entry_service__to_delete_tim
3032

3133
assert time_entry_service.delete.called
3234
assert expected_time_entry == deleted_time_entry
35+
36+
37+
def test__get_list_time_entries_function__uses_the_time_entry_service__to_retrieve_time_entries(
38+
mocker: MockFixture,
39+
):
40+
expected_time_entries = mocker.Mock()
41+
time_entry_service = mocker.Mock(
42+
get_all=mocker.Mock(return_value=expected_time_entries)
43+
)
44+
45+
time_entries_use_case = _use_cases.GetTimeEntriesUseCase(time_entry_service)
46+
actual_time_entries = time_entries_use_case.get_time_entries()
47+
48+
assert time_entry_service.get_all.called
49+
assert expected_time_entries == actual_time_entries
50+
51+
52+
def test__get_time_entry_by_id_function__uses_the_time_entry_service__to_retrieve_time_entry(
53+
mocker: MockFixture,
54+
):
55+
expected_time_entries = mocker.Mock()
56+
time_entry_service = mocker.Mock(
57+
get_by_id=mocker.Mock(return_value=expected_time_entries)
58+
)
59+
60+
time_entry_use_case = _use_cases.GetTimeEntryUseCase(time_entry_service)
61+
actual_time_entry = time_entry_use_case.get_time_entry_by_id(fake.uuid4())
62+
63+
assert time_entry_service.get_by_id.called
64+
assert expected_time_entries == actual_time_entry

V2/time_tracker/_infrastructure/_db.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
from . import _config
44

5+
_TEST_DIALECT = "sqlite"
6+
57

68
class DB():
79
config = _config.load_config()
@@ -17,4 +19,6 @@ def get_session(self):
1719
self.metadata.create_all(self.engine)
1820
if self.connection is None:
1921
self.connection = self.engine.connect()
22+
if self.engine.dialect.name == _TEST_DIALECT:
23+
self.connection.execute("pragma foreign_keys=ON")
2024
return self.connection
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
# flake8: noqa
2-
from ._time_entries import create_time_entry, delete_time_entry
2+
from ._time_entries import create_time_entry
3+
from ._time_entries import delete_time_entry
4+
from ._time_entries import get_time_entries
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# flake8: noqa
22
from ._create_time_entry import create_time_entry
3-
from ._delete_time_entry import delete_time_entry
3+
from ._delete_time_entry import delete_time_entry
4+
from ._get_time_entries import get_time_entries

0 commit comments

Comments
 (0)