Skip to content

Commit 595d0ee

Browse files
committed
feat: TT-365 Method POST activity and create function serverless
1 parent 464f281 commit 595d0ee

File tree

17 files changed

+163
-71
lines changed

17 files changed

+163
-71
lines changed

V2/serverless.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,13 @@ functions:
4646
- GET
4747
route: activities/{id:?}
4848
authLevel: anonymous
49+
50+
create_activity:
51+
handler: time_entries/interface.create_activity
52+
events:
53+
- http: true
54+
x-azure-settings:
55+
methods:
56+
- POST
57+
route: activities/
58+
authLevel: anonymous

V2/tests/api/azure/activity_azure_endpoints_test.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from time_entries._application._activities import _get_activities as activities
1+
from time_entries._application._activities import _get_activities as activities, _create_activity
22
import azure.functions as func
33
import json
44
import typing
5-
5+
from faker import Faker
66

77
def test__activity_azure_endpoint__returns_all_activities(
88
create_temp_activities,
@@ -35,3 +35,24 @@ def test__activity_azure_endpoint__returns_an_activity__when_activity_matches_it
3535

3636
assert response.status_code == 200
3737
assert activitiy_json_data == json.dumps(activities_json[0])
38+
39+
def test__activity_azure_endpoint__creates_an_activity__when_activity_has_all_attributes(
40+
create_temp_activities,
41+
):
42+
activities_json, tmp_directory = create_temp_activities
43+
_create_activity.JSON_PATH = tmp_directory
44+
45+
activity_body = {'id': Faker().uuid4(), 'name': Faker().user_name(), 'description': Faker().sentence(),'deleted': Faker().uuid4() ,'status': 'active', 'tenant_id': Faker().uuid4()}
46+
body = json.dumps(activity_body).encode("utf-8")
47+
req = func.HttpRequest(
48+
method='POST',
49+
body= body,
50+
url='/api/activities/',
51+
)
52+
53+
response = _create_activity.create_activity(req)
54+
activitiy_json_data = response.get_body()
55+
56+
assert response.status_code == 200
57+
assert activitiy_json_data == body
58+

V2/tests/integration/daos/activities_json_dao_test.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,18 @@ def test_get_all__returns_an_empty_list__when_doesnt_found_any_activities(
8383
result = activities_json_dao.get_all()
8484

8585
assert result == activities
86+
87+
def test_create_activity__returns_an_activity_dto__when_create_an_activity_that_matches_attributes(create_fake_activities):
88+
create_fake_activities([])
89+
90+
activities_json_dao = ActivitiesJsonDao(Faker().file_path())
91+
activity_data = {
92+
"name": "test_name",
93+
"description": "test_description",
94+
"tenant_id": "test_tenant_id",
95+
"id": "test_id",
96+
"deleted": "test_deleted",
97+
"status": "test_status",
98+
}
99+
result = activities_json_dao.create_activity(activity_data)
100+
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
@@ -26,3 +26,15 @@ def test__get_by_id__uses_the_activity_dao__to_retrieve_one_activity(mocker):
2626

2727
assert activity_dao.get_by_id.called
2828
assert expected_activity == actual_activity
29+
30+
def test__create_activity__uses_the_activity_dao__to_create_an_activity(mocker):
31+
expected_activity = mocker.Mock()
32+
activity_dao = mocker.Mock(
33+
create_activity=mocker.Mock(return_value=expected_activity)
34+
)
35+
activity_service = ActivityService(activity_dao)
36+
37+
actual_activity = activity_service.create_activity(Faker().pydict())
38+
39+
assert activity_dao.create_activity.called
40+
assert expected_activity == actual_activity

V2/tests/unit/use_cases/activities_use_case_test.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,18 @@ def test__get_activity_by_id_function__uses_the_activities_service__to_retrieve_
3434

3535
assert activity_service.get_by_id.called
3636
assert expected_activity == actual_activity
37+
38+
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
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from ._activities import get_activities
1+
from ._activities import get_activities, create_activity
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
from ._get_activities import get_activities
2+
from ._create_activity import create_activity
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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+
12+
'::WqV2/time_entries/_infrastructure/_data_persistence/activities_data.json'
13+
)
14+
15+
16+
17+
def create_activity(req: func.HttpRequest) -> func.HttpResponse:
18+
logging.info(
19+
'Python HTTP trigger function processed a request to create an activity.'
20+
)
21+
activity_data = req.get_json()
22+
status_code = 200
23+
if _validate_activity(activity_data):
24+
response = _create_activity(activity_data)
25+
else:
26+
status_code = 404
27+
response = b'Not possible to create activity, attributes are not correct '
28+
29+
return func.HttpResponse(
30+
body=response, status_code=status_code, mimetype="application/json"
31+
)
32+
33+
def _create_activity(activity_data: dict) -> str:
34+
activity_use_case = _use_cases.CreateActivityUseCase(
35+
_create_activity_service(JSON_PATH)
36+
)
37+
activity = activity_use_case.create_activity(activity_data)
38+
return json.dumps(activity.__dict__) if activity else b'Not Found'
39+
40+
def _validate_activity(activity_data: dict) -> bool:
41+
activity_keys = [field.name for field in dataclasses.fields(Activity)]
42+
new_activity_keys = list(activity_data.keys())
43+
return all(map(lambda key: key in activity_keys, new_activity_keys)) and len(activity_keys) == len(new_activity_keys)
44+
45+
def _create_activity_service(path: str):
46+
activity_json = ActivitiesJsonDao(path)
47+
return ActivityService(activity_json)
48+
49+

V2/time_entries/_domain/_persistence_contracts/_activities_dao.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ def get_by_id(self, id: str) -> Activity:
1111
@abc.abstractmethod
1212
def get_all(self) -> typing.List[Activity]:
1313
pass
14+
15+
@abc.abstractmethod
16+
def create_activity(self, activity_data: dict) -> Activity:
17+
pass

V2/time_entries/_domain/_services/_activity.py

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

1212
def get_all(self) -> typing.List[Activity]:
1313
return self.activities_dao.get_all()
14+
15+
def create_activity(self, activity_data: dict) -> Activity:
16+
return self.activities_dao.create_activity(activity_data)

0 commit comments

Comments
 (0)