Skip to content

Commit 003376d

Browse files
committed
feat: TT-365 Method POST activity and create function serverless
1 parent 500a5d0 commit 003376d

File tree

17 files changed

+162
-5
lines changed

17 files changed

+162
-5
lines changed

V2/serverless.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ functions:
6363
- http: true
6464
x-azure-settings:
6565
methods:
66-
- PUT
66+
- PUT
6767
route: activities/{id}
68+
authLevel: anonymous
69+
70+
create_activity:
71+
handler: time_entries/interface.create_activity
72+
events:
73+
- http: true
74+
x-azure-settings:
75+
methods:
76+
- POST
77+
route: activities/
6878
authLevel: anonymous

V2/tests/api/azure/activity_azure_endpoints_test.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,23 @@ def test__update_activity_azure_endpoint__returns_an_activity__when_found_an_act
8080

8181
assert response.status_code == 200
8282
assert activitiy_json_data == json.dumps(new_activity)
83+
84+
def test__activity_azure_endpoint__creates_an_activity__when_activity_has_all_attributes(
85+
create_temp_activities,
86+
):
87+
activities_json, tmp_directory = create_temp_activities
88+
activities._create_activity.JSON_PATH = tmp_directory
89+
90+
activity_body = {'id': Faker().uuid4(), 'name': Faker().user_name(), 'description': Faker().sentence(),'deleted': Faker().uuid4() ,'status': 'active', 'tenant_id': Faker().uuid4()}
91+
body = json.dumps(activity_body).encode("utf-8")
92+
req = func.HttpRequest(
93+
method='POST',
94+
body= body,
95+
url='/api/activities/',
96+
)
97+
98+
response = activities._create_activity.create_activity(req)
99+
activitiy_json_data = response.get_body()
100+
101+
assert response.status_code == 200
102+
assert activitiy_json_data == body

V2/tests/integration/daos/activities_json_dao_test.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,18 @@ def test_update__returns_none__when_doesnt_found_one_activity_to_update(
132132
result = activities_json_dao.update('', activity_data)
133133

134134
assert result == None
135+
136+
def test_create_activity__returns_an_activity_dto__when_create_an_activity_that_matches_attributes(create_fake_activities):
137+
create_fake_activities([])
138+
139+
activities_json_dao = ActivitiesJsonDao(Faker().file_path())
140+
activity_data = {
141+
"name": "test_name",
142+
"description": "test_description",
143+
"tenant_id": "test_tenant_id",
144+
"id": "test_id",
145+
"deleted": "test_deleted",
146+
"status": "test_status",
147+
}
148+
result = activities_json_dao.create_activity(activity_data)
149+
assert result == Activity(**activity_data)

V2/tests/unit/services/activity_service_test.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,15 @@ def test__update_activity__uses_the_activity_dao__to_update_one_activity(
5858

5959
assert activity_dao.update.called
6060
assert expected_activity == updated_activity
61+
62+
def test__create_activity__uses_the_activity_dao__to_create_an_activity(mocker):
63+
expected_activity = mocker.Mock()
64+
activity_dao = mocker.Mock(
65+
create_activity=mocker.Mock(return_value=expected_activity)
66+
)
67+
activity_service = ActivityService(activity_dao)
68+
69+
actual_activity = activity_service.create_activity(Faker().pydict())
70+
71+
assert activity_dao.create_activity.called
72+
assert expected_activity == actual_activity

V2/tests/unit/use_cases/activities_use_case_test.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,20 @@ def test__get_activity_by_id_function__uses_the_activity_service__to_retrieve_ac
3636
assert expected_activity == actual_activity
3737

3838

39+
def test__create_activity_function__uses_the_activities_service__to_create_activity(
40+
mocker: MockFixture,
41+
):
42+
expected_activity = mocker.Mock()
43+
activity_service = mocker.Mock(
44+
create_activity=mocker.Mock(return_value=expected_activity)
45+
)
46+
47+
activity_use_case = _use_cases.CreateActivityUseCase(activity_service)
48+
actual_activity = activity_use_case.create_activity(fake.pydict())
49+
50+
assert activity_service.create_activity.called
51+
assert expected_activity == actual_activity
52+
3953
def test__delete_activity_function__uses_the_activity_service__to_change_activity_status(
4054
mocker: MockFixture,
4155
):
@@ -50,7 +64,6 @@ def test__delete_activity_function__uses_the_activity_service__to_change_activit
5064
assert activity_service.delete.called
5165
assert expected_activity == deleted_activity
5266

53-
5467
def test__update_activity_function__uses_the_activities_service__to_update_an_activity(
5568
mocker: MockFixture,
5669
):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
from ._activities import get_activities
22
from ._activities import delete_activity
33
from ._activities import update_activity
4+
from ._activities import create_activity
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
from ._get_activities import get_activities
22
from ._delete_activity import delete_activity
33
from ._update_activity import update_activity
4+
from ._create_activity import create_activity
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
from time_entries._infrastructure import ActivitiesJsonDao
2+
from time_entries._domain import ActivityService, _use_cases, Activity
3+
4+
import azure.functions as func
5+
import json
6+
import logging
7+
import dataclasses
8+
9+
10+
JSON_PATH = (
11+
'time_entries/_infrastructure/_data_persistence/activities_data.json'
12+
)
13+
14+
15+
16+
def create_activity(req: func.HttpRequest) -> func.HttpResponse:
17+
logging.info(
18+
'Python HTTP trigger function processed a request to create an activity.'
19+
)
20+
activity_data = req.get_json()
21+
status_code = 200
22+
if _validate_activity(activity_data):
23+
response = _create_activity(activity_data)
24+
else:
25+
status_code = 404
26+
response = b'Not possible to create activity, attributes are not correct '
27+
28+
return func.HttpResponse(
29+
body=response, status_code=status_code, mimetype="application/json"
30+
)
31+
32+
def _create_activity(activity_data: dict) -> str:
33+
activity_use_case = _use_cases.CreateActivityUseCase(
34+
_create_activity_service(JSON_PATH)
35+
)
36+
activity = activity_use_case.create_activity(activity_data)
37+
return json.dumps(activity.__dict__) if activity else b'Not Found'
38+
39+
def _validate_activity(activity_data: dict) -> bool:
40+
activity_keys = [field.name for field in dataclasses.fields(Activity)]
41+
new_activity_keys = list(activity_data.keys())
42+
return all(map(lambda key: key in activity_keys, new_activity_keys)) and len(activity_keys) == len(new_activity_keys)
43+
44+
def _create_activity_service(path: str):
45+
activity_json = ActivitiesJsonDao(path)
46+
return ActivityService(activity_json)
47+
48+

V2/time_entries/_domain/_persistence_contracts/_activities_dao.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,11 @@ def delete(self, id: str) -> Activity:
1919
@abc.abstractmethod
2020
def update(self, id: str, new_activity: dict) -> Activity:
2121
pass
22+
23+
@abc.abstractmethod
24+
def create_activity(self, activity_data: dict) -> Activity:
25+
pass
26+
27+
@abc.abstractmethod
28+
def delete(self, id: str) -> Activity:
29+
pass

V2/time_entries/_domain/_services/_activity.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@ def delete(self, activity_id: str) -> Activity:
1717

1818
def update(self, activity_id: str, new_activity: dict) -> Activity:
1919
return self.activities_dao.update(activity_id, new_activity)
20+
21+
def create_activity(self, activity_data: dict) -> Activity:
22+
return self.activities_dao.create_activity(activity_data)

0 commit comments

Comments
 (0)