Skip to content

Commit 777541a

Browse files
Merge pull request #1195 from NHSDigital/NRL-2100-update-smoke-tests-v2
NRL-2100 Update smoke tests to run for both v1 & v2 perms
2 parents ca3603a + ef29c25 commit 777541a

9 files changed

Lines changed: 405 additions & 34 deletions

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ SHELL := /bin/bash
77

88
DIST_PATH ?= ./dist
99
TEST_ARGS ?= --cov --cov-report=term-missing --cov-report=xml:$(DIST_PATH)/test-coverage.xml
10-
SMOKE_TEST_ARGS ?=
10+
SMOKE_TEST_ARGS ?= -s ./tests/smoke/scenarios/*
1111
FEATURE_TEST_ARGS ?= ./tests/features
1212
TF_WORKSPACE_NAME ?= $(shell terraform -chdir=terraform/infrastructure workspace show)
1313
ENV ?= dev
@@ -149,14 +149,14 @@ test-smoke-internal: check-warn ## Run the smoke tests against the internal envi
149149
TEST_STACK_NAME=$(TF_WORKSPACE_NAME) \
150150
TEST_STACK_DOMAIN=$(shell terraform -chdir=terraform/infrastructure output -raw domain 2>/dev/null) \
151151
TEST_CONNECT_MODE="internal" \
152-
pytest ./tests/smoke/scenarios/* $(SMOKE_TEST_ARGS)
152+
pytest $(SMOKE_TEST_ARGS)
153153

154154
test-smoke-public: check-warn ## Run the smoke tests for the external access points
155155
@echo "Running smoke tests for the public endpoints ${ENV}"
156156
TEST_ENVIRONMENT_NAME=$(ENV) \
157157
TEST_STACK_NAME=$(TF_WORKSPACE_NAME) \
158158
TEST_CONNECT_MODE="public" \
159-
pytest ./tests/smoke/scenarios/* $(SMOKE_TEST_ARGS)
159+
pytest $(SMOKE_TEST_ARGS)
160160

161161
test-performance-prepare:
162162
mkdir -p $(DIST_PATH)

scripts/get_s3_permissions.py

Lines changed: 103 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ def add_feature_test_files(local_path):
169169
"v2-z00z-y11y-x22x",
170170
"V1ONLY0D5",
171171
[PointerTypes.LLOYD_GEORGE_FOLDER.value],
172-
[],
173172
), # http://snomed.info/sct|16521000000101
174173
]
175174
[
@@ -178,11 +177,108 @@ def add_feature_test_files(local_path):
178177
ods_code,
179178
pointer_types,
180179
)
181-
for app_id, ods_code, pointer_types, access_controls in v1_permissions
180+
for app_id, ods_code, pointer_types in v1_permissions
181+
]
182+
183+
184+
def add_smoke_test_files(secretsmanager, local_path, env_name):
185+
"""Bake in v2 permissions for the smoke test application so that the
186+
v2 permissions model can be proven via smoke tests without
187+
requiring a dynamic layer rebuild between test setup and test execution.
188+
"""
189+
190+
parameters_name = f"nhsd-nrlf--{env_name}--smoke-test-parameters"
191+
192+
secret_value = secretsmanager.get_secret_value(SecretId=parameters_name)
193+
parameters = json.loads(secret_value["SecretString"])
194+
smoke_test_app_id = parameters.get("nrlf_app_id")
195+
196+
print("Adding smoke test v2 permissions to temporary directory...")
197+
org_permissions = {
198+
"consumer": [
199+
(
200+
smoke_test_app_id,
201+
"SMOKETEST",
202+
[
203+
PointerTypes.MENTAL_HEALTH_PLAN.value
204+
], # http://snomed.info/sct|736253002
205+
[],
206+
),
207+
],
208+
"producer": [
209+
(
210+
smoke_test_app_id,
211+
"SMOKETEST",
212+
[
213+
PointerTypes.MENTAL_HEALTH_PLAN.value
214+
], # http://snomed.info/sct|736253002
215+
[],
216+
),
217+
(
218+
# For public tests - don't have a separate apigee app for 1DSync
219+
smoke_test_app_id,
220+
"SMOKETEST1DSYNC",
221+
[],
222+
[AccessControls.ALLOW_ALL_TYPES.value],
223+
),
224+
],
225+
}
226+
[
227+
_write_permission_file(
228+
Path.joinpath(local_path, actor_type, app_id),
229+
ods_code,
230+
pointer_types,
231+
access_controls,
232+
)
233+
for actor_type, entries in org_permissions.items()
234+
for app_id, ods_code, pointer_types, access_controls in entries
235+
]
236+
app_permissions = {
237+
"producer": [
238+
(
239+
"SMOKETEST1DSYNC",
240+
[],
241+
[AccessControls.ALLOW_ALL_TYPES.value],
242+
),
243+
],
244+
}
245+
[
246+
_write_permission_file(
247+
Path.joinpath(local_path, actor_type),
248+
app_id,
249+
pointer_types,
250+
access_controls,
251+
)
252+
for actor_type, entries in app_permissions.items()
253+
for app_id, pointer_types, access_controls in entries
254+
]
255+
256+
print("Adding smoke test v1 permissions to temporary directory...")
257+
v1_permissions = [
258+
( # not needed, won't hit this file
259+
"SMOKETEST1DSYNCV1",
260+
"SMOKETEST",
261+
[],
262+
),
263+
(
264+
smoke_test_app_id,
265+
"SMOKETESTV1",
266+
[PointerTypes.MENTAL_HEALTH_PLAN.value], # http://snomed.info/sct|736253002
267+
),
268+
]
269+
[
270+
_write_v1_permission_file(
271+
Path.joinpath(local_path, app_id),
272+
ods_code,
273+
pointer_types,
274+
)
275+
for app_id, ods_code, pointer_types in v1_permissions
182276
]
183277

184278

185-
def download_files(s3_client, bucket_name, local_path, file_names, folders):
279+
def download_files(
280+
s3_client, bucket_name, local_path, file_names, folders, secretsmanager, env_name
281+
):
186282
print(f"Downloading {len(file_names)} S3 files to temporary directory...")
187283
local_path = Path(local_path)
188284

@@ -199,6 +295,7 @@ def download_files(s3_client, bucket_name, local_path, file_names, folders):
199295

200296
add_test_files("K6PerformanceTest", "Y05868.json", local_path)
201297
add_feature_test_files(local_path)
298+
add_smoke_test_files(secretsmanager, local_path, env_name)
202299

203300

204301
def main(use_shared_resources: str, env: str, workspace: str, path_to_store: str):
@@ -210,12 +307,15 @@ def main(use_shared_resources: str, env: str, workspace: str, path_to_store: str
210307
s3 = boto_session.client("s3")
211308
files, folders = get_file_folders(s3, bucket)
212309

310+
secretsmanager = boto_session.client("secretsmanager", region_name="eu-west-2")
213311
download_files(
214312
s3,
215313
bucket,
216314
path.abspath(path.join(path_to_store + "/nrlf_permissions")),
217315
files,
218316
folders,
317+
secretsmanager,
318+
env_name=env,
219319
)
220320
print("Downloaded S3 permissions...")
221321

tests/smoke/conftest.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pytest
55

66
from scripts.aws_session_assume import get_boto_session
7-
from tests.smoke.environment import EnvironmentConfig, SmokeTestParameters
7+
from tests.smoke.environment import ConnectMode, EnvironmentConfig, SmokeTestParameters
88
from tests.utilities.api_clients import ConsumerTestClient, ProducerTestClient
99

1010

@@ -50,6 +50,32 @@ def consumer_client(
5050
)
5151

5252

53+
@pytest.fixture(autouse=True, scope="session")
54+
def producer_client_v1(
55+
environment_config: EnvironmentConfig, smoke_test_parameters: SmokeTestParameters
56+
) -> ProducerTestClient:
57+
config = environment_config.to_client_config(smoke_test_parameters)
58+
if environment_config.connect_mode == ConnectMode.INTERNAL:
59+
config.connection_metadata.ods_code = smoke_test_parameters.v1_ods_code
60+
config.custom_headers["NHSD-End-User-Organisation-ODS"] = (
61+
smoke_test_parameters.v1_ods_code
62+
)
63+
return ProducerTestClient(config=config)
64+
65+
66+
@pytest.fixture(autouse=True, scope="session")
67+
def consumer_client_v1(
68+
environment_config: EnvironmentConfig, smoke_test_parameters: SmokeTestParameters
69+
) -> ConsumerTestClient:
70+
config = environment_config.to_client_config(smoke_test_parameters)
71+
if environment_config.connect_mode == ConnectMode.INTERNAL:
72+
config.connection_metadata.ods_code = smoke_test_parameters.v1_ods_code
73+
config.custom_headers["NHSD-End-User-Organisation-ODS"] = (
74+
smoke_test_parameters.v1_ods_code
75+
)
76+
return ConsumerTestClient(config=config)
77+
78+
5379
@pytest.fixture
5480
def test_nhs_numbers(smoke_test_parameters: SmokeTestParameters) -> list[str]:
5581
return smoke_test_parameters.test_nhs_numbers

tests/smoke/environment.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def __init__(self, parameters: dict[str, str]):
1515
self.nrlf_app_id = parameters.get("nrlf_app_id")
1616
self.ods_code = parameters.get("ods_code")
1717
self.test_nhs_numbers = parameters.get("test_nhs_numbers").split(",")
18+
self.v1_ods_code = "SMOKETESTV1"
1819

1920

2021
class ConnectMode(Enum):
@@ -50,7 +51,7 @@ def to_client_config(self, parameters: SmokeTestParameters):
5051
}
5152
)
5253

53-
smoketest_id = str(uuid.uuid4())
54+
smoketest_id = f"SMOKETEST-{str(uuid.uuid4())}"
5455
env_resources_name = self.env_name.split("-")[0]
5556

5657
if self.connect_mode == ConnectMode.INTERNAL.value:
Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import copy
2+
13
import pytest
24

3-
from nrlf.core.constants import PERMISSION_ALLOW_ALL_POINTER_TYPES
45
from tests.smoke.environment import ConnectMode, EnvironmentConfig, SmokeTestParameters
56
from tests.smoke.setup import build_document_reference
67
from tests.utilities.api_clients import ProducerTestClient
@@ -10,13 +11,13 @@
1011
def producer_client_1dsync(
1112
environment_config: EnvironmentConfig, smoke_test_parameters: SmokeTestParameters
1213
) -> ProducerTestClient:
13-
client_config = environment_config.to_client_config(smoke_test_parameters)
14+
custom_smoke_test_parameters = copy.copy(smoke_test_parameters)
15+
if environment_config.connect_mode == ConnectMode.INTERNAL.value:
16+
custom_smoke_test_parameters.nrlf_app_id = "SMOKETEST1DSYNC"
17+
18+
custom_smoke_test_parameters.ods_code = "SMOKETEST1DSYNC"
1419

15-
if environment_config.connect_mode == ConnectMode.INTERNAL:
16-
client_config.connection_metadata["nrl.permissions"] = [
17-
PERMISSION_ALLOW_ALL_POINTER_TYPES
18-
]
19-
client_config.connection_metadata["nrl.app-id"] = "SMOKETEST_1DSYNC"
20+
client_config = environment_config.to_client_config(custom_smoke_test_parameters)
2021

2122
return ProducerTestClient(config=client_config)
2223

@@ -29,27 +30,25 @@ def test_smoke_1dsync_upsert_delete(
2930
"""
3031
Smoke test scenario for 1dsync upsert and delete behaviour
3132
"""
32-
test_ods_code = smoke_test_parameters.ods_code
33+
test_ods_code = "SMOKETEST1DSYNC"
3334
test_docref = build_document_reference(
3435
nhs_number=test_nhs_numbers[0], custodian=test_ods_code
3536
)
3637

3738
for attempts in range(0, 5):
38-
try:
39-
test_docref.id = (
40-
f"{test_ods_code}-smoketest_1dsync_upsert_delete_pointer_{attempts}"
41-
)
42-
upsert_response = producer_client_1dsync.upsert(
43-
test_docref.model_dump(exclude_none=True)
44-
)
45-
assert upsert_response.ok
46-
assert upsert_response.headers["Location"].split("/")[-1] == test_docref.id
47-
finally:
48-
delete_response = producer_client_1dsync.delete(test_docref.id)
49-
50-
assert (
51-
delete_response.ok
52-
), f"Failed to delete document reference with ID: {test_docref.id}. It will need to be deleted manually if it still exists."
53-
54-
read_response = producer_client_1dsync.read(test_docref.id)
55-
assert read_response.status_code == 404
39+
test_docref.id = (
40+
f"{test_ods_code}-smoketest_1dsync_upsert_delete_pointer_{attempts}"
41+
)
42+
upsert_response = producer_client_1dsync.upsert(
43+
test_docref.model_dump(exclude_none=True)
44+
)
45+
assert upsert_response.ok
46+
assert upsert_response.headers["Location"].split("/")[-1] == test_docref.id
47+
delete_response = producer_client_1dsync.delete(test_docref.id)
48+
49+
assert (
50+
delete_response.ok
51+
), f"Failed to delete document reference with ID: {test_docref.id}. It will need to be deleted manually if it still exists."
52+
53+
read_response = producer_client_1dsync.read(test_docref.id)
54+
assert read_response.status_code == 404
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import pytest
2+
3+
from nrlf.core.constants import PERMISSION_ALLOW_ALL_POINTER_TYPES, V2Headers
4+
from tests.smoke.environment import ConnectMode, EnvironmentConfig, SmokeTestParameters
5+
from tests.smoke.setup import build_document_reference
6+
from tests.utilities.api_clients import ConnectionMetadata, ProducerTestClient
7+
8+
v1_1dsync_app_id = "SMOKETEST1DSYNCV1"
9+
10+
11+
@pytest.fixture
12+
def producer_client_1dsync_v1(
13+
environment_config: EnvironmentConfig, smoke_test_parameters: SmokeTestParameters
14+
) -> ProducerTestClient:
15+
client_config = environment_config.to_client_config(smoke_test_parameters)
16+
17+
if environment_config.connect_mode == ConnectMode.INTERNAL.value:
18+
connection_metadata = ConnectionMetadata.model_validate(
19+
{
20+
"nrl.permissions": [PERMISSION_ALLOW_ALL_POINTER_TYPES],
21+
"nrl.app-id": v1_1dsync_app_id,
22+
"nrl.ods-code": smoke_test_parameters.ods_code,
23+
"client_rp_details": {
24+
"developer.app.name": smoke_test_parameters.apigee_app_name,
25+
"developer.app.id": smoke_test_parameters.apigee_app_id,
26+
},
27+
}
28+
)
29+
client_config.connection_metadata = connection_metadata
30+
client_config.custom_headers[V2Headers.X_PROXYGEN_APP_NRL_APP_ID] = (
31+
v1_1dsync_app_id
32+
)
33+
34+
return ProducerTestClient(config=client_config)
35+
36+
37+
def test_smoke_1dsync_upsert_delete_v1(
38+
producer_client_1dsync_v1: ProducerTestClient,
39+
smoke_test_parameters: SmokeTestParameters,
40+
test_nhs_numbers: list[str],
41+
):
42+
"""
43+
Smoke test scenario for 1dsync upsert and delete behaviour
44+
"""
45+
test_ods_code = smoke_test_parameters.ods_code
46+
test_docref = build_document_reference(
47+
nhs_number=test_nhs_numbers[0], custodian=test_ods_code
48+
)
49+
50+
for attempts in range(0, 5):
51+
try:
52+
test_docref.id = (
53+
f"{test_ods_code}-smoketest_1dsync_upsert_delete_pointer_{attempts}"
54+
)
55+
upsert_response = producer_client_1dsync_v1.upsert(
56+
test_docref.model_dump(exclude_none=True)
57+
)
58+
assert upsert_response.ok
59+
assert upsert_response.headers["Location"].split("/")[-1] == test_docref.id
60+
finally:
61+
delete_response = producer_client_1dsync_v1.delete(test_docref.id)
62+
63+
assert (
64+
delete_response.ok
65+
), f"Failed to delete document reference with ID: {test_docref.id}. It will need to be deleted manually if it still exists."
66+
67+
read_response = producer_client_1dsync_v1.read(test_docref.id)
68+
assert read_response.status_code == 404

0 commit comments

Comments
 (0)