Skip to content

Commit c69773d

Browse files
committed
Add dedupe ok incoming keys
1 parent 879d6bc commit c69773d

File tree

8 files changed

+188
-1
lines changed

8 files changed

+188
-1
lines changed

src/api/createProductTeam/tests/v1/test_index_v1.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77

88
from test_helpers.dynamodb import mock_table
99
from test_helpers.response_assertions import _response_assertions
10-
from test_helpers.sample_data import CPM_PRODUCT_TEAM_NO_ID
10+
from test_helpers.sample_data import (
11+
CPM_PRODUCT_TEAM_NO_ID,
12+
CPM_PRODUCT_TEAM_NO_ID_DUPED_KEYS,
13+
)
1114

1215
TABLE_NAME = "hiya"
1316

@@ -110,3 +113,54 @@ def test_index_bad_payload(version):
110113
_response_assertions(
111114
result=result, expected=expected, check_body=True, check_content_length=True
112115
)
116+
117+
118+
@pytest.mark.parametrize(
119+
"version",
120+
[
121+
"1",
122+
],
123+
)
124+
def test_index(version):
125+
with mock_table(table_name=TABLE_NAME), mock.patch.dict(
126+
os.environ,
127+
{
128+
"DYNAMODB_TABLE": TABLE_NAME,
129+
"AWS_DEFAULT_REGION": "eu-west-2",
130+
},
131+
clear=True,
132+
):
133+
from api.createProductTeam.index import handler
134+
135+
result = handler(
136+
event={
137+
"headers": {"version": version},
138+
"body": json.dumps(CPM_PRODUCT_TEAM_NO_ID_DUPED_KEYS),
139+
}
140+
)
141+
result_body = json_loads(result["body"])
142+
expected_body = json.dumps(
143+
{
144+
"id": result_body["id"],
145+
"name": "FOOBAR Product Team",
146+
"ods_code": "F5H1R",
147+
"status": "active",
148+
"created_on": result_body["created_on"],
149+
"updated_on": None,
150+
"deleted_on": None,
151+
"keys": [{"key_type": "product_team_id_alias", "key_value": "BAR"}],
152+
}
153+
)
154+
expected = {
155+
"statusCode": 201,
156+
"body": expected_body,
157+
"headers": {
158+
"Content-Length": str(len(expected_body)),
159+
"Content-Type": "application/json",
160+
"Version": version,
161+
"Location": None,
162+
},
163+
}
164+
_response_assertions(
165+
result=result, expected=expected, check_body=True, check_content_length=True
166+
)

src/api/tests/feature_tests/features/createProductTeam.success.feature

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,43 @@ Feature: Create Product Team - success scenarios
4040
| partOf.identifier.system | https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations |
4141
| partOf.identifier.value | F5H1R |
4242

43+
Scenario: Successfully create a ProductTeam with duplicated keys
44+
When I make a "POST" request with "default" headers to "ProductTeam" with body:
45+
| path | value |
46+
| name | My Great Product Team |
47+
| ods_code | F5H1R |
48+
| keys.0.key_type | product_team_id_alias |
49+
| keys.0.key_value | FOOBAR |
50+
| keys.1.key_type | product_team_id_alias |
51+
| keys.1.key_value | FOOBAR |
52+
| keys.2.key_type | product_team_id_alias |
53+
| keys.2.key_value | FOOBAR |
54+
Then I receive a status code "201" with body where "keys" has a length of "1"
55+
| path | key_value |
56+
| id | << ignore >> |
57+
| name | My Great Product Team |
58+
| ods_code | F5H1R |
59+
| status | active |
60+
| created_on | << ignore >> |
61+
| updated_on | << ignore >> |
62+
| deleted_on | << ignore >> |
63+
| keys.0.key_type | product_team_id_alias |
64+
| keys.0.key_value | FOOBAR |
65+
And the response headers contain:
66+
| name | value |
67+
| Content-Type | application/json |
68+
| Content-Length | 288 |
69+
Given I note the response field "$.id" as "product_team_id"
70+
When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }"
71+
Then I receive a status code "200" with body
72+
| path | value |
73+
| resourceType | Organization |
74+
| identifier.0.system | connecting-party-manager/product-team-id |
75+
| identifier.0.value | ${ note(product_team_id) } |
76+
| name | My Great Product Team |
77+
| partOf.identifier.system | https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations |
78+
| partOf.identifier.value | F5H1R |
79+
4380
Scenario: Successfully create a ProductTeam and view by alias
4481
When I make a "POST" request with "default" headers to "ProductTeam" with body:
4582
| path | value |

src/api/tests/feature_tests/steps/steps.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,35 @@ def then_response(context: Context, status_code: str):
191191
)
192192

193193

194+
@then(
195+
'I receive a status code "{status_code}" with body where "{list_to_check}" has a length of "{count}"'
196+
)
197+
def then_response(context: Context, status_code: str, list_to_check: str, count: str):
198+
expected_body = parse_table(table=context.table, context=context)
199+
try:
200+
response_body = context.response.json()
201+
except JSONDecodeError:
202+
response_body = context.response.text
203+
assert len(response_body[list_to_check]) == int(count)
204+
assert_many(
205+
assertions=(
206+
assert_equal,
207+
assert_same_type,
208+
assert_equal,
209+
),
210+
expected=(
211+
int(status_code),
212+
expected_body,
213+
expected_body,
214+
),
215+
received=(
216+
context.response.status_code,
217+
response_body,
218+
response_body,
219+
),
220+
)
221+
222+
194223
@then(
195224
'I receive a status code "{status_code}" with a "{entity_type}" search body reponse that contains'
196225
)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"keys": [
3+
{
4+
"key_type": "product_team_id_alias",
5+
"key_value": "BAR"
6+
},
7+
{
8+
"key_type": "product_team_id_alias",
9+
"key_value": "BAR"
10+
},
11+
{
12+
"key_type": "product_team_id_alias",
13+
"key_value": "BAR"
14+
},
15+
{
16+
"key_type": "product_team_id_alias",
17+
"key_value": "BAR"
18+
}
19+
],
20+
"ods_code": "F5H1R",
21+
"name": "FOOBAR Product Team"
22+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"keys": [
3+
{
4+
"key_type": "product_team_id_alias",
5+
"key_value": "BAR"
6+
},
7+
{
8+
"key_type": "product_team_alias",
9+
"key_value": "FOO"
10+
}
11+
],
12+
"ods_code": "F5H1R",
13+
"name": "FOOBAR Product Team"
14+
}

src/layers/domain/request_models/tests/test_parse_product_team_params.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
CPM_PRODUCT_TEAM_EXTRA_PARAMS,
77
CPM_PRODUCT_TEAM_ID,
88
CPM_PRODUCT_TEAM_NO_ID,
9+
CPM_PRODUCT_TEAM_NO_ID_DUPED_KEYS,
10+
CPM_PRODUCT_TEAM_NO_ID_KEYS_NOT_ALLOWED,
911
)
1012

1113

@@ -29,3 +31,19 @@ def test_validate_product_team_raises_no_extra_fields():
2931
CreateProductTeamIncomingParams(**CPM_PRODUCT_TEAM_EXTRA_PARAMS)
3032

3133
assert exc.value.model is CreateProductTeamIncomingParams
34+
35+
36+
def test_validate_product_team_raises_no_extra_keys():
37+
with pytest.raises(ValidationError) as exc:
38+
CreateProductTeamIncomingParams(**CPM_PRODUCT_TEAM_NO_ID_KEYS_NOT_ALLOWED)
39+
40+
assert exc.value.model is CreateProductTeamIncomingParams
41+
42+
43+
def test_product_team_duped_keys():
44+
product_team = CreateProductTeamIncomingParams(**CPM_PRODUCT_TEAM_NO_ID_DUPED_KEYS)
45+
assert isinstance(product_team, CreateProductTeamIncomingParams)
46+
assert len(product_team.keys) == 1
47+
assert product_team.keys[0] == CPM_PRODUCT_TEAM_NO_ID["keys"][0]
48+
assert product_team.ods_code == CPM_PRODUCT_TEAM_NO_ID["ods_code"]
49+
assert product_team.name == CPM_PRODUCT_TEAM_NO_ID["name"]

src/layers/domain/request_models/v1.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,10 @@ class CreateProductTeamIncomingParams(BaseModel, extra=Extra.forbid):
1919
ods_code: str = Field(...)
2020
name: str = Field(...)
2121
keys: list[ProductTeamKey] = Field(default_factory=list)
22+
23+
def __init__(self, **data):
24+
super().__init__(**data)
25+
# Deduplicate the list of keys
26+
self.keys = list(
27+
{frozenset(key.dict().items()): key for key in self.keys}.values()
28+
)

src/test_helpers/sample_data.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ def _read_core_test_data(file_name: str) -> dict | list:
2828
CPM_PRODUCT_TEAM_NO_ID = _read_core_test_data(
2929
f"{PATH_TO_CORE_CPM_TEST_DATA}/cpm-product-team-example-no-id.json"
3030
)
31+
CPM_PRODUCT_TEAM_NO_ID_KEYS_NOT_ALLOWED = _read_core_test_data(
32+
f"{PATH_TO_CORE_CPM_TEST_DATA}/cpm-product-team-example-no-id-keys-not-allowed.json"
33+
)
34+
CPM_PRODUCT_TEAM_NO_ID_DUPED_KEYS = _read_core_test_data(
35+
f"{PATH_TO_CORE_CPM_TEST_DATA}/cpm-product-team-example-no-id-duped-keys.json"
36+
)
3137
CPM_PRODUCT_TEAM_EXTRA_PARAMS = _read_core_test_data(
3238
f"{PATH_TO_CORE_CPM_TEST_DATA}/cpm-product-team-example-extra.json"
3339
)

0 commit comments

Comments
 (0)