Skip to content

Commit d5caf06

Browse files
committed
feat: TT-403 created end-point to DELETE of time_entries
1 parent bf76daf commit d5caf06

File tree

16 files changed

+203
-6
lines changed

16 files changed

+203
-6
lines changed

V2/serverless.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,13 @@ functions:
8686
- POST
8787
route: time-entries/
8888
authLevel: anonymous
89+
90+
delete_time_entry:
91+
handler: time_tracker/time_entries/interface.delete_time_entry
92+
events:
93+
- http: true
94+
x-azure-settings:
95+
methods:
96+
- DELETE
97+
route: time-entries/{id}
98+
authLevel: anonymous

V2/tests/api/azure/time_entry_azure_endpoints_test.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import json
55

66

7-
ACTIVITY_URL = "/api/time-entries/"
7+
TIME_ENTRY_URL = "/api/time-entries/"
88

99

1010
def test__time_entry_azure_endpoint__creates_an_time_entry__when_time_entry_has_all_attributes(
@@ -18,10 +18,47 @@ def test__time_entry_azure_endpoint__creates_an_time_entry__when_time_entry_has_
1818
req = func.HttpRequest(
1919
method="POST",
2020
body=body,
21-
url=ACTIVITY_URL,
21+
url=TIME_ENTRY_URL,
2222
)
2323

2424
response = time_entries.create_time_entry(req)
2525
time_entry_json_data = response.get_body()
2626
assert response.status_code == 201
2727
assert time_entry_json_data == body
28+
29+
30+
def test__time_entry_azure_endpoint__returns_an_time_entry_with_true_deleted__when_an_time_entry_matching_its_id_is_found(
31+
create_temp_time_entries,
32+
):
33+
time_entries_json, tmp_directory = create_temp_time_entries
34+
time_entries.delete_time_entry.JSON_PATH = tmp_directory
35+
req = func.HttpRequest(
36+
method="DELETE",
37+
body=None,
38+
url=TIME_ENTRY_URL,
39+
route_params={"id": time_entries_json[0]["id"]},
40+
)
41+
42+
response = time_entries.delete_time_entry(req)
43+
time_entry_json_data = json.loads(response.get_body().decode("utf-8"))
44+
45+
assert response.status_code == 200
46+
assert time_entry_json_data["deleted"] is True
47+
48+
49+
def test__delete_time_entries_azure_endpoint__returns_a_status_code_400__when_time_entry_recive_invalid_id(
50+
create_temp_time_entries,
51+
):
52+
tmp_directory = create_temp_time_entries
53+
time_entries.delete_time_entry.JSON_PATH = tmp_directory
54+
req = func.HttpRequest(
55+
method="DELETE",
56+
body=None,
57+
url=TIME_ENTRY_URL,
58+
route_params={"id": "invalid id"},
59+
)
60+
61+
response = time_entries.delete_time_entry(req)
62+
63+
assert response.status_code == 400
64+
assert response.get_body() == b'Invalid Format ID'

V2/tests/fixtures.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def create_temp_time_entries(tmpdir_factory):
5050
json_file = temporary_directory.join("time_entries.json")
5151
time_entries = [
5252
{
53-
"id": Faker().random_int(),
53+
"id": 1,
5454
"start_date": Faker().date(),
5555
"owner_id": Faker().random_int(),
5656
"description": Faker().sentence(),

V2/tests/integration/daos/time_entries_dao.test.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,30 @@ def test_create_time_entry__returns_an_time_entry_dto__when_create_an_time_entry
2727
time_entry_data = time_entry_factory()
2828
result = time_entries_json_dao.create(time_entry_data.__dict__)
2929
assert result == TimeEntry(**time_entry_data)
30+
31+
32+
def test_delete__returns_an_time_entry_with_true_deleted__when_an_time_entry_matching_its_id_is_found(
33+
create_fake_time_entries, time_entry_factory
34+
):
35+
time_entries_json_dao = TimeEntriesJsonDao(Faker().file_path())
36+
time_entries = create_fake_time_entries(
37+
[
38+
time_entry_factory().__dict__
39+
]
40+
)
41+
42+
time_entry_dto = time_entries[0]
43+
result = time_entries_json_dao.delete(time_entry_dto.id)
44+
45+
assert result.deleted == True
46+
47+
48+
def test_delete__returns_none__when_no_time_entry_matching_its_id_is_found(
49+
create_fake_time_entries,
50+
):
51+
time_entries_json_dao = TimeEntriesJsonDao(Faker().file_path())
52+
create_fake_time_entries([])
53+
54+
result = time_entries_json_dao.delete(Faker().pyint())
55+
56+
assert result is None

V2/tests/unit/services/time_entry_service_test.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,18 @@ def test__create_time_entries__uses_the_time_entry_dao__to_create_an_time_entry(
1414

1515
assert time_entry_dao.create.called
1616
assert expected_time_entry == actual_time_entry
17+
18+
19+
def test__delete_time_entry__uses_the_time_entry_dao__to_change_time_entry_deleted(
20+
mocker,
21+
):
22+
expected_time_entry = mocker.Mock()
23+
time_entry_dao = mocker.Mock(
24+
delete=mocker.Mock(return_value=expected_time_entry)
25+
)
26+
27+
time_entry_service = TimeEntryService(time_entry_dao)
28+
deleted_time_entry = time_entry_service.delete(Faker().pyint())
29+
30+
assert time_entry_dao.delete.called
31+
assert expected_time_entry == deleted_time_entry

V2/tests/unit/use_cases/time_entries_use_case_test.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from pytest_mock import MockFixture
2+
from faker import Faker
23

34
from time_tracker.time_entries._domain import _use_cases
45

@@ -16,3 +17,16 @@ def test__create_time_entry_function__uses_the_time_entries_service__to_create_t
1617

1718
assert time_entry_service.create.called
1819
assert expected_time_entry == actual_time_entry
20+
21+
22+
def test__delete_time_entry_function__uses_the_time_entry_service__to_change_time_entry_deleted(
23+
mocker: MockFixture,
24+
):
25+
expected_time_entry = mocker.Mock()
26+
time_entry_service = mocker.Mock(delete=mocker.Mock(return_value=expected_time_entry))
27+
28+
time_entry_use_case = _use_cases.DeleteTimeEntryUseCase(time_entry_service)
29+
deleted_time_entry = time_entry_use_case.delete_time_entry(Faker().pyint())
30+
31+
assert time_entry_service.delete.called
32+
assert expected_time_entry == deleted_time_entry
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# flake8: noqa
2-
from ._time_entries import create_time_entry
2+
from ._time_entries import create_time_entry
3+
from ._time_entries import delete_time_entry
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# flake8: noqa
2-
from ._create_time_entry import create_time_entry
2+
from ._create_time_entry import create_time_entry
3+
from ._delete_time_entry import delete_time_entry
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import json
2+
3+
import azure.functions as func
4+
5+
from ... import _domain
6+
from ... import _infrastructure
7+
8+
_JSON_PATH = (
9+
'time_tracker/time_entries/_infrastructure/_data_persistence/time_entries_data.json'
10+
)
11+
12+
13+
def delete_time_entry(req: func.HttpRequest) -> func.HttpResponse:
14+
time_entry_dao = _infrastructure.TimeEntriesJsonDao(_JSON_PATH)
15+
time_entry_service = _domain.TimeEntryService(time_entry_dao)
16+
use_case = _domain._use_cases.DeleteTimeEntryUseCase(time_entry_service)
17+
18+
try:
19+
time_entry_id = int(req.route_params.get("id"))
20+
21+
deleted_time_entry = use_case.delete_time_entry(time_entry_id)
22+
if not deleted_time_entry:
23+
return func.HttpResponse(
24+
body='Not found',
25+
status_code=404,
26+
mimetype="application/json"
27+
)
28+
29+
return func.HttpResponse(
30+
body=json.dumps(deleted_time_entry.__dict__),
31+
status_code=200,
32+
mimetype="application/json"
33+
)
34+
35+
except ValueError:
36+
return func.HttpResponse(
37+
body=b'Invalid Format ID',
38+
status_code=400,
39+
mimetype="application/json"
40+
)
41+

V2/time_tracker/time_entries/_domain/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44
from ._services import TimeEntryService
55
from ._use_cases import (
66
CreateTimeEntryUseCase,
7+
DeleteTimeEntryUseCase
78
)

0 commit comments

Comments
 (0)