Skip to content

Commit 32a80b4

Browse files
author
EliuX
committed
fix:bug: Close #107 Allow removing id by specifying null
1 parent 9d9083e commit 32a80b4

File tree

8 files changed

+49
-52
lines changed

8 files changed

+49
-52
lines changed

tests/time_tracker_api/project_types/project_types_namespace_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def test_create_project_type_should_reject_bad_request(client: FlaskClient,
4242
from time_tracker_api.project_types.project_types_namespace import project_type_dao
4343
invalid_project_type_data = valid_project_type_data.copy()
4444
invalid_project_type_data.update({
45-
"parent_id": None,
45+
"name": None,
4646
})
4747
repository_create_mock = mocker.patch.object(project_type_dao.repository,
4848
'create',
@@ -166,7 +166,7 @@ def test_update_project_should_reject_bad_request(client: FlaskClient,
166166
from time_tracker_api.project_types.project_types_namespace import project_type_dao
167167
invalid_project_type_data = valid_project_type_data.copy()
168168
invalid_project_type_data.update({
169-
"parent_id": None,
169+
"name": None,
170170
})
171171
repository_update_mock = mocker.patch.object(project_type_dao.repository,
172172
'partial_update',

tests/time_tracker_api/time_entries/time_entries_namespace_test.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from flask_restplus._http import HTTPStatus
88
from pytest_mock import MockFixture
99

10-
from commons.data_access_layer.cosmos_db import current_datetime
10+
from commons.data_access_layer.cosmos_db import current_datetime, current_datetime_str
1111

1212
fake = Faker()
1313

@@ -16,14 +16,14 @@
1616
"project_id": fake.uuid4(),
1717
"activity_id": fake.uuid4(),
1818
"description": fake.paragraph(nb_sentences=2),
19-
"start_date": str(yesterday.isoformat()),
20-
"owner_id": fake.uuid4(),
21-
"tenant_id": fake.uuid4()
19+
"start_date": current_datetime_str(),
2220
}
2321

2422
fake_time_entry = ({
2523
"id": fake.random_int(1, 9999),
2624
"running": True,
25+
"owner_id": fake.uuid4(),
26+
"tenant_id": fake.uuid4(),
2727
})
2828
fake_time_entry.update(valid_time_entry_input)
2929

@@ -86,21 +86,20 @@ def test_create_time_entry_should_succeed_with_valid_request(client: FlaskClient
8686
repository_create_mock.assert_called_once()
8787

8888

89-
def test_create_time_entry_should_reject_bad_request(client: FlaskClient,
90-
mocker: MockFixture,
91-
valid_header: dict):
89+
def test_create_time_entry_with_missing_req_field_should_return_bad_request(client: FlaskClient,
90+
mocker: MockFixture,
91+
valid_header: dict):
9292
from time_tracker_api.time_entries.time_entries_namespace import time_entries_dao
93-
invalid_time_entry_input = valid_time_entry_input.copy()
94-
invalid_time_entry_input.update({
95-
"project_id": None,
96-
})
9793
repository_create_mock = mocker.patch.object(time_entries_dao.repository,
9894
'create',
9995
return_value=fake_time_entry)
10096

10197
response = client.post("/time-entries",
10298
headers=valid_header,
103-
json=invalid_time_entry_input,
99+
json={
100+
"activity_id": fake.uuid4(),
101+
"start_date": current_datetime_str(),
102+
},
104103
follow_redirects=True)
105104

106105
assert HTTPStatus.BAD_REQUEST == response.status_code

time_tracker_api/activities/activities_namespace.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
from faker import Faker
2-
from flask_restplus import fields, Resource, Namespace
2+
from flask_restplus import fields, Resource
33
from flask_restplus._http import HTTPStatus
44

55
from time_tracker_api.activities.activities_model import create_dao
6-
from time_tracker_api.api import common_fields
6+
from time_tracker_api.api import common_fields, api
77

88
faker = Faker()
99

10-
ns = Namespace('activities', description='API for activities')
10+
ns = api.namespace('activities', description='Namespace of the API for activities')
1111

1212
# Activity Model
1313
activity_input = ns.model('ActivityInput', {

time_tracker_api/api.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,30 +38,37 @@ def create_attributes_filter(ns: namespace, model: Model, filter_attrib_names: l
3838
return attribs_parser
3939

4040

41-
# Common models structure
41+
# Custom fields
42+
class NullableString(fields.String):
43+
__schema_type__ = ['string', 'null']
44+
45+
46+
class UUID(NullableString):
47+
def __init__(self, *args, **kwargs):
48+
super(UUID, self).__init__(*args, **kwargs)
49+
self.pattern = UUID_REGEX
50+
51+
4252
common_fields = {
43-
'id': fields.String(
53+
'id': UUID(
4454
title='Identifier',
4555
readOnly=True,
4656
required=True,
4757
description='The unique identifier',
48-
pattern=UUID_REGEX,
4958
example=faker.uuid4(),
5059
),
51-
'tenant_id': fields.String(
60+
'tenant_id': UUID(
5261
title='Identifier of Tenant',
5362
readOnly=True,
5463
required=True,
5564
description='Tenant it belongs to',
56-
# pattern=UUID_REGEX, This must be confirmed
5765
example=faker.uuid4(),
5866
),
59-
'deleted': fields.String(
67+
'deleted': UUID(
6068
readOnly=True,
6169
required=True,
6270
title='Last event Identifier',
6371
description='Last event over this resource',
64-
pattern=UUID_REGEX,
6572
),
6673
}
6774

time_tracker_api/customers/customers_namespace.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
from faker import Faker
2-
from flask_restplus import Namespace, Resource, fields
2+
from flask_restplus import Resource, fields
33
from flask_restplus._http import HTTPStatus
44

5-
from time_tracker_api.api import common_fields
5+
from time_tracker_api.api import common_fields, api
66
from time_tracker_api.customers.customers_model import create_dao
77

88
faker = Faker()
99

10-
ns = Namespace('customers', description='API for customers')
10+
ns = api.namespace('customers', description='Namespace of the API for customers')
1111

1212
# Customer Model
1313
customer_input = ns.model('CustomerInput', {

time_tracker_api/project_types/project_types_namespace.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
from faker import Faker
2-
from flask_restplus import Namespace, Resource, fields
2+
from flask_restplus import Resource, fields
33
from flask_restplus._http import HTTPStatus
44

5-
from time_tracker_api.api import common_fields, create_attributes_filter
5+
from time_tracker_api.api import common_fields, create_attributes_filter, api, UUID
66
from time_tracker_api.project_types.project_types_model import create_dao
7-
from time_tracker_api.security import UUID_REGEX
87

98
faker = Faker()
109

11-
ns = Namespace('project-types', description='API for project types')
10+
ns = api.namespace('project-types', description='Namespace of the API for project types')
1211

1312
# ProjectType Model
1413
project_type_input = ns.model('ProjectTypeInput', {
@@ -26,19 +25,17 @@
2625
description='Comments about the project type',
2726
example=faker.paragraph(),
2827
),
29-
'customer_id': fields.String(
28+
'customer_id': UUID(
3029
title='Identifier of the Customer',
3130
required=False,
3231
description='Customer this project type belongs to. '
3332
'If not specified, it will be considered an internal project of the tenant.',
34-
pattern=UUID_REGEX,
3533
example=faker.uuid4(),
3634
),
37-
'parent_id': fields.String(
35+
'parent_id': UUID(
3836
title='Identifier of the parent project type',
3937
required=False,
4038
description='This parent node allows to created a tree-like structure for project types',
41-
pattern=UUID_REGEX,
4239
example=faker.uuid4(),
4340
),
4441
})

time_tracker_api/projects/projects_namespace.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
from faker import Faker
2-
from flask_restplus import Namespace, Resource, fields
2+
from flask_restplus import Resource, fields
33
from flask_restplus._http import HTTPStatus
44

5-
from time_tracker_api.api import common_fields, create_attributes_filter
5+
from time_tracker_api.api import common_fields, create_attributes_filter, UUID, api
66
from time_tracker_api.projects.projects_model import create_dao
7-
from time_tracker_api.security import UUID_REGEX
87

98
faker = Faker()
109

11-
ns = Namespace('projects', description='API for projects (clients)')
10+
ns = api.namespace('projects', description='Namespace of the API for projects')
1211

1312
# Project Model
1413
project_input = ns.model('ProjectInput', {
@@ -26,19 +25,17 @@
2625
description='Description about the project',
2726
example=faker.paragraph(),
2827
),
29-
'customer_id': fields.String(
28+
'customer_id': UUID(
3029
title='Identifier of the Customer',
3130
required=False,
3231
description='Customer this project type belongs to. '
3332
'If not specified, it will be considered an internal project of the tenant.',
34-
pattern=UUID_REGEX,
3533
example=faker.uuid4(),
3634
),
37-
'project_type_id': fields.String(
35+
'project_type_id': UUID(
3836
title='Identifier of the project type',
3937
required=False,
4038
description='Id of the project type it belongs. This allows grouping the projects.',
41-
pattern=UUID_REGEX,
4239
example=faker.uuid4(),
4340
),
4441
})

time_tracker_api/time_entries/time_entries_namespace.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
11
from datetime import timedelta
22

33
from faker import Faker
4-
from flask_restplus import fields, Resource, Namespace
4+
from flask_restplus import fields, Resource
55
from flask_restplus._http import HTTPStatus
66

77
from commons.data_access_layer.cosmos_db import current_datetime, datetime_str, current_datetime_str
88
from commons.data_access_layer.database import COMMENTS_MAX_LENGTH
9-
from time_tracker_api.api import common_fields, create_attributes_filter
10-
from time_tracker_api.security import UUID_REGEX
9+
from time_tracker_api.api import common_fields, create_attributes_filter, api, UUID
1110
from time_tracker_api.time_entries.time_entries_model import create_dao
1211

1312
faker = Faker()
1413

15-
ns = Namespace('time-entries', description='API for time entries')
14+
ns = api.namespace('time-entries', description='Namespace of the API for time entries')
1615

1716
# TimeEntry Model
1817
time_entry_input = ns.model('TimeEntryInput', {
19-
'project_id': fields.String(
18+
'project_id': UUID(
2019
title='Project',
2120
required=True,
2221
description='The id of the selected project',
23-
pattern=UUID_REGEX,
2422
example=faker.uuid4(),
2523
),
2624
'start_date': fields.DateTime(
@@ -30,11 +28,10 @@
3028
description='When the user started doing this activity',
3129
example=datetime_str(current_datetime() - timedelta(days=1)),
3230
),
33-
'activity_id': fields.String(
31+
'activity_id': UUID(
3432
title='Activity',
3533
required=False,
3634
description='The id of the selected activity',
37-
pattern=UUID_REGEX,
3835
example=faker.uuid4(),
3936
),
4037
'description': fields.String(
@@ -86,7 +83,7 @@
8683
description='Whether this time entry is currently running or not',
8784
example=faker.boolean(),
8885
),
89-
'owner_id': fields.String(
86+
'owner_id': UUID(
9087
required=True,
9188
readOnly=True,
9289
title='Owner of time entry',

0 commit comments

Comments
 (0)