Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ export const getRecordsFromExceptionManagementService = (

export const getRecordsFromNemsSubscription = (
request: APIRequestContext,
id: string
nhsNumbers: string
): Promise<ApiResponse> => {
return apiClient.get(request, `${config.endpointNemsSubscriptionDataDataService}api/${config.nemsSubscriberDataService}${id}`);
return apiClient.get(request, `${config.endpointNemsSubscriptionDataDataService}api/${config.nemsSubscriberDataService}?nhsNumber=${nhsNumbers}`);
};

export function extractSubscriptionID(response: ApiResponse): string | null {
Expand Down Expand Up @@ -115,3 +115,34 @@ export const invalidServiceNowEndpoint = (
return apiClient.post(request, endpoint, payload);
};

export async function retry<T>(
fn: () => Promise<T>,
validate: (result: T) => boolean,
options?: {
retries?: number;
delayMs?: number;
throwLastError?: boolean;
}
): Promise<T> {
const { retries = 5, delayMs = 2000, throwLastError = true } = options || {};
let lastError: any;
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const result = await fn();
if (validate(result)) {
return result;
}
} catch (err) {
lastError = err;
}
if (attempt < retries) {
await new Promise(res => setTimeout(res, delayMs));
}
}
if (throwLastError && lastError) {
throw lastError;
}
throw new Error(`Retry validation failed after ${retries} attempts`);
}


2 changes: 1 addition & 1 deletion tests/playwright-tests/src/config/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const config = {
routeBsSelectUnblockParticipant: 'api/UnblockParticipant',
routeGetValidationExceptions: 'api/GetValidationExceptions',
routeSerNowReceiveParticipant: 'api/servicenow/receive',
nemsSubscriberDataService: 'CheckSubscriptionStatus?nhsNumber=',
nemsSubscriberDataService: 'CheckSubscriptionStatus',
invalidRouteSerNowEndpoint: 'api/serviceno/receive',
cohortDistributionService: 'CohortDistributionDataService',
participantManagementService: 'ParticipantManagementDataService',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"inputParticipantRecord_test": {
"inputParticipantRecord": {
"number": "CS0573846",
"u_case_variable_data": {
"nhs_number": "9997160908",
"forename_": "Jane",
"surname_family_name": "Doe",
"date_of_birth": "2010-10-22",
"enter_dummy_gp_code": "ZZZDKL",
"enter_dummy_gp_code": "",
"BSO_code": "NORTH NOTTINGHAMSHIRE BREAST SCREENING OFFICE",
"reason_for_adding": "requires_ceasing_following_surgery_bilateral_mastectomy"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect, test } from '../../fixtures/test-fixtures';
import { extractSubscriptionID, getRecordsFromNemsSubscription, getRecordsFromParticipantDemographicService, getRecordsFromParticipantManagementService, receiveParticipantViaServiceNow } from "../../../api/distributionService/bsSelectService";
import { extractSubscriptionID, getRecordsFromNemsSubscription, getRecordsFromParticipantDemographicService, getRecordsFromParticipantManagementService, receiveParticipantViaServiceNow, retry } from "../../../api/distributionService/bsSelectService";
import { composeValidators, expectStatus } from "../../../api/responseValidators";
import { ParticipantRecord } from '../../../interface/InputData';
import { loadParticipantPayloads } from '../../fixtures/jsonDataReader';
Expand All @@ -8,10 +8,10 @@ test.describe('@DTOSS-3881-01 @e2e @epic4c- Cohort Manger subscribed the Added r

let participantData: Record<string, ParticipantRecord>;

test.beforeAll(() => {
test.beforeAll(async () => {
const folderName = '@DTOSS-3881-01';
const fileName = 'ADD-participantPayload.json';
participantData = loadParticipantPayloads(folderName, fileName);
participantData = await loadParticipantPayloads(folderName, fileName);
});

test('@DTOSS-3881-01 DTOSS-10011 @not-runner-based - Verify subscription IDs on Nems table for ADD', {
Expand All @@ -22,7 +22,7 @@ test.describe('@DTOSS-3881-01 @e2e @epic4c- Cohort Manger subscribed the Added r
}, async ({ request }, testInfo) => {

await test.step('Given Cohort manager receives data from ServiceNow and subscribed to PDS', async () => {
const payload = participantData['inputParticipantRecord_test'];
const payload = participantData['inputParticipantRecord'];
const response = await receiveParticipantViaServiceNow(request, payload);
const validators = composeValidators(
expectStatus(202)
Expand All @@ -31,55 +31,44 @@ test.describe('@DTOSS-3881-01 @e2e @epic4c- Cohort Manger subscribed the Added r
});

await test.step('Then NHSNumber, GivenName, FamilyName is written to Participant Demographic table', async () => {
const response = await getRecordsFromParticipantDemographicService(request);

const response = await retry(
() => getRecordsFromParticipantDemographicService(request),
(res) =>
res?.data?.[0]?.NhsNumber === 9997160908 &&
res?.data?.[0]?.GivenName === "Jane" &&
res?.data?.[0]?.FamilyName === "Doe",
{ retries: 5, delayMs: 2000 }
);
expect(response?.data?.[0]?.NhsNumber).toBe(9997160908);
expect(response?.data?.[0]?.GivenName).toBe("Jane");
expect(response?.data?.[0]?.FamilyName).toBe("Doe");
});

await test.step('And NHSNumber, ScreeningId, ReferralFlag is written to Participant Management table', async () => {
const response = await getRecordsFromParticipantManagementService(request);
const response = await retry(
() => getRecordsFromParticipantManagementService(request),
(res) =>
res?.data?.[0]?.NHSNumber === 9997160908 &&
res?.data?.[0]?.ScreeningId === 1 &&
res?.data?.[0]?.ReferralFlag === 1,
{ retries: 5, delayMs: 2000 }
);
expect(response?.data?.[0]?.NHSNumber).toBe(9997160908);
expect(response?.data?.[0]?.ScreeningId).toBe(1);
expect(response?.data?.[0]?.ReferralFlag).toBe(1);
});

await test.step('Assert that NemsSubscription service is available', async () => {
const nhsNumber = participantData['inputParticipantRecord_test'].u_case_variable_data.nhs_number;
await test.step('DTOSS-10012 ADD verify NemsSubscription in NEMS_SUBSCRIPTION table', async () => {
const nhsNumber = participantData['inputParticipantRecord'].u_case_variable_data.nhs_number;
const response = await getRecordsFromNemsSubscription(request, nhsNumber);
const validators = composeValidators(
expectStatus(200)
);
await validators(response);
});

await test.step(`DTOSS-10012 ADD verify NemsSubscription in NEMS_SUBSCRIPTION table`, async () => {
const nhsNumber = participantData['inputParticipantRecord_test'].u_case_variable_data.nhs_number;

const response = await getRecordsFromNemsSubscription(request, nhsNumber);
const subscriptionID = extractSubscriptionID(response);
expect(response.status).toBe(200);
expect(subscriptionID).not.toBeNull();

console.log(`Extracted Subscription ID: ${subscriptionID} for NHS number: ${nhsNumber}`);
});
});

test('@DTOSS-3881-02 DTOSS-10013 @not-runner-based AMEND verify NemsSubscription_id in NEMS_SUBSCRIPTION table', {
annotation: [{
type: 'Requirement - https://nhsd-jira.digital.nhs.uk/browse/DTOSS-3881',
description: 'Tests - https://nhsd-jira.digital.nhs.uk/browse/DTOSS-10013',
}]
}, async ({ request }, testInfo) => {

const nhsNumber = '9996534472';

const response = await getRecordsFromNemsSubscription(request, nhsNumber);
const subscriptionID = extractSubscriptionID(response);
expect(response.status).toBe(200);
expect(subscriptionID).not.toBeNull();

console.log(`Extracted Subscription ID: ${subscriptionID} for NHS number: ${nhsNumber}`);
});
});
8 changes: 4 additions & 4 deletions tests/playwright-tests/src/tests/fixtures/jsonDataReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import { config } from '../../config/env';
import { ParticipantRecord } from '../../interface/InputData';


export function loadParticipantPayloads(folderName: string, fileName: string): Record<string, ParticipantRecord> {
export async function loadParticipantPayloads(folderName: string, fileName: string): Promise<Record<string, ParticipantRecord>> {
const fullPath = path.join(process.cwd(), config.participantPayloadPath, folderName, fileName);
if (!fs.existsSync(fullPath)) {
throw new Error(`File not found: ${fullPath}`);
throw new Error(`File not found: ${fullPath}`);
}
const rawData = fs.readFileSync(fullPath, 'utf-8');
const rawData = await fs.readFileSync(fullPath, 'utf-8');
return JSON.parse(rawData);
}

export function omitField<T extends object>(obj: T, fieldPath: string): Partial<T> {
export async function omitField<T extends object>(obj: T, fieldPath: string): Promise<Partial<T>> {
const result = JSON.parse(JSON.stringify(obj));
const parts = fieldPath.split('.');
let current: any = result;
Expand Down
Loading