From c1b4d848997adc132c54e0d6d39ab2640747ec84 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Fri, 6 Feb 2026 12:15:41 +0000 Subject: [PATCH 01/27] CCM-14061: Initial routing config e2e test --- tests/security/functions/login.ts | 3 +- .../security/lifecycle/templates/teardown.ts | 14 ++- .../template-mgmt-cis2-login.security.ts | 4 +- .../domain/delete-client-templates.ts | 8 +- tests/test-team/fixtures/clients.ts | 15 ++++ tests/test-team/functions/login.ts | 3 +- tests/test-team/lifecycle/templates/setup.ts | 77 ++++++++++++++++- .../test-team/lifecycle/templates/teardown.ts | 14 ++- .../nhsapp-routing-config-e2e.ts | 85 +++++++++++++++++++ .../template-mgmt-cis2-login-e2e.ts | 4 +- 10 files changed, 205 insertions(+), 22 deletions(-) create mode 100644 tests/test-team/template-mgmt-e2e-tests/nhsapp-routing-config-e2e.ts diff --git a/tests/security/functions/login.ts b/tests/security/functions/login.ts index da92fada..daf5b22e 100644 --- a/tests/security/functions/login.ts +++ b/tests/security/functions/login.ts @@ -41,11 +41,10 @@ async function enterCis2TotpCodeWithRetry( } async function loginWithCis2( - basePage: TemplateMgmtBasePage, + page: Page, targetHeadingText: string ) { const cis2Credentials = await getCis2Credentials(); - const page = basePage.page; try { // Notify WebUI - Click the CIS2 login button diff --git a/tests/security/lifecycle/templates/teardown.ts b/tests/security/lifecycle/templates/teardown.ts index ed899f01..106e355c 100644 --- a/tests/security/lifecycle/templates/teardown.ts +++ b/tests/security/lifecycle/templates/teardown.ts @@ -3,7 +3,7 @@ import { parseSetupTeardownArgs, StateFile, deleteClientConfigs, - deleteClientTemplates, + deleteClientEntries, } from 'nhs-notify-system-tests-shared'; import z from 'zod'; @@ -48,13 +48,19 @@ async function main() { z.string().default('') ); - const deleted = await Promise.allSettled( + const deletedTemplates = await Promise.allSettled( [...clientIds, cis2ClientId].map((id) => - deleteClientTemplates(targetEnvrionment, id) + deleteClientEntries(id, `nhs-notify-${targetEnvrionment}-app-api-templates`) ) ); - const failures = deleted.flatMap((res) => + const deletedRoutingConfigs = await Promise.allSettled( + [...clientIds, cis2ClientId].map((id) => + deleteClientEntries(id, `nhs-notify-${targetEnvrionment}-app-api-routing-configuration`) + ) + ); + + const failures = [...deletedTemplates, ...deletedRoutingConfigs].flatMap((res) => res.status === 'rejected' ? [res.reason] : [] ); diff --git a/tests/security/tests/template-mgmt-cis2-login.security.ts b/tests/security/tests/template-mgmt-cis2-login.security.ts index f99bd8f0..96e1d7e8 100644 --- a/tests/security/tests/template-mgmt-cis2-login.security.ts +++ b/tests/security/tests/template-mgmt-cis2-login.security.ts @@ -46,7 +46,7 @@ test('User logs in via CIS2, saves data in templates, logs out and logs back in const name = 'E2E Name'; await startPage({ basePage, baseURL }); - await loginWithCis2(basePage, 'Message templates'); + await loginWithCis2(basePage.page, 'Message templates'); await startNewTemplate(props); await chooseTemplate(props, channel); await createTemplate(props, channel, channelPath, name); @@ -55,5 +55,5 @@ test('User logs in via CIS2, saves data in templates, logs out and logs back in await logOut(basePage); await page.waitForLoadState('networkidle'); await startPage({ basePage, baseURL }); - await loginWithCis2(basePage, 'Message templates'); + await loginWithCis2(basePage.page, 'Message templates'); }); diff --git a/tests/shared/setup-teardown/domain/delete-client-templates.ts b/tests/shared/setup-teardown/domain/delete-client-templates.ts index 3e055200..a47d8987 100644 --- a/tests/shared/setup-teardown/domain/delete-client-templates.ts +++ b/tests/shared/setup-teardown/domain/delete-client-templates.ts @@ -8,12 +8,10 @@ import { const client = new DynamoDBClient({ region: 'eu-west-2' }); -export async function deleteClientTemplates( - environment: string, - clientId: string +export async function deleteClientEntries( + clientId: string, + tableName: string, ): Promise { - const tableName = `nhs-notify-${environment}-app-api-templates`; - const input: QueryCommandInput = { TableName: tableName, KeyConditionExpression: '#owner = :owner', diff --git a/tests/test-team/fixtures/clients.ts b/tests/test-team/fixtures/clients.ts index 98cf4de9..8661770f 100644 --- a/tests/test-team/fixtures/clients.ts +++ b/tests/test-team/fixtures/clients.ts @@ -6,6 +6,7 @@ export const clients: Record = { campaignIds: ['ProductPrimary-Campaign'], features: { proofing: true, + routing: true, }, }, auth: { @@ -17,6 +18,7 @@ export const clients: Record = { campaignIds: ['Client2Product-Campaign'], features: { proofing: true, + routing: true, }, }, auth: { @@ -28,10 +30,23 @@ export const clients: Record = { campaignIds: ['Client3Product-Campaign'], features: { proofing: true, + routing: true, }, }, auth: { name: 'Client 3 Product', }, }, + RoutingDisabled: { + templates: { + campaignIds: ['RoutingDisabled-Campaign'], + features: { + proofing: true, + routing: false, + }, + }, + auth: { + name: 'Routing Disabled', + }, + }, }; diff --git a/tests/test-team/functions/login.ts b/tests/test-team/functions/login.ts index ed8bef64..4f3d27cf 100644 --- a/tests/test-team/functions/login.ts +++ b/tests/test-team/functions/login.ts @@ -46,11 +46,10 @@ async function enterCis2TotpCodeWithRetry( } async function loginWithCis2( - basePage: TemplateMgmtBasePage, + page: Page, targetHeadingText: string ) { const cis2Credentials = await getCis2Credentials(); - const page = basePage.page; try { // Notify WebUI - Click the CIS2 login button diff --git a/tests/test-team/lifecycle/templates/setup.ts b/tests/test-team/lifecycle/templates/setup.ts index 7cc14486..97459981 100644 --- a/tests/test-team/lifecycle/templates/setup.ts +++ b/tests/test-team/lifecycle/templates/setup.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto'; import { createClientConfig, increaseSftpPollingFrequency, @@ -5,6 +6,9 @@ import { parseSetupTeardownArgs, StateFile, getCis2ClientId, + TemplateFactory, + StorageHelper, + TemplateType, } from 'nhs-notify-system-tests-shared'; import { clients } from '../../fixtures/clients'; @@ -35,15 +39,86 @@ async function main() { ) ); + const clientIds = Object.fromEntries(clientEntries.map(([key, { id }]) => [key, id])); + stateFile.setValues( 'clientIds', - Object.fromEntries(clientEntries.map(([key, { id }]) => [key, id])) + clientIds, ); const cis2ClientId = await getCis2ClientId(); stateFile.setValue('cis2', 'notify-client-id', cis2ClientId); + const nhsAppRoutingConfigNhsAppTemplate = TemplateFactory.create( + randomUUID(), + clientIds['ProductPrimary'], + TemplateType.NHS_APP, + { + name: 'nhsapp-routing-config-nhsapp-template' + } + ); + stateFile.setValue('templates', 'nhsAppRoutingConfigNhsApp', nhsAppRoutingConfigNhsAppTemplate); + + const emailRoutingConfigEmailTemplate = TemplateFactory.create( + randomUUID(), + clientIds['ProductPrimary'], + TemplateType.EMAIL, + { + name: 'email-routing-config-email-template' + } + ); + stateFile.setValue('templates', 'emailRoutingConfigEmail', emailRoutingConfigEmailTemplate); + + const smsRoutingConfigSmsTemplate = TemplateFactory.create( + randomUUID(), + clientIds['ProductPrimary'], + TemplateType.SMS, + { + name: 'sms-routing-config-sms-template' + } + ); + stateFile.setValue('templates', 'smsRoutingConfigSms', smsRoutingConfigSmsTemplate); + + const multiChannelRoutingConfigNhsAppTemplate = TemplateFactory.create( + randomUUID(), + clientIds['ProductPrimary'], + TemplateType.NHS_APP, + { + name: 'multi-channel-routing-config-nhsapp-template' + } + ); + stateFile.setValue('templates', 'multiChannelRoutingConfigNhsApp', multiChannelRoutingConfigNhsAppTemplate); + + const multiChannelRoutingConfigEmailTemplate = TemplateFactory.create( + randomUUID(), + clientIds['ProductPrimary'], + TemplateType.EMAIL, + { + name: 'multi-channel-routing-config-email-template' + } + ); + stateFile.setValue('templates', 'multiChannelRoutingConfigEmail', multiChannelRoutingConfigEmailTemplate); + + const multiChannelRoutingConfigSmsTemplate = TemplateFactory.create( + randomUUID(), + clientIds['ProductPrimary'], + TemplateType.SMS, + { + name: 'multi-channel-routing-config-sms-template' + } + ); + stateFile.setValue('templates', 'multiChannelRoutingConfigSms', multiChannelRoutingConfigSmsTemplate); + + await new StorageHelper(`nhs-notify-${targetEnvrionment}-app-api-templates`, [ + nhsAppRoutingConfigNhsAppTemplate, + emailRoutingConfigEmailTemplate, + smsRoutingConfigSmsTemplate, + multiChannelRoutingConfigNhsAppTemplate, + multiChannelRoutingConfigEmailTemplate, + multiChannelRoutingConfigSmsTemplate, + ]).seedData(); + await stateFile.persist(); } diff --git a/tests/test-team/lifecycle/templates/teardown.ts b/tests/test-team/lifecycle/templates/teardown.ts index ed899f01..106e355c 100644 --- a/tests/test-team/lifecycle/templates/teardown.ts +++ b/tests/test-team/lifecycle/templates/teardown.ts @@ -3,7 +3,7 @@ import { parseSetupTeardownArgs, StateFile, deleteClientConfigs, - deleteClientTemplates, + deleteClientEntries, } from 'nhs-notify-system-tests-shared'; import z from 'zod'; @@ -48,13 +48,19 @@ async function main() { z.string().default('') ); - const deleted = await Promise.allSettled( + const deletedTemplates = await Promise.allSettled( [...clientIds, cis2ClientId].map((id) => - deleteClientTemplates(targetEnvrionment, id) + deleteClientEntries(id, `nhs-notify-${targetEnvrionment}-app-api-templates`) ) ); - const failures = deleted.flatMap((res) => + const deletedRoutingConfigs = await Promise.allSettled( + [...clientIds, cis2ClientId].map((id) => + deleteClientEntries(id, `nhs-notify-${targetEnvrionment}-app-api-routing-configuration`) + ) + ); + + const failures = [...deletedTemplates, ...deletedRoutingConfigs].flatMap((res) => res.status === 'rejected' ? [res.reason] : [] ); diff --git a/tests/test-team/template-mgmt-e2e-tests/nhsapp-routing-config-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/nhsapp-routing-config-e2e.ts new file mode 100644 index 00000000..fce8e2ca --- /dev/null +++ b/tests/test-team/template-mgmt-e2e-tests/nhsapp-routing-config-e2e.ts @@ -0,0 +1,85 @@ +/* eslint-disable security/detect-non-literal-regexp */ + +import path, { dirname } from 'node:path'; +import { expect, test } from '@playwright/test'; +import { StateFile } from 'nhs-notify-system-tests-shared'; +import z, { string } from 'zod'; + +test.use({ storageState: 'login-state/primary.json' }); + +const getSeededTemplateConfig = async (configFile: string | undefined) => { + + const projectRoot = path.resolve(dirname(configFile ?? ''), '..'); + + const templatesStateFile = new StateFile( + path.join(projectRoot, 'lifecycle', 'templates'), + process.env.RUN_ID + ); + + await templatesStateFile.loadFromDisk(); + + return templatesStateFile.getValue( + 'templates', + 'nhsAppRoutingConfigNhsApp', + z.object({ + id: z.string(), + name: string(), + message: string(), + }), + ); +} + +test(`User creates an NHS App routing config`, async ({ page, baseURL, }, { config: { configFile } }) => { + await page.goto(`${baseURL}/templates/message-plans`); + + await page.getByText('New message plan').click(); + + await expect(page).toHaveURL(`${baseURL}/templates/message-plans/choose-message-order`); + + await page.getByLabel('NHS App only').check(); + + await page.getByText('Save and continue').click(); + + await expect(page).toHaveURL(`${baseURL}/templates/message-plans/create-message-plan?messageOrder=NHSAPP`); + + await page.getByLabel('Message plan name').fill('message plan name'); + + await page.getByText('Save and continue').click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-templates/(.*)`)); + + const urlSegments = page.url().split('/'); + const routingConfigId = urlSegments[urlSegments.length - 1]; + + await page.getByTestId('choose-template-link-NHSAPP').click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-nhs-app-template/${routingConfigId}\?(.*)`)); + + const { id: templateId, name: templateName, message: templateMessage } = await getSeededTemplateConfig(configFile); + + await page.getByTestId(`${templateId}-preview-link`).click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-nhs-app-template/${routingConfigId}/preview-template/${templateId}\?(.*)`)); + + await expect(page.getByText(templateId)).toBeVisible(); + await expect(page.getByText(templateName)).toBeVisible(); + await expect(page.getByText(templateMessage)).toBeVisible(); + + await page.getByTestId('back-link-bottom').click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-nhs-app-template/${routingConfigId}\?(.*)`)); + + await page.getByTestId(`${templateId}-radio`).check(); + + await page.getByText('Save and continue').click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-templates/${routingConfigId}(.*)`)); + + await page.getByText('Move to production').click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/get-ready-to-move/${routingConfigId}(.*)`)); + + await page.getByText('Continue').click(); + + // remaining pages not ready yet +}); diff --git a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts index 9facdf89..e3726303 100644 --- a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts @@ -42,7 +42,7 @@ test('User logs in via CIS2, saves data in templates, logs out and logs back in const name = 'E2E Name'; await startPage({ basePage, baseURL }); - await loginWithCis2(basePage, 'Message templates'); + await loginWithCis2(basePage.page, 'Message templates'); await startNewTemplate(props); await chooseTemplate(props, channel); await createTemplate(props, channel, channelPath, name); @@ -51,5 +51,5 @@ test('User logs in via CIS2, saves data in templates, logs out and logs back in await logOut(basePage); await page.waitForLoadState('networkidle'); await startPage({ basePage, baseURL }); - await loginWithCis2(basePage, 'Message templates'); + await loginWithCis2(basePage.page, 'Message templates'); }); From 8e30a07e62d24c0cb05c2d7405ab1debb80ffa88 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Fri, 6 Feb 2026 12:31:18 +0000 Subject: [PATCH 02/27] CCM-14061: Fix file endings --- .../template-mgmt-e2e-tests/nhsapp-routing-config-e2e.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-team/template-mgmt-e2e-tests/nhsapp-routing-config-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/nhsapp-routing-config-e2e.ts index fce8e2ca..edee047d 100644 --- a/tests/test-team/template-mgmt-e2e-tests/nhsapp-routing-config-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/nhsapp-routing-config-e2e.ts @@ -8,9 +8,9 @@ import z, { string } from 'zod'; test.use({ storageState: 'login-state/primary.json' }); const getSeededTemplateConfig = async (configFile: string | undefined) => { - + const projectRoot = path.resolve(dirname(configFile ?? ''), '..'); - + const templatesStateFile = new StateFile( path.join(projectRoot, 'lifecycle', 'templates'), process.env.RUN_ID From 9ce20e5f7a30028c207ad3925000427f5cc17c52 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Fri, 6 Feb 2026 13:00:30 +0000 Subject: [PATCH 03/27] CCM-14061: Download templates state file --- .github/actions/product-tests/action.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/actions/product-tests/action.yaml b/.github/actions/product-tests/action.yaml index 4a8f761e..36632c50 100644 --- a/.github/actions/product-tests/action.yaml +++ b/.github/actions/product-tests/action.yaml @@ -35,6 +35,16 @@ runs: gh run download "${{ inputs.github_run_id }}" --repo "${{ inputs.github_repository }}" --name "$ARTIFACT_NAME" --dir "$DEST_PATH" shell: bash + - name: Download setup JSON artifact (templates service) + env: + GH_TOKEN: ${{ inputs.github_token }} + run: | + ARTIFACT_NAME="auth-state" + DEST_PATH="./tests/test-team/lifecycle/templates" + echo "Downloading artifact '$ARTIFACT_NAME' to $DEST_PATH ..." + gh run download "${{ inputs.github_run_id }}" --repo "${{ inputs.github_repository }}" --name "$ARTIFACT_NAME" --dir "$DEST_PATH" + shell: bash + - name: Run product tests shell: bash env: From 9baaa5e9b65ee74eb0f4e301b1e106d904942aa1 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Fri, 6 Feb 2026 13:01:16 +0000 Subject: [PATCH 04/27] CCM-14061: Download templates state file --- .github/actions/product-tests/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/product-tests/action.yaml b/.github/actions/product-tests/action.yaml index 36632c50..1f974cee 100644 --- a/.github/actions/product-tests/action.yaml +++ b/.github/actions/product-tests/action.yaml @@ -39,7 +39,7 @@ runs: env: GH_TOKEN: ${{ inputs.github_token }} run: | - ARTIFACT_NAME="auth-state" + ARTIFACT_NAME="templates-state" DEST_PATH="./tests/test-team/lifecycle/templates" echo "Downloading artifact '$ARTIFACT_NAME' to $DEST_PATH ..." gh run download "${{ inputs.github_run_id }}" --repo "${{ inputs.github_repository }}" --name "$ARTIFACT_NAME" --dir "$DEST_PATH" From 3114f8cd8c144e7c0e7f0c79c44400514309d214 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Fri, 6 Feb 2026 13:33:28 +0000 Subject: [PATCH 05/27] CCM-14061: Use multiple channels --- tests/test-team/fixtures/clients.ts | 12 +-- tests/test-team/lifecycle/templates/setup.ts | 42 ++------- ...ng-config-e2e.ts => routing-config-e2e.ts} | 92 +++++++++++++------ 3 files changed, 75 insertions(+), 71 deletions(-) rename tests/test-team/template-mgmt-e2e-tests/{nhsapp-routing-config-e2e.ts => routing-config-e2e.ts} (59%) diff --git a/tests/test-team/fixtures/clients.ts b/tests/test-team/fixtures/clients.ts index 8661770f..20389a31 100644 --- a/tests/test-team/fixtures/clients.ts +++ b/tests/test-team/fixtures/clients.ts @@ -6,7 +6,7 @@ export const clients: Record = { campaignIds: ['ProductPrimary-Campaign'], features: { proofing: true, - routing: true, + routing: false, }, }, auth: { @@ -18,7 +18,7 @@ export const clients: Record = { campaignIds: ['Client2Product-Campaign'], features: { proofing: true, - routing: true, + routing: false, }, }, auth: { @@ -30,19 +30,19 @@ export const clients: Record = { campaignIds: ['Client3Product-Campaign'], features: { proofing: true, - routing: true, + routing: false, }, }, auth: { name: 'Client 3 Product', }, }, - RoutingDisabled: { + RoutingEnabled: { templates: { - campaignIds: ['RoutingDisabled-Campaign'], + campaignIds: ['RoutingEnabled-Campaign'], features: { proofing: true, - routing: false, + routing: true, }, }, auth: { diff --git a/tests/test-team/lifecycle/templates/setup.ts b/tests/test-team/lifecycle/templates/setup.ts index 97459981..2e0fb80b 100644 --- a/tests/test-team/lifecycle/templates/setup.ts +++ b/tests/test-team/lifecycle/templates/setup.ts @@ -50,42 +50,13 @@ async function main() { stateFile.setValue('cis2', 'notify-client-id', cis2ClientId); - const nhsAppRoutingConfigNhsAppTemplate = TemplateFactory.create( - randomUUID(), - clientIds['ProductPrimary'], - TemplateType.NHS_APP, - { - name: 'nhsapp-routing-config-nhsapp-template' - } - ); - stateFile.setValue('templates', 'nhsAppRoutingConfigNhsApp', nhsAppRoutingConfigNhsAppTemplate); - - const emailRoutingConfigEmailTemplate = TemplateFactory.create( - randomUUID(), - clientIds['ProductPrimary'], - TemplateType.EMAIL, - { - name: 'email-routing-config-email-template' - } - ); - stateFile.setValue('templates', 'emailRoutingConfigEmail', emailRoutingConfigEmailTemplate); - - const smsRoutingConfigSmsTemplate = TemplateFactory.create( - randomUUID(), - clientIds['ProductPrimary'], - TemplateType.SMS, - { - name: 'sms-routing-config-sms-template' - } - ); - stateFile.setValue('templates', 'smsRoutingConfigSms', smsRoutingConfigSmsTemplate); - const multiChannelRoutingConfigNhsAppTemplate = TemplateFactory.create( randomUUID(), clientIds['ProductPrimary'], TemplateType.NHS_APP, { - name: 'multi-channel-routing-config-nhsapp-template' + name: 'multi-channel-routing-config-nhsapp-template', + message: 'multi-channel-routing-config-nhsapp-message', } ); stateFile.setValue('templates', 'multiChannelRoutingConfigNhsApp', multiChannelRoutingConfigNhsAppTemplate); @@ -95,7 +66,8 @@ async function main() { clientIds['ProductPrimary'], TemplateType.EMAIL, { - name: 'multi-channel-routing-config-email-template' + name: 'multi-channel-routing-config-email-template-name', + message: 'multi-channel-routing-config-email-template-message', } ); stateFile.setValue('templates', 'multiChannelRoutingConfigEmail', multiChannelRoutingConfigEmailTemplate); @@ -105,15 +77,13 @@ async function main() { clientIds['ProductPrimary'], TemplateType.SMS, { - name: 'multi-channel-routing-config-sms-template' + name: 'multi-channel-routing-config-sms-template-name', + message: 'multi-channel-routing-config-sms-template-message', } ); stateFile.setValue('templates', 'multiChannelRoutingConfigSms', multiChannelRoutingConfigSmsTemplate); await new StorageHelper(`nhs-notify-${targetEnvrionment}-app-api-templates`, [ - nhsAppRoutingConfigNhsAppTemplate, - emailRoutingConfigEmailTemplate, - smsRoutingConfigSmsTemplate, multiChannelRoutingConfigNhsAppTemplate, multiChannelRoutingConfigEmailTemplate, multiChannelRoutingConfigSmsTemplate, diff --git a/tests/test-team/template-mgmt-e2e-tests/nhsapp-routing-config-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts similarity index 59% rename from tests/test-team/template-mgmt-e2e-tests/nhsapp-routing-config-e2e.ts rename to tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts index edee047d..7a47c241 100644 --- a/tests/test-team/template-mgmt-e2e-tests/nhsapp-routing-config-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts @@ -1,7 +1,7 @@ /* eslint-disable security/detect-non-literal-regexp */ import path, { dirname } from 'node:path'; -import { expect, test } from '@playwright/test'; +import { expect, Page, test } from '@playwright/test'; import { StateFile } from 'nhs-notify-system-tests-shared'; import z, { string } from 'zod'; @@ -18,62 +18,96 @@ const getSeededTemplateConfig = async (configFile: string | undefined) => { await templatesStateFile.loadFromDisk(); - return templatesStateFile.getValue( + return templatesStateFile.getValues( 'templates', - 'nhsAppRoutingConfigNhsApp', - z.object({ + z.record(z.string(), z.object({ id: z.string(), name: string(), message: string(), - }), + })), ); } -test(`User creates an NHS App routing config`, async ({ page, baseURL, }, { config: { configFile } }) => { - await page.goto(`${baseURL}/templates/message-plans`); +const previewAndSelectTemplate = async ( + page: Page, + baseURL: string | undefined, + routingConfigId: string, + channel: string, + channelUrlSegment: string, + { id: templateId, name: templateName, message: templateMessage }: { id: string, name: string, message: string }, +) => { - await page.getByText('New message plan').click(); + await page.getByTestId(`choose-template-link-${channel}`).click(); - await expect(page).toHaveURL(`${baseURL}/templates/message-plans/choose-message-order`); + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}\?(.*)`)); - await page.getByLabel('NHS App only').check(); + await page.getByTestId(`${templateId}-preview-link`).click(); - await page.getByText('Save and continue').click(); + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}/preview-template/${templateId}\?(.*)`)); - await expect(page).toHaveURL(`${baseURL}/templates/message-plans/create-message-plan?messageOrder=NHSAPP`); + await expect(page.getByText(templateId)).toBeVisible(); + await expect(page.getByText(templateName)).toBeVisible(); + await expect(page.getByText(templateMessage)).toBeVisible(); - await page.getByLabel('Message plan name').fill('message plan name'); + await page.getByTestId('back-link-bottom').click(); - await page.getByText('Save and continue').click(); + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}\?(.*)`)); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-templates/(.*)`)); + await page.getByTestId(`${templateId}-radio`).check(); - const urlSegments = page.url().split('/'); - const routingConfigId = urlSegments[urlSegments.length - 1]; + await page.getByText('Save and continue').click(); - await page.getByTestId('choose-template-link-NHSAPP').click(); + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-templates/${routingConfigId}(.*)`)); +} - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-nhs-app-template/${routingConfigId}\?(.*)`)); +test(`User creates a multi-channel routing config`, async ({ page, baseURL, }, { config: { configFile } }) => { - const { id: templateId, name: templateName, message: templateMessage } = await getSeededTemplateConfig(configFile); + const templates = await getSeededTemplateConfig(configFile); + await page.goto(`${baseURL}/templates/message-plans`); - await page.getByTestId(`${templateId}-preview-link`).click(); + await page.getByText('New message plan').click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-nhs-app-template/${routingConfigId}/preview-template/${templateId}\?(.*)`)); + await expect(page).toHaveURL(`${baseURL}/templates/message-plans/choose-message-order`); - await expect(page.getByText(templateId)).toBeVisible(); - await expect(page.getByText(templateName)).toBeVisible(); - await expect(page.getByText(templateMessage)).toBeVisible(); + await page.getByLabel('NHS App, Email, Text message', { exact: true }).check(); - await page.getByTestId('back-link-bottom').click(); + await page.getByText('Save and continue').click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-nhs-app-template/${routingConfigId}\?(.*)`)); + await expect(page).toHaveURL(`${baseURL}/templates/message-plans/create-message-plan?messageOrder=NHSAPP%2CEMAIL%2CSMS`); - await page.getByTestId(`${templateId}-radio`).check(); + await page.getByLabel('Message plan name').fill('message plan name'); await page.getByText('Save and continue').click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-templates/${routingConfigId}(.*)`)); + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-templates/(.*)`)); + + const urlSegments = page.url().split('/'); + const routingConfigId = urlSegments[urlSegments.length - 1]; + + await previewAndSelectTemplate( + page, + baseURL, + routingConfigId, + 'NHSAPP', + 'nhs-app', + templates['multiChannelRoutingConfigNhsApp'] + ); + await previewAndSelectTemplate( + page, + baseURL, + routingConfigId, + 'EMAIL', + 'email', + templates['multiChannelRoutingConfigEmail'] + ); + await previewAndSelectTemplate( + page, + baseURL, + routingConfigId, + 'SMS', + 'text-message', + templates['multiChannelRoutingConfigSms'] + ); await page.getByText('Move to production').click(); From 5d469cf2cec42a8cfa2bba647360b72571d82374 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Fri, 6 Feb 2026 13:44:12 +0000 Subject: [PATCH 06/27] CCM-14061: Fix client ID --- tests/test-team/lifecycle/templates/setup.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test-team/lifecycle/templates/setup.ts b/tests/test-team/lifecycle/templates/setup.ts index 2e0fb80b..e6e981ad 100644 --- a/tests/test-team/lifecycle/templates/setup.ts +++ b/tests/test-team/lifecycle/templates/setup.ts @@ -52,7 +52,7 @@ async function main() { const multiChannelRoutingConfigNhsAppTemplate = TemplateFactory.create( randomUUID(), - clientIds['ProductPrimary'], + clientIds['RoutingEnabled'], TemplateType.NHS_APP, { name: 'multi-channel-routing-config-nhsapp-template', @@ -63,7 +63,7 @@ async function main() { const multiChannelRoutingConfigEmailTemplate = TemplateFactory.create( randomUUID(), - clientIds['ProductPrimary'], + clientIds['RoutingEnabled'], TemplateType.EMAIL, { name: 'multi-channel-routing-config-email-template-name', @@ -74,7 +74,7 @@ async function main() { const multiChannelRoutingConfigSmsTemplate = TemplateFactory.create( randomUUID(), - clientIds['ProductPrimary'], + clientIds['RoutingEnabled'], TemplateType.SMS, { name: 'multi-channel-routing-config-sms-template-name', From 1590324e83226cfedd512e0efadb73d7ef79efef Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Fri, 6 Feb 2026 14:00:39 +0000 Subject: [PATCH 07/27] CCM-14061: Fix user --- tests/test-team/fixtures/clients.ts | 2 +- tests/test-team/fixtures/users.ts | 4 ++++ tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test-team/fixtures/clients.ts b/tests/test-team/fixtures/clients.ts index 20389a31..3306bcd3 100644 --- a/tests/test-team/fixtures/clients.ts +++ b/tests/test-team/fixtures/clients.ts @@ -46,7 +46,7 @@ export const clients: Record = { }, }, auth: { - name: 'Routing Disabled', + name: 'Routing Enabled', }, }, }; diff --git a/tests/test-team/fixtures/users.ts b/tests/test-team/fixtures/users.ts index 964872bd..45f7e10f 100644 --- a/tests/test-team/fixtures/users.ts +++ b/tests/test-team/fixtures/users.ts @@ -14,4 +14,8 @@ export const users: Record = { clientKey: 'Client3Product', clientConfig: clients['Client3Product'].auth, }, + routingEnabled: { + clientKey: 'RoutingEnabled', + clientConfig: clients['RoutingEnabled'].auth, + }, }; diff --git a/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts index 7a47c241..459b73b7 100644 --- a/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts @@ -5,7 +5,7 @@ import { expect, Page, test } from '@playwright/test'; import { StateFile } from 'nhs-notify-system-tests-shared'; import z, { string } from 'zod'; -test.use({ storageState: 'login-state/primary.json' }); +test.use({ storageState: 'login-state/routingEnabled.json' }); const getSeededTemplateConfig = async (configFile: string | undefined) => { From a9c416bfbe5342674a22dc2081f15c323e3efe41 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Fri, 6 Feb 2026 14:23:06 +0000 Subject: [PATCH 08/27] CCM-14061: Fix seeded email template --- tests/test-team/lifecycle/templates/setup.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test-team/lifecycle/templates/setup.ts b/tests/test-team/lifecycle/templates/setup.ts index e6e981ad..8f2af292 100644 --- a/tests/test-team/lifecycle/templates/setup.ts +++ b/tests/test-team/lifecycle/templates/setup.ts @@ -55,7 +55,7 @@ async function main() { clientIds['RoutingEnabled'], TemplateType.NHS_APP, { - name: 'multi-channel-routing-config-nhsapp-template', + name: 'multi-channel-routing-config-nhsapp-template-name', message: 'multi-channel-routing-config-nhsapp-message', } ); @@ -68,6 +68,7 @@ async function main() { { name: 'multi-channel-routing-config-email-template-name', message: 'multi-channel-routing-config-email-template-message', + subject: 'multi-channel-routing-config-email-template-subject', } ); stateFile.setValue('templates', 'multiChannelRoutingConfigEmail', multiChannelRoutingConfigEmailTemplate); From ddf5638f92b177eed1227927a91b8d381b6ba838 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Fri, 6 Feb 2026 14:35:16 +0000 Subject: [PATCH 09/27] CCM-14061: Fix continue button selector --- tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts index 459b73b7..884a5269 100644 --- a/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts @@ -113,7 +113,9 @@ test(`User creates a multi-channel routing config`, async ({ page, baseURL, }, { await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/get-ready-to-move/${routingConfigId}(.*)`)); - await page.getByText('Continue').click(); + await page.getByText('Continue', { exact: true }).click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/review-and-move-to-production/${routingConfigId}(.*)`)); // remaining pages not ready yet }); From e043848c197e0b41223febf7076512c28c063c9f Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Fri, 6 Feb 2026 15:13:18 +0000 Subject: [PATCH 10/27] CCM-14061: Add routing-enabled template tests --- tests/test-team/fixtures/clients.ts | 30 ++++++++++-- tests/test-team/fixtures/users.ts | 14 ++++-- tests/test-team/lifecycle/templates/setup.ts | 6 +-- .../routing-config-e2e.ts | 2 +- .../template-mgmt-copy-e2e.ts | 4 +- .../template-mgmt-delete-e2e.ts | 4 +- .../template-mgmt-email-e2e.ts | 4 +- .../template-mgmt-foreign-letter-e2e.ts | 6 +-- .../template-mgmt-letter-e2e.ts | 6 +-- .../template-mgmt-nhsapp-e2e.ts | 4 +- .../template-mgmt-sms-e2e.ts | 4 +- .../template-mgmt-copy-e2e.ts | 36 ++++++++++++++ .../template-mgmt-delete-e2e.ts | 34 +++++++++++++ .../template-mgmt-email-e2e.ts | 36 ++++++++++++++ .../template-mgmt-foreign-letter-e2e.ts | 48 +++++++++++++++++++ .../template-mgmt-letter-e2e.ts | 37 ++++++++++++++ .../template-mgmt-nhsapp-e2e.ts | 34 +++++++++++++ .../template-mgmt-sms-e2e.ts | 36 ++++++++++++++ 18 files changed, 319 insertions(+), 26 deletions(-) rename tests/test-team/template-mgmt-e2e-tests/{ => templates-with-routing-disabled}/template-mgmt-copy-e2e.ts (87%) rename tests/test-team/template-mgmt-e2e-tests/{ => templates-with-routing-disabled}/template-mgmt-delete-e2e.ts (84%) rename tests/test-team/template-mgmt-e2e-tests/{ => templates-with-routing-disabled}/template-mgmt-email-e2e.ts (86%) rename tests/test-team/template-mgmt-e2e-tests/{ => templates-with-routing-disabled}/template-mgmt-foreign-letter-e2e.ts (83%) rename tests/test-team/template-mgmt-e2e-tests/{ => templates-with-routing-disabled}/template-mgmt-letter-e2e.ts (81%) rename tests/test-team/template-mgmt-e2e-tests/{ => templates-with-routing-disabled}/template-mgmt-nhsapp-e2e.ts (86%) rename tests/test-team/template-mgmt-e2e-tests/{ => templates-with-routing-disabled}/template-mgmt-sms-e2e.ts (86%) create mode 100644 tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts create mode 100644 tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts create mode 100644 tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts create mode 100644 tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-foreign-letter-e2e.ts create mode 100644 tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts create mode 100644 tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts create mode 100644 tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts diff --git a/tests/test-team/fixtures/clients.ts b/tests/test-team/fixtures/clients.ts index 3306bcd3..178aca0c 100644 --- a/tests/test-team/fixtures/clients.ts +++ b/tests/test-team/fixtures/clients.ts @@ -37,16 +37,40 @@ export const clients: Record = { name: 'Client 3 Product', }, }, - RoutingEnabled: { + PrimaryRoutingEnabled: { templates: { - campaignIds: ['RoutingEnabled-Campaign'], + campaignIds: ['PrimaryRoutingEnabled-Campaign'], features: { proofing: true, routing: true, }, }, auth: { - name: 'Routing Enabled', + name: 'Primary - Routing Enabled', + }, + }, + CopyRoutingEnabled: { + templates: { + campaignIds: ['CopyRoutingEnabled-Campaign'], + features: { + proofing: true, + routing: true, + }, + }, + auth: { + name: 'Copy - Routing Enabled', + }, + }, + DeleteRoutingEnabled: { + templates: { + campaignIds: ['DeleteRoutingEnabled-Campaign'], + features: { + proofing: true, + routing: true, + }, + }, + auth: { + name: 'Delete - Routing Enabled', }, }, }; diff --git a/tests/test-team/fixtures/users.ts b/tests/test-team/fixtures/users.ts index 45f7e10f..acdb6c94 100644 --- a/tests/test-team/fixtures/users.ts +++ b/tests/test-team/fixtures/users.ts @@ -14,8 +14,16 @@ export const users: Record = { clientKey: 'Client3Product', clientConfig: clients['Client3Product'].auth, }, - routingEnabled: { - clientKey: 'RoutingEnabled', - clientConfig: clients['RoutingEnabled'].auth, + primaryRoutingEnabled: { + clientKey: 'PrimaryRoutingEnabled', + clientConfig: clients['PrimaryRoutingEnabled'].auth, + }, + copyRoutingEnabled: { + clientKey: 'CopyRoutingEnabled', + clientConfig: clients['CopyRoutingEnabled'].auth, + }, + deleteRoutingEnabled: { + clientKey: 'DeleteRoutingEnabled', + clientConfig: clients['DeleteRoutingEnabled'].auth, }, }; diff --git a/tests/test-team/lifecycle/templates/setup.ts b/tests/test-team/lifecycle/templates/setup.ts index 8f2af292..eff62182 100644 --- a/tests/test-team/lifecycle/templates/setup.ts +++ b/tests/test-team/lifecycle/templates/setup.ts @@ -52,7 +52,7 @@ async function main() { const multiChannelRoutingConfigNhsAppTemplate = TemplateFactory.create( randomUUID(), - clientIds['RoutingEnabled'], + clientIds['PrimaryRoutingEnabled'], TemplateType.NHS_APP, { name: 'multi-channel-routing-config-nhsapp-template-name', @@ -63,7 +63,7 @@ async function main() { const multiChannelRoutingConfigEmailTemplate = TemplateFactory.create( randomUUID(), - clientIds['RoutingEnabled'], + clientIds['PrimaryRoutingEnabled'], TemplateType.EMAIL, { name: 'multi-channel-routing-config-email-template-name', @@ -75,7 +75,7 @@ async function main() { const multiChannelRoutingConfigSmsTemplate = TemplateFactory.create( randomUUID(), - clientIds['RoutingEnabled'], + clientIds['PrimaryRoutingEnabled'], TemplateType.SMS, { name: 'multi-channel-routing-config-sms-template-name', diff --git a/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts index 884a5269..c7d9f524 100644 --- a/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts @@ -5,7 +5,7 @@ import { expect, Page, test } from '@playwright/test'; import { StateFile } from 'nhs-notify-system-tests-shared'; import z, { string } from 'zod'; -test.use({ storageState: 'login-state/routingEnabled.json' }); +test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); const getSeededTemplateConfig = async (configFile: string | undefined) => { diff --git a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-copy-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts similarity index 87% rename from tests/test-team/template-mgmt-e2e-tests/template-mgmt-copy-e2e.ts rename to tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts index 370bfa49..a0febd36 100644 --- a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-copy-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts @@ -1,7 +1,7 @@ /* eslint-disable security/detect-non-literal-regexp */ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { getRandomChannel } from 'nhs-notify-system-tests-shared'; import { startPage, @@ -10,7 +10,7 @@ import { previewPage, startNewTemplate, copyTemplate, -} from '../functions/template-mgmt-e2e-common-steps'; +} from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/copy.json' }); diff --git a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-delete-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts similarity index 84% rename from tests/test-team/template-mgmt-e2e-tests/template-mgmt-delete-e2e.ts rename to tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts index 91d2740e..c783a269 100644 --- a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-delete-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts @@ -1,7 +1,7 @@ /* eslint-disable security/detect-non-literal-regexp */ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, @@ -9,7 +9,7 @@ import { previewPage, startNewTemplate, deleteTemplate, -} from '../functions/template-mgmt-e2e-common-steps'; +} from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/delete.json' }); diff --git a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-email-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts similarity index 86% rename from tests/test-team/template-mgmt-e2e-tests/template-mgmt-email-e2e.ts rename to tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts index a33a5f0e..079195dd 100644 --- a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-email-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts @@ -1,7 +1,7 @@ /* eslint-disable security/detect-non-literal-regexp */ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, @@ -10,7 +10,7 @@ import { submitPage, startNewTemplate, previewPageChooseSubmit, -} from '../functions/template-mgmt-e2e-common-steps'; +} from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/primary.json' }); diff --git a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-foreign-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-foreign-letter-e2e.ts similarity index 83% rename from tests/test-team/template-mgmt-e2e-tests/template-mgmt-foreign-letter-e2e.ts rename to tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-foreign-letter-e2e.ts index 7ea3c2dd..baf73b38 100644 --- a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-foreign-letter-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-foreign-letter-e2e.ts @@ -1,14 +1,14 @@ /* eslint-disable security/detect-non-literal-regexp */ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; -import { TemplateMgmtLetterPage } from '../pages/template-mgmt-letter-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { TemplateMgmtLetterPage } from '../../pages/template-mgmt-letter-page'; import { startPage, chooseTemplate, createLetterTemplate, startNewTemplate, -} from '../functions/template-mgmt-e2e-common-steps'; +} from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/primary.json' }); diff --git a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts similarity index 81% rename from tests/test-team/template-mgmt-e2e-tests/template-mgmt-letter-e2e.ts rename to tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts index b7e52e28..4d91644f 100644 --- a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-letter-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts @@ -1,15 +1,15 @@ /* eslint-disable security/detect-non-literal-regexp */ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; -import { TemplateMgmtLetterPage } from '../pages/template-mgmt-letter-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { TemplateMgmtLetterPage } from '../../pages/template-mgmt-letter-page'; import { startPage, chooseTemplate, createLetterTemplate, startNewTemplate, requestProof, -} from '../functions/template-mgmt-e2e-common-steps'; +} from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/primary.json' }); diff --git a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-nhsapp-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts similarity index 86% rename from tests/test-team/template-mgmt-e2e-tests/template-mgmt-nhsapp-e2e.ts rename to tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts index e9ab8990..2a93ea1d 100644 --- a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-nhsapp-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts @@ -1,5 +1,5 @@ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, @@ -8,7 +8,7 @@ import { submitPage, startNewTemplate, previewPageChooseSubmit, -} from '../functions/template-mgmt-e2e-common-steps'; +} from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/primary.json' }); diff --git a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-sms-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts similarity index 86% rename from tests/test-team/template-mgmt-e2e-tests/template-mgmt-sms-e2e.ts rename to tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts index 7703c7e3..93e94b18 100644 --- a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-sms-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts @@ -1,7 +1,7 @@ /* eslint-disable security/detect-non-literal-regexp */ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, @@ -10,7 +10,7 @@ import { submitPage, startNewTemplate, previewPageChooseSubmit, -} from '../functions/template-mgmt-e2e-common-steps'; +} from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/primary.json' }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts new file mode 100644 index 00000000..4d52da2d --- /dev/null +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts @@ -0,0 +1,36 @@ +/* eslint-disable security/detect-non-literal-regexp */ + +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { getRandomChannel } from 'nhs-notify-system-tests-shared'; +import { + startPage, + chooseTemplate, + createTemplate, + previewPage, + startNewTemplate, + copyTemplate, +} from '../../functions/template-mgmt-e2e-common-steps'; + +test.use({ storageState: 'login-state/copyRoutingEnabled.json' }); + +test(`User copies a template - routing enabled`, async ({ page, baseURL }) => { + const props = { + basePage: new TemplateMgmtBasePage(page), + baseURL, + }; + + const randomChannel = getRandomChannel(); + const channel = randomChannel.name; + const channelPath = randomChannel.path; + const name = 'Test edit'; + + console.log('name = ', channel, 'path = ', channelPath); + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createTemplate(props, channel, channelPath, name); + await previewPage(props, channelPath, name); + await copyTemplate(props, name); +}); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts new file mode 100644 index 00000000..4c8d360f --- /dev/null +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts @@ -0,0 +1,34 @@ +/* eslint-disable security/detect-non-literal-regexp */ + +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { + startPage, + chooseTemplate, + createTemplate, + previewPage, + startNewTemplate, + deleteTemplate, +} from '../../functions/template-mgmt-e2e-common-steps'; + +test.use({ storageState: 'login-state/deleteRoutingEnabled.json' }); + +test(`User deletes a template - routing enabled`, async ({ + page, + baseURL, +}) => { + const props = { + basePage: new TemplateMgmtBasePage(page), + baseURL, + }; + const channel = 'Email'; + const channelPath = 'email'; + const name = 'Test delete' + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createTemplate(props, channel, channelPath, name); + await previewPage(props, channelPath, name); + await deleteTemplate(props, name); +}); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts new file mode 100644 index 00000000..d9c2a8a7 --- /dev/null +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts @@ -0,0 +1,36 @@ +/* eslint-disable security/detect-non-literal-regexp */ + +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { + startPage, + chooseTemplate, + createTemplate, + previewPage, + submitPage, + startNewTemplate, + previewPageChooseSubmit, +} from '../../functions/template-mgmt-e2e-common-steps'; + +test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); + +test(`User creates and submits a new email template successfully - routing enabled`, async ({ + page, + baseURL, +}) => { + const props = { + basePage: new TemplateMgmtBasePage(page), + baseURL, + }; + const channel = 'Email'; + const channelPath = 'email'; + const name = 'E2E Name'; + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createTemplate(props, channel, channelPath, name); + await previewPage(props, channelPath, name); + await previewPageChooseSubmit(props, channelPath); + await submitPage(props, channelPath, name); +}); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-foreign-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-foreign-letter-e2e.ts new file mode 100644 index 00000000..a870a008 --- /dev/null +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-foreign-letter-e2e.ts @@ -0,0 +1,48 @@ +/* eslint-disable security/detect-non-literal-regexp */ + +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { TemplateMgmtLetterPage } from '../../pages/template-mgmt-letter-page'; +import { + startPage, + chooseTemplate, + createLetterTemplate, + startNewTemplate, +} from '../../functions/template-mgmt-e2e-common-steps'; + +test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); + +const testConfigs = [ + { + language: 'bn', + inputFileName: 'Bengali.pdf', + }, + { language: 'ar', inputFileName: 'Arabic.pdf' }, + { + language: 'tr', + inputFileName: 'Turkish.pdf', + }, +]; + +for (const { language, inputFileName } of testConfigs) { + test(`User creates and submits a new letter template successfully - ${language} - routing enabled)`, async ({ + page, + baseURL, + }) => { + test.setTimeout(240_000); // override just for this test + + const props = { + basePage: new TemplateMgmtBasePage(page), + letterPage: new TemplateMgmtLetterPage(page), + baseURL, + }; + + const channel = 'Letter'; + const name = `E2E Name ${language}`; + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createLetterTemplate(props, name, language, inputFileName); + }); +} diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts new file mode 100644 index 00000000..71336d41 --- /dev/null +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts @@ -0,0 +1,37 @@ +/* eslint-disable security/detect-non-literal-regexp */ + +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { TemplateMgmtLetterPage } from '../../pages/template-mgmt-letter-page'; +import { + startPage, + chooseTemplate, + createLetterTemplate, + startNewTemplate, + requestProof, +} from '../../functions/template-mgmt-e2e-common-steps'; + +test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); + +test(`User creates and submits a new letter template successfully - routing enabled`, async ({ + page, + baseURL, +}) => { + test.setTimeout(240_000); // override just for this test + const props = { + basePage: new TemplateMgmtBasePage(page), + letterPage: new TemplateMgmtLetterPage(page), + baseURL, + }; + const channel = 'Letter'; + const channelPath = 'letter'; + const name = 'E2E Name'; + const language = 'en'; + const inputFileName = 'template.pdf'; + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createLetterTemplate(props, name, language, inputFileName); + await requestProof(props, channel, channelPath); +}); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts new file mode 100644 index 00000000..009b488f --- /dev/null +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts @@ -0,0 +1,34 @@ +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { + startPage, + chooseTemplate, + createTemplate, + previewPage, + submitPage, + startNewTemplate, + previewPageChooseSubmit, +} from '../../functions/template-mgmt-e2e-common-steps'; + +test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); + +test(`User creates and submits a new nhsapp template successfully - routing enabled`, async ({ + page, + baseURL, +}) => { + const props = { + basePage: new TemplateMgmtBasePage(page), + baseURL, + }; + const channel = 'NHS App message'; + const channelPath = 'nhs-app'; + const name = 'E2E Name'; + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createTemplate(props, channel, channelPath, name); + await previewPage(props, channelPath, name); + await previewPageChooseSubmit(props, channelPath); + await submitPage(props, channelPath, name); +}); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts new file mode 100644 index 00000000..61516ef8 --- /dev/null +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts @@ -0,0 +1,36 @@ +/* eslint-disable security/detect-non-literal-regexp */ + +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { + startPage, + chooseTemplate, + createTemplate, + previewPage, + submitPage, + startNewTemplate, + previewPageChooseSubmit, +} from '../../functions/template-mgmt-e2e-common-steps'; + +test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); + +test(`User creates and submits a new sms template successfully - routing enabled`, async ({ + page, + baseURL, +}) => { + const props = { + basePage: new TemplateMgmtBasePage(page), + baseURL, + }; + const channel = 'Text message (SMS)'; + const channelPath = 'text-message'; + const name = 'E2E Name'; + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createTemplate(props, channel, channelPath, name); + await previewPage(props, channelPath, name); + await previewPageChooseSubmit(props, channelPath); + await submitPage(props, channelPath, name); +}); From a4ea2824bd3c8329af92f275f945beb3c1d7ef22 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Fri, 6 Feb 2026 15:47:31 +0000 Subject: [PATCH 11/27] CCM-14061: Fix routing enabled tests --- .../functions/template-mgmt-e2e-common-steps.ts | 11 ++++++++--- .../template-mgmt-copy-e2e.ts | 2 +- .../template-mgmt-email-e2e.ts | 2 -- .../template-mgmt-nhsapp-e2e.ts | 2 -- .../template-mgmt-sms-e2e.ts | 2 -- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts index d3e2b6b2..554d5e54 100644 --- a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts +++ b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts @@ -211,7 +211,8 @@ export function deleteTemplate( export function copyTemplate( { basePage, baseURL }: CommonStepsProps, - name:string + name: string, + routingEnabled = false, ) { return test.step('Copy template', async () => { await basePage.goBackLink.click(); @@ -245,8 +246,12 @@ export function copyTemplate( await basePage.page.reload(); // shouldn't need to do this await basePage.clickFirstTableRowLink(); - await basePage.checkRadio('Edit template'); - await basePage.clickButtonByName('Continue'); + if (routingEnabled) { + await basePage.page.getByText('Edit template').click(); + } else { + await basePage.checkRadio('Edit template'); + await basePage.clickButtonByName('Continue'); + } const timestamp = Date.now(); const editedTemplateName = `Test edit changed ${timestamp}`; await basePage.fillTextBox('Template name', editedTemplateName); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts index 4d52da2d..6da8c34a 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts @@ -32,5 +32,5 @@ test(`User copies a template - routing enabled`, async ({ page, baseURL }) => { await chooseTemplate(props, channel); await createTemplate(props, channel, channelPath, name); await previewPage(props, channelPath, name); - await copyTemplate(props, name); + await copyTemplate(props, name, true); }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts index d9c2a8a7..52e23c81 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts @@ -31,6 +31,4 @@ test(`User creates and submits a new email template successfully - routing enabl await chooseTemplate(props, channel); await createTemplate(props, channel, channelPath, name); await previewPage(props, channelPath, name); - await previewPageChooseSubmit(props, channelPath); - await submitPage(props, channelPath, name); }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts index 009b488f..d13261e9 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts @@ -29,6 +29,4 @@ test(`User creates and submits a new nhsapp template successfully - routing enab await chooseTemplate(props, channel); await createTemplate(props, channel, channelPath, name); await previewPage(props, channelPath, name); - await previewPageChooseSubmit(props, channelPath); - await submitPage(props, channelPath, name); }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts index 61516ef8..6254974a 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts @@ -31,6 +31,4 @@ test(`User creates and submits a new sms template successfully - routing enabled await chooseTemplate(props, channel); await createTemplate(props, channel, channelPath, name); await previewPage(props, channelPath, name); - await previewPageChooseSubmit(props, channelPath); - await submitPage(props, channelPath, name); }); From b9c60b3aa4e2e327a91925baa5803470f2c35d25 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Mon, 9 Feb 2026 09:55:56 +0000 Subject: [PATCH 12/27] CCM-14061: Update security tests --- tests/security/fixtures/clients.ts | 36 ++++++ tests/security/fixtures/users.ts | 12 ++ tests/security/lifecycle/templates/setup.ts | 38 ++++++ .../security/tests/routing-config.security.ts | 119 ++++++++++++++++++ .../template-mgmt-copy.security.ts | 4 +- .../template-mgmt-delete.security.ts | 4 +- .../template-mgmt-email.security.ts | 4 +- .../template-mgmt-letter.security.ts | 6 +- .../template-mgmt-nhsapp.security.ts | 4 +- .../template-mgmt-sms.security.ts | 4 +- .../template-mgmt-copy.security.ts | 34 +++++ .../template-mgmt-delete.security.ts | 34 +++++ .../template-mgmt-email.security.ts | 34 +++++ .../template-mgmt-letter.security.ts | 35 ++++++ .../template-mgmt-nhsapp.security.ts | 32 +++++ .../template-mgmt-sms.security.ts | 34 +++++ .../routing-config-e2e.ts | 2 - 17 files changed, 421 insertions(+), 15 deletions(-) create mode 100644 tests/security/tests/routing-config.security.ts rename tests/security/tests/{ => templates-with-routing-disabled}/template-mgmt-copy.security.ts (88%) rename tests/security/tests/{ => templates-with-routing-disabled}/template-mgmt-delete.security.ts (86%) rename tests/security/tests/{ => templates-with-routing-disabled}/template-mgmt-email.security.ts (88%) rename tests/security/tests/{ => templates-with-routing-disabled}/template-mgmt-letter.security.ts (81%) rename tests/security/tests/{ => templates-with-routing-disabled}/template-mgmt-nhsapp.security.ts (87%) rename tests/security/tests/{ => templates-with-routing-disabled}/template-mgmt-sms.security.ts (88%) create mode 100644 tests/security/tests/templates-with-routing-enabled/template-mgmt-copy.security.ts create mode 100644 tests/security/tests/templates-with-routing-enabled/template-mgmt-delete.security.ts create mode 100644 tests/security/tests/templates-with-routing-enabled/template-mgmt-email.security.ts create mode 100644 tests/security/tests/templates-with-routing-enabled/template-mgmt-letter.security.ts create mode 100644 tests/security/tests/templates-with-routing-enabled/template-mgmt-nhsapp.security.ts create mode 100644 tests/security/tests/templates-with-routing-enabled/template-mgmt-sms.security.ts diff --git a/tests/security/fixtures/clients.ts b/tests/security/fixtures/clients.ts index a6c34d14..d534be97 100644 --- a/tests/security/fixtures/clients.ts +++ b/tests/security/fixtures/clients.ts @@ -45,4 +45,40 @@ export const clients: Record = { name: 'Client 4 Security ZAP Spider Scan', }, }, + PrimaryRoutingEnabled: { + templates: { + campaignIds: ['PrimaryRoutingEnabled-Campaign'], + features: { + proofing: true, + routing: true, + }, + }, + auth: { + name: 'Primary - Routing Enabled', + }, + }, + CopyRoutingEnabled: { + templates: { + campaignIds: ['CopyRoutingEnabled-Campaign'], + features: { + proofing: true, + routing: true, + }, + }, + auth: { + name: 'Copy - Routing Enabled', + }, + }, + DeleteRoutingEnabled: { + templates: { + campaignIds: ['DeleteRoutingEnabled-Campaign'], + features: { + proofing: true, + routing: true, + }, + }, + auth: { + name: 'Delete - Routing Enabled', + }, + }, }; diff --git a/tests/security/fixtures/users.ts b/tests/security/fixtures/users.ts index 0c05858d..19a683fe 100644 --- a/tests/security/fixtures/users.ts +++ b/tests/security/fixtures/users.ts @@ -18,4 +18,16 @@ export const users: Record = { clientKey: 'SecSpider', clientConfig: clients['SecSpider'].auth, }, + primaryRoutingEnabled: { + clientKey: 'PrimaryRoutingEnabled', + clientConfig: clients['PrimaryRoutingEnabled'].auth, + }, + copyRoutingEnabled: { + clientKey: 'CopyRoutingEnabled', + clientConfig: clients['CopyRoutingEnabled'].auth, + }, + deleteRoutingEnabled: { + clientKey: 'DeleteRoutingEnabled', + clientConfig: clients['DeleteRoutingEnabled'].auth, + }, }; diff --git a/tests/security/lifecycle/templates/setup.ts b/tests/security/lifecycle/templates/setup.ts index b7185182..f18f4c5b 100644 --- a/tests/security/lifecycle/templates/setup.ts +++ b/tests/security/lifecycle/templates/setup.ts @@ -6,6 +6,7 @@ import { getCis2ClientId, TemplateFactory, StorageHelper, + TemplateType, } from 'nhs-notify-system-tests-shared'; import { clients } from '../../fixtures/clients'; import { randomUUID } from 'node:crypto'; @@ -52,8 +53,45 @@ async function main() { clientIds['SecSpider'] ); + const multiChannelRoutingConfigNhsAppTemplate = TemplateFactory.create( + randomUUID(), + clientIds['PrimaryRoutingEnabled'], + TemplateType.NHS_APP, + { + name: 'multi-channel-routing-config-nhsapp-template-name', + message: 'multi-channel-routing-config-nhsapp-message', + } + ); + stateFile.setValue('templates', 'multiChannelRoutingConfigNhsApp', multiChannelRoutingConfigNhsAppTemplate); + + const multiChannelRoutingConfigEmailTemplate = TemplateFactory.create( + randomUUID(), + clientIds['PrimaryRoutingEnabled'], + TemplateType.EMAIL, + { + name: 'multi-channel-routing-config-email-template-name', + message: 'multi-channel-routing-config-email-template-message', + subject: 'multi-channel-routing-config-email-template-subject', + } + ); + stateFile.setValue('templates', 'multiChannelRoutingConfigEmail', multiChannelRoutingConfigEmailTemplate); + + const multiChannelRoutingConfigSmsTemplate = TemplateFactory.create( + randomUUID(), + clientIds['PrimaryRoutingEnabled'], + TemplateType.SMS, + { + name: 'multi-channel-routing-config-sms-template-name', + message: 'multi-channel-routing-config-sms-template-message', + } + ); + stateFile.setValue('templates', 'multiChannelRoutingConfigSms', multiChannelRoutingConfigSmsTemplate); + await new StorageHelper(`nhs-notify-${targetEnvrionment}-app-api-templates`, [ smsTemplate, + multiChannelRoutingConfigNhsAppTemplate, + multiChannelRoutingConfigEmailTemplate, + multiChannelRoutingConfigSmsTemplate, ]).seedData(); await stateFile.persist(); diff --git a/tests/security/tests/routing-config.security.ts b/tests/security/tests/routing-config.security.ts new file mode 100644 index 00000000..28c13d8d --- /dev/null +++ b/tests/security/tests/routing-config.security.ts @@ -0,0 +1,119 @@ +import path, { dirname } from 'node:path'; +import { expect, Page, test } from '@playwright/test'; +import { StateFile } from 'nhs-notify-system-tests-shared'; +import z, { string } from 'zod'; + +test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); + +const getSeededTemplateConfig = async (configFile: string | undefined) => { + + const projectRoot = path.resolve(dirname(configFile ?? ''), '..'); + + const templatesStateFile = new StateFile( + path.join(projectRoot, 'lifecycle', 'templates'), + process.env.RUN_ID + ); + + await templatesStateFile.loadFromDisk(); + + return templatesStateFile.getValues( + 'templates', + z.record(z.string(), z.object({ + id: z.string(), + name: string(), + message: string(), + })), + ); +} + +const previewAndSelectTemplate = async ( + page: Page, + baseURL: string | undefined, + routingConfigId: string, + channel: string, + channelUrlSegment: string, + { id: templateId, name: templateName, message: templateMessage }: { id: string, name: string, message: string }, +) => { + + await page.getByTestId(`choose-template-link-${channel}`).click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}\?(.*)`)); + + await page.getByTestId(`${templateId}-preview-link`).click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}/preview-template/${templateId}\?(.*)`)); + + await expect(page.getByText(templateId)).toBeVisible(); + await expect(page.getByText(templateName)).toBeVisible(); + await expect(page.getByText(templateMessage)).toBeVisible(); + + await page.getByTestId('back-link-bottom').click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}\?(.*)`)); + + await page.getByTestId(`${templateId}-radio`).check(); + + await page.getByText('Save and continue').click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-templates/${routingConfigId}(.*)`)); +} + +test(`User creates a multi-channel routing config`, async ({ page, baseURL, }, { config: { configFile } }) => { + + const templates = await getSeededTemplateConfig(configFile); + await page.goto(`${baseURL}/templates/message-plans`); + + await page.getByText('New message plan').click(); + + await expect(page).toHaveURL(`${baseURL}/templates/message-plans/choose-message-order`); + + await page.getByLabel('NHS App, Email, Text message', { exact: true }).check(); + + await page.getByText('Save and continue').click(); + + await expect(page).toHaveURL(`${baseURL}/templates/message-plans/create-message-plan?messageOrder=NHSAPP%2CEMAIL%2CSMS`); + + await page.getByLabel('Message plan name').fill('message plan name'); + + await page.getByText('Save and continue').click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-templates/(.*)`)); + + const urlSegments = page.url().split('/'); + const routingConfigId = urlSegments[urlSegments.length - 1]; + + await previewAndSelectTemplate( + page, + baseURL, + routingConfigId, + 'NHSAPP', + 'nhs-app', + templates['multiChannelRoutingConfigNhsApp'] + ); + await previewAndSelectTemplate( + page, + baseURL, + routingConfigId, + 'EMAIL', + 'email', + templates['multiChannelRoutingConfigEmail'] + ); + await previewAndSelectTemplate( + page, + baseURL, + routingConfigId, + 'SMS', + 'text-message', + templates['multiChannelRoutingConfigSms'] + ); + + await page.getByText('Move to production').click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/get-ready-to-move/${routingConfigId}(.*)`)); + + await page.getByText('Continue', { exact: true }).click(); + + await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/review-and-move-to-production/${routingConfigId}(.*)`)); + + // remaining pages not ready yet +}); diff --git a/tests/security/tests/template-mgmt-copy.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-copy.security.ts similarity index 88% rename from tests/security/tests/template-mgmt-copy.security.ts rename to tests/security/tests/templates-with-routing-disabled/template-mgmt-copy.security.ts index 7ee6022b..4b3ff370 100644 --- a/tests/security/tests/template-mgmt-copy.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-copy.security.ts @@ -1,7 +1,7 @@ /* eslint-disable security/detect-non-literal-regexp */ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { getRandomChannel } from 'nhs-notify-system-tests-shared'; import { startPage, @@ -10,7 +10,7 @@ import { previewPage, startNewTemplate, copyTemplate, -} from '../functions/common-steps'; +} from '../../functions/common-steps'; test.use({ storageState: 'login-state/copy.json' }); diff --git a/tests/security/tests/template-mgmt-delete.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-delete.security.ts similarity index 86% rename from tests/security/tests/template-mgmt-delete.security.ts rename to tests/security/tests/templates-with-routing-disabled/template-mgmt-delete.security.ts index 20004f9e..57bd8159 100644 --- a/tests/security/tests/template-mgmt-delete.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-delete.security.ts @@ -1,7 +1,7 @@ /* eslint-disable security/detect-non-literal-regexp */ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, @@ -9,7 +9,7 @@ import { previewPage, startNewTemplate, deleteTemplate, -} from '../functions/common-steps'; +} from '../../functions/common-steps'; test.use({ storageState: 'login-state/delete.json' }); diff --git a/tests/security/tests/template-mgmt-email.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-email.security.ts similarity index 88% rename from tests/security/tests/template-mgmt-email.security.ts rename to tests/security/tests/templates-with-routing-disabled/template-mgmt-email.security.ts index 31e0dd46..08698f9b 100644 --- a/tests/security/tests/template-mgmt-email.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-email.security.ts @@ -1,7 +1,7 @@ /* eslint-disable security/detect-non-literal-regexp */ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, @@ -10,7 +10,7 @@ import { submitPage, startNewTemplate, previewPageChooseSubmit, -} from '../functions/common-steps'; +} from '../../functions/common-steps'; test.use({ storageState: 'login-state/primary.json' }); diff --git a/tests/security/tests/template-mgmt-letter.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-letter.security.ts similarity index 81% rename from tests/security/tests/template-mgmt-letter.security.ts rename to tests/security/tests/templates-with-routing-disabled/template-mgmt-letter.security.ts index dbaa11ef..185552df 100644 --- a/tests/security/tests/template-mgmt-letter.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-letter.security.ts @@ -1,15 +1,15 @@ /* eslint-disable security/detect-non-literal-regexp */ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; -import { TemplateMgmtLetterPage } from '../pages/template-mgmt-letter-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { TemplateMgmtLetterPage } from '../../pages/template-mgmt-letter-page'; import { startPage, chooseTemplate, createLetterTemplate, startNewTemplate, requestProof, -} from '../functions/common-steps'; +} from '../../functions/common-steps'; test.use({ storageState: 'login-state/primary.json' }); diff --git a/tests/security/tests/template-mgmt-nhsapp.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-nhsapp.security.ts similarity index 87% rename from tests/security/tests/template-mgmt-nhsapp.security.ts rename to tests/security/tests/templates-with-routing-disabled/template-mgmt-nhsapp.security.ts index 753337e9..d5aee52d 100644 --- a/tests/security/tests/template-mgmt-nhsapp.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-nhsapp.security.ts @@ -1,5 +1,5 @@ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, @@ -8,7 +8,7 @@ import { submitPage, startNewTemplate, previewPageChooseSubmit, -} from '../functions/common-steps'; +} from '../../functions/common-steps'; test.use({ storageState: 'login-state/primary.json' }); diff --git a/tests/security/tests/template-mgmt-sms.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-sms.security.ts similarity index 88% rename from tests/security/tests/template-mgmt-sms.security.ts rename to tests/security/tests/templates-with-routing-disabled/template-mgmt-sms.security.ts index bb2ef98b..c6b25e60 100644 --- a/tests/security/tests/template-mgmt-sms.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-sms.security.ts @@ -1,7 +1,7 @@ /* eslint-disable security/detect-non-literal-regexp */ import { test } from '@playwright/test'; -import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, @@ -10,7 +10,7 @@ import { submitPage, startNewTemplate, previewPageChooseSubmit, -} from '../functions/common-steps'; +} from '../../functions/common-steps'; test.use({ storageState: 'login-state/primary.json' }); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-copy.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-copy.security.ts new file mode 100644 index 00000000..d576eae5 --- /dev/null +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-copy.security.ts @@ -0,0 +1,34 @@ +/* eslint-disable security/detect-non-literal-regexp */ + +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { getRandomChannel } from 'nhs-notify-system-tests-shared'; +import { + startPage, + chooseTemplate, + createTemplate, + previewPage, + startNewTemplate, + copyTemplate, +} from '../../functions/common-steps'; + +test.use({ storageState: 'login-state/copyRoutingEnabled.json' }); + +test(`User copies a template`, async ({ page, baseURL }) => { + const props = { + basePage: new TemplateMgmtBasePage(page), + baseURL, + }; + + const randomChannel = getRandomChannel(); + const channel = randomChannel.name; + const channelPath = randomChannel.path; + const name = 'Test edit'; + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createTemplate(props, channel, channelPath, name); + await previewPage(props, channelPath, name); + await copyTemplate(props, name); +}); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-delete.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-delete.security.ts new file mode 100644 index 00000000..6c856f69 --- /dev/null +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-delete.security.ts @@ -0,0 +1,34 @@ +/* eslint-disable security/detect-non-literal-regexp */ + +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { + startPage, + chooseTemplate, + createTemplate, + previewPage, + startNewTemplate, + deleteTemplate, +} from '../../functions/common-steps'; + +test.use({ storageState: 'login-state/deleteRoutingEnabled.json' }); + +test(`User deletes a template`, async ({ + page, + baseURL, +}) => { + const props = { + basePage: new TemplateMgmtBasePage(page), + baseURL, + }; + const channel = 'Email'; + const channelPath = 'email'; + const name = 'Test delete' + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createTemplate(props, channel, channelPath, name); + await previewPage(props, channelPath, name); + await deleteTemplate(props, name); +}); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-email.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-email.security.ts new file mode 100644 index 00000000..8515795d --- /dev/null +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-email.security.ts @@ -0,0 +1,34 @@ +/* eslint-disable security/detect-non-literal-regexp */ + +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { + startPage, + chooseTemplate, + createTemplate, + previewPage, + submitPage, + startNewTemplate, + previewPageChooseSubmit, +} from '../../functions/common-steps'; + +test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); + +test(`User creates and submits a new email template successfully`, async ({ + page, + baseURL, +}) => { + const props = { + basePage: new TemplateMgmtBasePage(page), + baseURL, + }; + const channel = 'Email'; + const channelPath = 'email'; + const name = 'E2E Name'; + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createTemplate(props, channel, channelPath, name); + await previewPage(props, channelPath, name); +}); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-letter.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-letter.security.ts new file mode 100644 index 00000000..72bae1df --- /dev/null +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-letter.security.ts @@ -0,0 +1,35 @@ +/* eslint-disable security/detect-non-literal-regexp */ + +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { TemplateMgmtLetterPage } from '../../pages/template-mgmt-letter-page'; +import { + startPage, + chooseTemplate, + createLetterTemplate, + startNewTemplate, + requestProof, +} from '../../functions/common-steps'; + +test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); + +test(`User creates and submits a new letter template successfully`, async ({ + page, + baseURL, +}) => { + test.setTimeout(240_000); // override just for this test + const props = { + basePage: new TemplateMgmtBasePage(page), + letterPage: new TemplateMgmtLetterPage(page), + baseURL, + }; + const channel = 'Letter'; + const channelPath = 'letter'; + const name = 'E2E Name'; + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createLetterTemplate(props, name); + await requestProof(props, channel, channelPath); +}); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-nhsapp.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-nhsapp.security.ts new file mode 100644 index 00000000..2340cf7f --- /dev/null +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-nhsapp.security.ts @@ -0,0 +1,32 @@ +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { + startPage, + chooseTemplate, + createTemplate, + previewPage, + submitPage, + startNewTemplate, + previewPageChooseSubmit, +} from '../../functions/common-steps'; + +test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); + +test(`User creates and submits a new nhsapp template successfully`, async ({ + page, + baseURL, +}) => { + const props = { + basePage: new TemplateMgmtBasePage(page), + baseURL, + }; + const channel = 'NHS App message'; + const channelPath = 'nhs-app'; + const name = 'E2E Name'; + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createTemplate(props, channel, channelPath, name); + await previewPage(props, channelPath, name); +}); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-sms.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-sms.security.ts new file mode 100644 index 00000000..028752e4 --- /dev/null +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-sms.security.ts @@ -0,0 +1,34 @@ +/* eslint-disable security/detect-non-literal-regexp */ + +import { test } from '@playwright/test'; +import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; +import { + startPage, + chooseTemplate, + createTemplate, + previewPage, + submitPage, + startNewTemplate, + previewPageChooseSubmit, +} from '../../functions/common-steps'; + +test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); + +test(`User creates and submits a new sms template successfully`, async ({ + page, + baseURL, +}) => { + const props = { + basePage: new TemplateMgmtBasePage(page), + baseURL, + }; + const channel = 'Text message (SMS)'; + const channelPath = 'text-message'; + const name = 'E2E Name'; + + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createTemplate(props, channel, channelPath, name); + await previewPage(props, channelPath, name); +}); diff --git a/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts index c7d9f524..28c13d8d 100644 --- a/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts @@ -1,5 +1,3 @@ -/* eslint-disable security/detect-non-literal-regexp */ - import path, { dirname } from 'node:path'; import { expect, Page, test } from '@playwright/test'; import { StateFile } from 'nhs-notify-system-tests-shared'; From df237ccec441c8e4ac8a13f80ea38cbee503fddc Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Mon, 9 Feb 2026 10:34:36 +0000 Subject: [PATCH 13/27] CCM-14061: Fix letter tests --- tests/security/functions/common-steps.ts | 10 ++++++---- tests/security/pages/template-mgmt-letter-page.ts | 6 ++++++ .../template-mgmt-letter.security.ts | 2 +- .../template-mgmt-letter.security.ts | 2 +- .../functions/template-mgmt-e2e-common-steps.ts | 12 +++++++----- tests/test-team/pages/template-mgmt-letter-page.ts | 6 ++++++ .../template-mgmt-letter-e2e.ts | 2 +- .../template-mgmt-letter-e2e.ts | 2 +- 8 files changed, 29 insertions(+), 13 deletions(-) diff --git a/tests/security/functions/common-steps.ts b/tests/security/functions/common-steps.ts index df240f0a..f8a2773d 100644 --- a/tests/security/functions/common-steps.ts +++ b/tests/security/functions/common-steps.ts @@ -113,12 +113,10 @@ export function createTemplate( export function requestProof( { basePage, baseURL, letterPage }: CommonLetterStepsProps, - channel: string, channelPath: string, + routingEnabled: boolean, ) { return test.step('Request Proof', async () => { - const maxRetries = 10; - const retryInterval = 2000; await basePage.clickButtonByName('Request a proof'); await basePage.clickButtonByName('Go back'); await expect(basePage.page).toHaveURL( @@ -134,8 +132,12 @@ export function requestProof( await basePage.checkStatus('Waiting for proof'); await letterPage.waitForProofRequest(); await letterPage.verifyFiles(); - await letterPage.submitLetterTemplate(); + if (routingEnabled) { + await letterPage.approveLetterTemplate(); + } else { + await letterPage.submitLetterTemplate(); + } }) } diff --git a/tests/security/pages/template-mgmt-letter-page.ts b/tests/security/pages/template-mgmt-letter-page.ts index 26cbf696..6d2b071c 100644 --- a/tests/security/pages/template-mgmt-letter-page.ts +++ b/tests/security/pages/template-mgmt-letter-page.ts @@ -132,4 +132,10 @@ export class TemplateMgmtLetterPage extends TemplateMgmtBasePage { await this.page.getByRole('button', { name: 'Approve and submit' }).click(); await expect(this.page.locator('#template-submitted')).toBeVisible(); } + + async approveLetterTemplate() { + await this.page.getByTestId('preview-letter-template-cta').click(); + await this.page.getByText('Approve template proof').click(); + await expect(this.page.getByText('Message templates')).toBeVisible(); + } } diff --git a/tests/security/tests/templates-with-routing-disabled/template-mgmt-letter.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-letter.security.ts index 185552df..d4b5c0fe 100644 --- a/tests/security/tests/templates-with-routing-disabled/template-mgmt-letter.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-letter.security.ts @@ -31,5 +31,5 @@ test(`User creates and submits a new letter template successfully`, async ({ await startNewTemplate(props); await chooseTemplate(props, channel); await createLetterTemplate(props, name); - await requestProof(props, channel, channelPath); + await requestProof(props, channelPath, false); }); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-letter.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-letter.security.ts index 72bae1df..092580c1 100644 --- a/tests/security/tests/templates-with-routing-enabled/template-mgmt-letter.security.ts +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-letter.security.ts @@ -31,5 +31,5 @@ test(`User creates and submits a new letter template successfully`, async ({ await startNewTemplate(props); await chooseTemplate(props, channel); await createLetterTemplate(props, name); - await requestProof(props, channel, channelPath); + await requestProof(props, channelPath, true); }); diff --git a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts index 554d5e54..8aef2b82 100644 --- a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts +++ b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts @@ -116,12 +116,10 @@ export function createTemplate( export function requestProof( { basePage, baseURL, letterPage }: CommonLetterStepsProps, - channel: string, channelPath: string, + routingEnabled: boolean, ) { return test.step('Request Proof', async () => { - const maxRetries = 10; - const retryInterval = 2000; await basePage.clickButtonByName('Request a proof'); await basePage.clickButtonByName('Go back'); await expect(basePage.page).toHaveURL( @@ -137,9 +135,13 @@ export function requestProof( await basePage.checkStatus('Waiting for proof'); await letterPage.waitForProofRequest(); await letterPage.verifyFiles(); - await letterPage.submitLetterTemplate(); -}) + if (routingEnabled) { + await letterPage.approveLetterTemplate(); + } else { + await letterPage.submitLetterTemplate(); + } + }) } export function previewPage( diff --git a/tests/test-team/pages/template-mgmt-letter-page.ts b/tests/test-team/pages/template-mgmt-letter-page.ts index 28a6c477..afd7122d 100644 --- a/tests/test-team/pages/template-mgmt-letter-page.ts +++ b/tests/test-team/pages/template-mgmt-letter-page.ts @@ -151,4 +151,10 @@ export class TemplateMgmtLetterPage extends TemplateMgmtBasePage { await this.page.getByRole('button', { name: 'Approve and submit' }).click(); await expect(this.page.locator('#template-submitted')).toBeVisible(); } + + async approveLetterTemplate() { + await this.page.getByTestId('preview-letter-template-cta').click(); + await this.page.getByText('Approve template proof').click(); + await expect(this.page.getByText('Message templates')).toBeVisible(); + } } diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts index 4d91644f..fbc4eb5b 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts @@ -33,5 +33,5 @@ test(`User creates and submits a new letter template successfully`, async ({ await startNewTemplate(props); await chooseTemplate(props, channel); await createLetterTemplate(props, name, language, inputFileName); - await requestProof(props, channel, channelPath); + await requestProof(props, channelPath, false); }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts index 71336d41..da029739 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts @@ -33,5 +33,5 @@ test(`User creates and submits a new letter template successfully - routing enab await startNewTemplate(props); await chooseTemplate(props, channel); await createLetterTemplate(props, name, language, inputFileName); - await requestProof(props, channel, channelPath); + await requestProof(props, channelPath, true); }); From 9e1171d818fcba1a05e32402586f76686d4334d8 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Mon, 9 Feb 2026 15:10:21 +0000 Subject: [PATCH 14/27] CCM-14061: Use getByLabel --- tests/test-team/pages/template-mgmt-base-page.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-team/pages/template-mgmt-base-page.ts b/tests/test-team/pages/template-mgmt-base-page.ts index ae629b52..8ba0e9cc 100644 --- a/tests/test-team/pages/template-mgmt-base-page.ts +++ b/tests/test-team/pages/template-mgmt-base-page.ts @@ -108,9 +108,9 @@ export class TemplateMgmtBasePage { await expect(this.page.getByText(status)).toBeVisible(); } - async fillTextBox(textBoxName: string, textBoxContent: string) { + async fillTextBox(textBoxLabel: string, textBoxContent: string) { await this.page - .getByRole("textbox", { name: textBoxName }) + .getByLabel(textBoxLabel) .fill(textBoxContent); } From 83c84ba86eafa5536a88cbfe518fdd74b3f7b4c9 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Mon, 9 Feb 2026 16:08:29 +0000 Subject: [PATCH 15/27] CCM-14061: Change selectors --- .../template-mgmt-e2e-common-steps.ts | 74 +++++++++++-------- .../template-mgmt-cis2-login-e2e.ts | 7 +- .../template-mgmt-copy-e2e.ts | 9 +-- .../template-mgmt-delete-e2e.ts | 6 +- .../template-mgmt-email-e2e.ts | 4 +- .../template-mgmt-nhsapp-e2e.ts | 4 +- .../template-mgmt-sms-e2e.ts | 4 +- .../template-mgmt-copy-e2e.ts | 10 +-- .../template-mgmt-delete-e2e.ts | 4 +- .../template-mgmt-email-e2e.ts | 6 +- .../template-mgmt-nhsapp-e2e.ts | 14 ++-- .../template-mgmt-sms-e2e.ts | 6 +- 12 files changed, 73 insertions(+), 75 deletions(-) diff --git a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts index 8aef2b82..1f88da16 100644 --- a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts +++ b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts @@ -1,4 +1,4 @@ -import { test, expect } from '@playwright/test'; +import { test, expect, Page } from '@playwright/test'; import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; import { TemplateMgmtLetterPage } from '../pages/template-mgmt-letter-page'; @@ -14,10 +14,10 @@ type CommonLetterStepsProps = CommonStepsProps & { export function startPage({ basePage, baseURL }: CommonStepsProps) { return test.step('start page', async () => { await basePage.navigateTo( - `${baseURL}/templates/create-and-submit-templates` + '/templates/create-and-submit-templates' ); await expect(basePage.page).toHaveURL( - `${baseURL}/templates/create-and-submit-templates` + '/templates/create-and-submit-templates' ); await expect(basePage.pageHeader).toHaveText( 'Create and submit a template to NHS Notify' @@ -38,7 +38,7 @@ export function chooseTemplate( ) { return test.step('Choose template type', async () => { await expect(basePage.page).toHaveURL( - `${baseURL}/templates/choose-a-template-type` + '/templates/choose-a-template-type' ); await expect(basePage.pageHeader).toHaveText( @@ -77,41 +77,51 @@ export function createLetterTemplate( }); } -export function createTemplate( - { basePage, baseURL }: CommonStepsProps, - channel: string, - channelPath: string, - name: string +export async function createEmailTemplate( + page: Page, + name: string, ) { - return test.step('Create template', async () => { + await expect(page).toHaveURL( + '/templates/create-email-template' + ); - const pageSlug = `create-${channelPath}-template` + await page.locator('[id="emailTemplateName"]').fill(name); - await expect(basePage.page).toHaveURL( - `${baseURL}/templates/${pageSlug}` - ); - if (channel === 'Email') { - await expect(basePage.pageHeader).toHaveText(`Create email template`); - } else if (channel === 'Text message (SMS)') { - await expect(basePage.pageHeader).toHaveText( - `Create text message template` - ); - } else { - await expect(basePage.pageHeader).toHaveText( - `Create ${channel} template` - ); - } + await page.locator('[id="emailTemplateSubjectLine"]').fill('E2E subject'); - await basePage.fillTextBox('Template name', name); + await page.locator('[id="emailTemplateMessage"]').fill('E2E Message'); - if (channel === 'Email') { - await basePage.fillTextBox('Subject line', 'E2E subject'); - } + await page.getByText('Save and continue').click(); +} - await basePage.fillTextBox('Message', 'E2E Message'); - await basePage.clickButtonByName('Save and preview'); +export async function createSmsTemplate( + page: Page, + name: string, +) { + await expect(page).toHaveURL( + '/templates/create-text-message-template' + ); - }); + await page.locator('[id="smsTemplateName"]').fill(name); + + await page.locator('[id="smsTemplateMessage"]').fill('E2E Message'); + + await page.getByText('Save and continue').click(); +} + +export async function createNhsAppTemplate( + page: Page, + name: string, +) { + await expect(page).toHaveURL( + '/templates/create-nhs-app-template' + ); + + await page.locator('[id="nhsAppTemplateName"]').fill(name); + + await page.locator('[id="nhsAppTemplateMessage"]').fill('E2E Message'); + + await page.getByText('Save and continue').click(); } export function requestProof( diff --git a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts index e3726303..a74bcdc6 100644 --- a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts @@ -4,7 +4,7 @@ import { loginWithCis2, logOut } from '../functions/login'; import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; import { chooseTemplate, - createTemplate, + createEmailTemplate, previewPage, startNewTemplate, startPage, @@ -28,9 +28,6 @@ test('User logs in via CIS2, saves data in templates, logs out and logs back in page, context, }) => { - if (!baseURL) { - throw new Error(`Missing baseURL ${baseURL}`); - } const basePage = new TemplateMgmtBasePage(page); const props = { @@ -45,7 +42,7 @@ test('User logs in via CIS2, saves data in templates, logs out and logs back in await loginWithCis2(basePage.page, 'Message templates'); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); await context.storageState({ path: 'login-state/cis2.json' }); await logOut(basePage); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts index a0febd36..26f90af4 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts @@ -6,10 +6,10 @@ import { getRandomChannel } from 'nhs-notify-system-tests-shared'; import { startPage, chooseTemplate, - createTemplate, previewPage, startNewTemplate, copyTemplate, + createEmailTemplate, } from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/copy.json' }); @@ -20,9 +20,8 @@ test(`User copies a template`, async ({ page, baseURL }) => { baseURL, }; - const randomChannel = getRandomChannel(); - const channel = randomChannel.name; - const channelPath = randomChannel.path; + const channel = 'Email'; + const channelPath = 'email'; const name = 'Test edit'; console.log('name = ', channel, 'path = ', channelPath); @@ -30,7 +29,7 @@ test(`User copies a template`, async ({ page, baseURL }) => { await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); await copyTemplate(props, name); }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts index c783a269..e240074f 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts @@ -5,10 +5,10 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, previewPage, startNewTemplate, deleteTemplate, + createEmailTemplate, } from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/delete.json' }); @@ -23,12 +23,12 @@ test(`User deletes a template`, async ({ }; const channel = 'Email'; const channelPath = 'email'; - const name = 'Test delete' + const name = 'Test delete'; await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); await deleteTemplate(props, name); }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts index 079195dd..52164942 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts @@ -5,11 +5,11 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, previewPage, submitPage, startNewTemplate, previewPageChooseSubmit, + createEmailTemplate, } from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/primary.json' }); @@ -29,7 +29,7 @@ test(`User creates and submits a new email template successfully`, async ({ await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); await previewPageChooseSubmit(props, channelPath); await submitPage(props, channelPath, name); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts index 2a93ea1d..8e831b90 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts @@ -3,11 +3,11 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, previewPage, submitPage, startNewTemplate, previewPageChooseSubmit, + createNhsAppTemplate, } from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/primary.json' }); @@ -27,7 +27,7 @@ test(`User creates and submits a new nhsapp template successfully`, async ({ await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createNhsAppTemplate(page, name); await previewPage(props, channelPath, name); await previewPageChooseSubmit(props, channelPath); await submitPage(props, channelPath, name); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts index 93e94b18..31098c52 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts @@ -5,11 +5,11 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, previewPage, submitPage, startNewTemplate, previewPageChooseSubmit, + createSmsTemplate, } from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/primary.json' }); @@ -29,7 +29,7 @@ test(`User creates and submits a new sms template successfully`, async ({ await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createSmsTemplate(page, name); await previewPage(props, channelPath, name); await previewPageChooseSubmit(props, channelPath); await submitPage(props, channelPath, name); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts index 6da8c34a..382c74d6 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts @@ -2,14 +2,13 @@ import { test } from '@playwright/test'; import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; -import { getRandomChannel } from 'nhs-notify-system-tests-shared'; import { startPage, chooseTemplate, - createTemplate, previewPage, startNewTemplate, copyTemplate, + createEmailTemplate, } from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/copyRoutingEnabled.json' }); @@ -20,9 +19,8 @@ test(`User copies a template - routing enabled`, async ({ page, baseURL }) => { baseURL, }; - const randomChannel = getRandomChannel(); - const channel = randomChannel.name; - const channelPath = randomChannel.path; + const channel = 'Email'; + const channelPath = 'email'; const name = 'Test edit'; console.log('name = ', channel, 'path = ', channelPath); @@ -30,7 +28,7 @@ test(`User copies a template - routing enabled`, async ({ page, baseURL }) => { await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); await copyTemplate(props, name, true); }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts index 4c8d360f..3d41d15b 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts @@ -5,10 +5,10 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, previewPage, startNewTemplate, deleteTemplate, + createEmailTemplate, } from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/deleteRoutingEnabled.json' }); @@ -28,7 +28,7 @@ test(`User deletes a template - routing enabled`, async ({ await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); await deleteTemplate(props, name); }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts index 52e23c81..46a7efe4 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts @@ -5,11 +5,9 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, previewPage, - submitPage, startNewTemplate, - previewPageChooseSubmit, + createEmailTemplate, } from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); @@ -29,6 +27,6 @@ test(`User creates and submits a new email template successfully - routing enabl await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts index d13261e9..e7580adc 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts @@ -3,11 +3,9 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, previewPage, - submitPage, startNewTemplate, - previewPageChooseSubmit, + createNhsAppTemplate, } from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); @@ -24,9 +22,9 @@ test(`User creates and submits a new nhsapp template successfully - routing enab const channelPath = 'nhs-app'; const name = 'E2E Name'; - await startPage(props); - await startNewTemplate(props); - await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); - await previewPage(props, channelPath, name); + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createNhsAppTemplate(page, name); + await previewPage(props, channelPath, name); }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts index 6254974a..3d94c53e 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts @@ -5,11 +5,9 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, previewPage, - submitPage, startNewTemplate, - previewPageChooseSubmit, + createSmsTemplate, } from '../../functions/template-mgmt-e2e-common-steps'; test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); @@ -29,6 +27,6 @@ test(`User creates and submits a new sms template successfully - routing enabled await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createSmsTemplate(page, name); await previewPage(props, channelPath, name); }); From e965b90018b12381010a00b42e0389daa0495950 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Mon, 9 Feb 2026 18:16:45 +0000 Subject: [PATCH 16/27] CCM-14061: Fix button locator --- .../template-mgmt-e2e-common-steps.ts | 57 ++++++++----------- .../routing-config-e2e.ts | 26 ++++----- .../template-mgmt-cis2-login-e2e.ts | 6 +- .../template-mgmt-copy-e2e.ts | 3 +- .../template-mgmt-delete-e2e.ts | 2 - .../template-mgmt-email-e2e.ts | 2 - .../template-mgmt-foreign-letter-e2e.ts | 2 - .../template-mgmt-letter-e2e.ts | 2 - .../template-mgmt-nhsapp-e2e.ts | 2 - .../template-mgmt-sms-e2e.ts | 2 - .../template-mgmt-copy-e2e.ts | 3 +- .../template-mgmt-delete-e2e.ts | 2 - .../template-mgmt-email-e2e.ts | 2 - .../template-mgmt-foreign-letter-e2e.ts | 2 - .../template-mgmt-letter-e2e.ts | 2 - .../template-mgmt-nhsapp-e2e.ts | 2 - .../template-mgmt-sms-e2e.ts | 2 - 17 files changed, 40 insertions(+), 79 deletions(-) diff --git a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts index 1f88da16..9b851941 100644 --- a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts +++ b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts @@ -4,14 +4,13 @@ import { TemplateMgmtLetterPage } from '../pages/template-mgmt-letter-page'; type CommonStepsProps = { basePage: TemplateMgmtBasePage; - baseURL?: string; }; type CommonLetterStepsProps = CommonStepsProps & { letterPage: TemplateMgmtLetterPage; }; -export function startPage({ basePage, baseURL }: CommonStepsProps) { +export function startPage({ basePage }: CommonStepsProps) { return test.step('start page', async () => { await basePage.navigateTo( '/templates/create-and-submit-templates' @@ -33,7 +32,7 @@ export function startNewTemplate({ basePage }: CommonStepsProps) { } export function chooseTemplate( - { basePage, baseURL }: CommonStepsProps, + { basePage }: CommonStepsProps, channel: string ) { return test.step('Choose template type', async () => { @@ -52,17 +51,15 @@ export function chooseTemplate( } export function createLetterTemplate( - { basePage, baseURL, letterPage }: CommonLetterStepsProps, + { basePage, letterPage }: CommonLetterStepsProps, name: string, language: string, inputFileName: string ) { return test.step('Create template', async () => { - const pageSlug = 'upload-letter-template'; - await expect(basePage.page).toHaveURL( - `${baseURL}/templates/${pageSlug}` + '/templates/upload-letter-template' ); await expect(basePage.pageHeader).toHaveText( @@ -91,7 +88,7 @@ export async function createEmailTemplate( await page.locator('[id="emailTemplateMessage"]').fill('E2E Message'); - await page.getByText('Save and continue').click(); + await page.getByText('Save and preview').click(); } export async function createSmsTemplate( @@ -106,7 +103,7 @@ export async function createSmsTemplate( await page.locator('[id="smsTemplateMessage"]').fill('E2E Message'); - await page.getByText('Save and continue').click(); + await page.getByText('Save and preview').click(); } export async function createNhsAppTemplate( @@ -121,11 +118,11 @@ export async function createNhsAppTemplate( await page.locator('[id="nhsAppTemplateMessage"]').fill('E2E Message'); - await page.getByText('Save and continue').click(); + await page.getByText('Save and preview').click(); } export function requestProof( - { basePage, baseURL, letterPage }: CommonLetterStepsProps, + { basePage, letterPage }: CommonLetterStepsProps, channelPath: string, routingEnabled: boolean, ) { @@ -134,12 +131,12 @@ export function requestProof( await basePage.clickButtonByName('Go back'); await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/preview-${channelPath}-template/(.*)`) + new RegExp(`/templates/preview-${channelPath}-template/(.*)`) ); await basePage.clickButtonByName('Request a proof'); await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/request-proof-of-template/(.*)`) + new RegExp('/templates/request-proof-of-template/(.*)') ); await basePage.clickButtonByName('Request a proof'); await basePage.checkStatus('Waiting for proof'); @@ -155,14 +152,14 @@ export function requestProof( } export function previewPage( - { basePage, baseURL }: CommonStepsProps, + { basePage }: CommonStepsProps, channelPath: string, name: string ) { return test.step('Preview page', async () => { await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/preview-${channelPath}-template/(.*)`) + new RegExp(`/templates/preview-${channelPath}-template/(.*)`) ); await expect(basePage.pageHeader).toHaveText(name); @@ -170,7 +167,7 @@ export function previewPage( } export function previewPageChooseSubmit( - { basePage, baseURL }: CommonStepsProps, + { basePage }: CommonStepsProps, channelPath: string, ) { return test.step('Preview page - select submit', async () => { @@ -180,20 +177,19 @@ export function previewPageChooseSubmit( await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/submit-${channelPath}-template/(.*)`) + new RegExp(`/templates/submit-${channelPath}-template/(.*)`) ); }); } export function deleteTemplate( - { basePage, baseURL }: CommonStepsProps, + { basePage }: CommonStepsProps, name:string ) { return test.step('Delete template', async () => { await basePage.goBackLink.click(); await expect(basePage.page).toHaveURL( - // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/message-templates`) + '/templates/message-templates' ); const rowCount = await basePage.tableRows(); console.log(rowCount); @@ -201,8 +197,7 @@ export function deleteTemplate( await basePage.clickLinkByName('Delete ' + name); await basePage.clickButtonByName('No, go back'); await expect(basePage.page).toHaveURL( - // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/message-templates`) + '/templates/message-templates' ); let rowCountCheck = await basePage.tableRows(); console.log(rowCountCheck); @@ -211,8 +206,7 @@ export function deleteTemplate( await basePage.clickLinkByName('Delete ' + name); await basePage.clickButtonByName('Yes, delete template'); await expect(basePage.page).toHaveURL( - // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/message-templates`) + '/templates/message-templates' ); rowCountCheck = await basePage.tableRows(); console.log(rowCount-1); @@ -222,15 +216,14 @@ export function deleteTemplate( } export function copyTemplate( - { basePage, baseURL }: CommonStepsProps, + { basePage }: CommonStepsProps, name: string, routingEnabled = false, ) { return test.step('Copy template', async () => { await basePage.goBackLink.click(); await expect(basePage.page).toHaveURL( - // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/message-templates`) + '/templates/message-templates' ); const rowCount = await basePage.tableRows(); console.log(rowCount); @@ -244,7 +237,7 @@ export function copyTemplate( await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/copy-template/(.*)`) + new RegExp(`/templates/copy-template/(.*)`) ); await basePage.checkRadio('Email'); @@ -252,7 +245,7 @@ export function copyTemplate( await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/message-templates`) + '/templates/message-templates' ); await basePage.page.reload(); // shouldn't need to do this @@ -281,14 +274,14 @@ export function copyTemplate( } export function submitPage( - { basePage, baseURL }: CommonStepsProps, + { basePage }: CommonStepsProps, channelPath: string, name: string ) { return test.step('Submit page', async () => { await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/submit-${channelPath}-template/(.*)`) + new RegExp(`/templates/submit-${channelPath}-template/(.*)`) ); await expect(basePage.pageHeader).toHaveText('Submit ' + `'` + name + `'`); @@ -298,7 +291,7 @@ export function submitPage( // Submitted Page await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/${channelPath}-template-submitted/(.*)`) + new RegExp(`/templates/${channelPath}-template-submitted/(.*)`) ); await expect(basePage.pageHeader).toHaveText('Template submitted'); diff --git a/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts index 28c13d8d..ec5e2499 100644 --- a/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/routing-config-e2e.ts @@ -28,7 +28,6 @@ const getSeededTemplateConfig = async (configFile: string | undefined) => { const previewAndSelectTemplate = async ( page: Page, - baseURL: string | undefined, routingConfigId: string, channel: string, channelUrlSegment: string, @@ -37,11 +36,11 @@ const previewAndSelectTemplate = async ( await page.getByTestId(`choose-template-link-${channel}`).click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}\?(.*)`)); + await expect(page).toHaveURL(new RegExp(`/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}\?(.*)`)); await page.getByTestId(`${templateId}-preview-link`).click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}/preview-template/${templateId}\?(.*)`)); + await expect(page).toHaveURL(new RegExp(`/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}/preview-template/${templateId}\?(.*)`)); await expect(page.getByText(templateId)).toBeVisible(); await expect(page.getByText(templateName)).toBeVisible(); @@ -49,42 +48,41 @@ const previewAndSelectTemplate = async ( await page.getByTestId('back-link-bottom').click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}\?(.*)`)); + await expect(page).toHaveURL(new RegExp(`/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}\?(.*)`)); await page.getByTestId(`${templateId}-radio`).check(); await page.getByText('Save and continue').click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-templates/${routingConfigId}(.*)`)); + await expect(page).toHaveURL(new RegExp(`/templates/message-plans/choose-templates/${routingConfigId}(.*)`)); } -test(`User creates a multi-channel routing config`, async ({ page, baseURL, }, { config: { configFile } }) => { +test(`User creates a multi-channel routing config`, async ({ page, }, { config: { configFile } }) => { const templates = await getSeededTemplateConfig(configFile); - await page.goto(`${baseURL}/templates/message-plans`); + await page.goto(`/templates/message-plans`); await page.getByText('New message plan').click(); - await expect(page).toHaveURL(`${baseURL}/templates/message-plans/choose-message-order`); + await expect(page).toHaveURL('/templates/message-plans/choose-message-order'); await page.getByLabel('NHS App, Email, Text message', { exact: true }).check(); await page.getByText('Save and continue').click(); - await expect(page).toHaveURL(`${baseURL}/templates/message-plans/create-message-plan?messageOrder=NHSAPP%2CEMAIL%2CSMS`); + await expect(page).toHaveURL('/templates/message-plans/create-message-plan?messageOrder=NHSAPP%2CEMAIL%2CSMS'); await page.getByLabel('Message plan name').fill('message plan name'); await page.getByText('Save and continue').click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-templates/(.*)`)); + await expect(page).toHaveURL(new RegExp('/templates/message-plans/choose-templates/(.*)')); const urlSegments = page.url().split('/'); const routingConfigId = urlSegments[urlSegments.length - 1]; await previewAndSelectTemplate( page, - baseURL, routingConfigId, 'NHSAPP', 'nhs-app', @@ -92,7 +90,6 @@ test(`User creates a multi-channel routing config`, async ({ page, baseURL, }, { ); await previewAndSelectTemplate( page, - baseURL, routingConfigId, 'EMAIL', 'email', @@ -100,7 +97,6 @@ test(`User creates a multi-channel routing config`, async ({ page, baseURL, }, { ); await previewAndSelectTemplate( page, - baseURL, routingConfigId, 'SMS', 'text-message', @@ -109,11 +105,11 @@ test(`User creates a multi-channel routing config`, async ({ page, baseURL, }, { await page.getByText('Move to production').click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/get-ready-to-move/${routingConfigId}(.*)`)); + await expect(page).toHaveURL(new RegExp(`/templates/message-plans/get-ready-to-move/${routingConfigId}(.*)`)); await page.getByText('Continue', { exact: true }).click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/review-and-move-to-production/${routingConfigId}(.*)`)); + await expect(page).toHaveURL(new RegExp(`/templates/message-plans/review-and-move-to-production/${routingConfigId}(.*)`)); // remaining pages not ready yet }); diff --git a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts index a74bcdc6..084640b9 100644 --- a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts @@ -24,7 +24,6 @@ test.use({ storageState: { cookies: [], origins: [] } }); * - CIS2 'prompt=login' works to force a re-authentication */ test('User logs in via CIS2, saves data in templates, logs out and logs back in again', async ({ - baseURL, page, context, }) => { @@ -32,13 +31,12 @@ test('User logs in via CIS2, saves data in templates, logs out and logs back in const basePage = new TemplateMgmtBasePage(page); const props = { basePage, - baseURL, }; const channel = 'Email'; const channelPath = 'email'; const name = 'E2E Name'; - await startPage({ basePage, baseURL }); + await startPage({ basePage }); await loginWithCis2(basePage.page, 'Message templates'); await startNewTemplate(props); await chooseTemplate(props, channel); @@ -47,6 +45,6 @@ test('User logs in via CIS2, saves data in templates, logs out and logs back in await context.storageState({ path: 'login-state/cis2.json' }); await logOut(basePage); await page.waitForLoadState('networkidle'); - await startPage({ basePage, baseURL }); + await startPage({ basePage }); await loginWithCis2(basePage.page, 'Message templates'); }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts index 26f90af4..bd743b21 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts @@ -14,10 +14,9 @@ import { test.use({ storageState: 'login-state/copy.json' }); -test(`User copies a template`, async ({ page, baseURL }) => { +test(`User copies a template`, async ({ page }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'Email'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts index e240074f..635e4962 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts @@ -15,11 +15,9 @@ test.use({ storageState: 'login-state/delete.json' }); test(`User deletes a template`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'Email'; const channelPath = 'email'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts index 52164942..9e0192f8 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts @@ -16,11 +16,9 @@ test.use({ storageState: 'login-state/primary.json' }); test(`User creates and submits a new email template successfully`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'Email'; const channelPath = 'email'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-foreign-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-foreign-letter-e2e.ts index baf73b38..3e316d35 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-foreign-letter-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-foreign-letter-e2e.ts @@ -27,14 +27,12 @@ const testConfigs = [ for (const { language, inputFileName } of testConfigs) { test(`User creates and submits a new letter template successfully - ${language})`, async ({ page, - baseURL, }) => { test.setTimeout(240_000); // override just for this test const props = { basePage: new TemplateMgmtBasePage(page), letterPage: new TemplateMgmtLetterPage(page), - baseURL, }; const channel = 'Letter'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts index fbc4eb5b..40548726 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts @@ -15,13 +15,11 @@ test.use({ storageState: 'login-state/primary.json' }); test(`User creates and submits a new letter template successfully`, async ({ page, - baseURL, }) => { test.setTimeout(240_000); // override just for this test const props = { basePage: new TemplateMgmtBasePage(page), letterPage: new TemplateMgmtLetterPage(page), - baseURL, }; const channel = 'Letter'; const channelPath = 'letter'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts index 8e831b90..a23d5e37 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts @@ -14,11 +14,9 @@ test.use({ storageState: 'login-state/primary.json' }); test(`User creates and submits a new nhsapp template successfully`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'NHS App message'; const channelPath = 'nhs-app'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts index 31098c52..70eac491 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts @@ -16,11 +16,9 @@ test.use({ storageState: 'login-state/primary.json' }); test(`User creates and submits a new sms template successfully`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'Text message (SMS)'; const channelPath = 'text-message'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts index 382c74d6..af923ee5 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts @@ -13,10 +13,9 @@ import { test.use({ storageState: 'login-state/copyRoutingEnabled.json' }); -test(`User copies a template - routing enabled`, async ({ page, baseURL }) => { +test(`User copies a template - routing enabled`, async ({ page }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'Email'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts index 3d41d15b..d1808196 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts @@ -15,11 +15,9 @@ test.use({ storageState: 'login-state/deleteRoutingEnabled.json' }); test(`User deletes a template - routing enabled`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'Email'; const channelPath = 'email'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts index 46a7efe4..639c8cd0 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts @@ -14,11 +14,9 @@ test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); test(`User creates and submits a new email template successfully - routing enabled`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'Email'; const channelPath = 'email'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-foreign-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-foreign-letter-e2e.ts index a870a008..43866bd0 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-foreign-letter-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-foreign-letter-e2e.ts @@ -27,14 +27,12 @@ const testConfigs = [ for (const { language, inputFileName } of testConfigs) { test(`User creates and submits a new letter template successfully - ${language} - routing enabled)`, async ({ page, - baseURL, }) => { test.setTimeout(240_000); // override just for this test const props = { basePage: new TemplateMgmtBasePage(page), letterPage: new TemplateMgmtLetterPage(page), - baseURL, }; const channel = 'Letter'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts index da029739..b54f46d9 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts @@ -15,13 +15,11 @@ test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); test(`User creates and submits a new letter template successfully - routing enabled`, async ({ page, - baseURL, }) => { test.setTimeout(240_000); // override just for this test const props = { basePage: new TemplateMgmtBasePage(page), letterPage: new TemplateMgmtLetterPage(page), - baseURL, }; const channel = 'Letter'; const channelPath = 'letter'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts index e7580adc..43070007 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts @@ -12,11 +12,9 @@ test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); test(`User creates and submits a new nhsapp template successfully - routing enabled`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'NHS App message'; const channelPath = 'nhs-app'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts index 3d94c53e..5d7180de 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts @@ -14,11 +14,9 @@ test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); test(`User creates and submits a new sms template successfully - routing enabled`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'Text message (SMS)'; const channelPath = 'text-message'; From af13165c9137ebc5e2b8c4c3d1c2372dcd74689d Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Mon, 9 Feb 2026 18:36:04 +0000 Subject: [PATCH 17/27] CCM-14061: Debug logging --- .../template-mgmt-e2e-common-steps.ts | 97 +++++++++++++++++++ .../template-mgmt-copy-e2e.ts | 2 +- .../template-mgmt-delete-e2e.ts | 2 +- .../template-mgmt-email-e2e.ts | 2 +- .../template-mgmt-foreign-letter-e2e.ts | 2 +- .../template-mgmt-letter-e2e.ts | 2 +- .../template-mgmt-nhsapp-e2e.ts | 2 +- .../template-mgmt-sms-e2e.ts | 2 +- .../template-mgmt-copy-e2e.ts | 2 +- .../template-mgmt-delete-e2e.ts | 2 +- .../template-mgmt-email-e2e.ts | 2 +- .../template-mgmt-foreign-letter-e2e.ts | 2 +- .../template-mgmt-letter-e2e.ts | 2 +- .../template-mgmt-nhsapp-e2e.ts | 2 +- .../template-mgmt-sms-e2e.ts | 2 +- 15 files changed, 111 insertions(+), 14 deletions(-) diff --git a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts index 9b851941..c5b16587 100644 --- a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts +++ b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts @@ -82,13 +82,53 @@ export async function createEmailTemplate( '/templates/create-email-template' ); + console.log( + name, + 'log 1', + await page.locator('[id="emailTemplateName"]').inputValue(), + await page.locator('[id="emailTemplateSubjectLine"]').inputValue(), + await page.locator('[id="emailTemplateMessage"]').inputValue() + ); + await page.locator('[id="emailTemplateName"]').fill(name); + console.log( + name, + 'log 2', + await page.locator('[id="emailTemplateName"]').inputValue(), + await page.locator('[id="emailTemplateSubjectLine"]').inputValue(), + await page.locator('[id="emailTemplateMessage"]').inputValue() + ); + await page.locator('[id="emailTemplateSubjectLine"]').fill('E2E subject'); + console.log( + name, + 'log 3', + await page.locator('[id="emailTemplateName"]').inputValue(), + await page.locator('[id="emailTemplateSubjectLine"]').inputValue(), + await page.locator('[id="emailTemplateMessage"]').inputValue() + ); + await page.locator('[id="emailTemplateMessage"]').fill('E2E Message'); + console.log( + name, + 'log 4', + await page.locator('[id="emailTemplateName"]').inputValue(), + await page.locator('[id="emailTemplateSubjectLine"]').inputValue(), + await page.locator('[id="emailTemplateMessage"]').inputValue() + ); + await page.getByText('Save and preview').click(); + + console.log( + name, + 'log 5', + await page.locator('[id="emailTemplateName"]').inputValue(), + await page.locator('[id="emailTemplateSubjectLine"]').inputValue(), + await page.locator('[id="emailTemplateMessage"]').inputValue() + ); } export async function createSmsTemplate( @@ -99,11 +139,39 @@ export async function createSmsTemplate( '/templates/create-text-message-template' ); + console.log( + name, + 'log 1', + await page.locator('[id="smsTemplateName"]').inputValue(), + await page.locator('[id="smsTemplateMessage"]').inputValue() + ); + await page.locator('[id="smsTemplateName"]').fill(name); + console.log( + name, + 'log 2', + await page.locator('[id="smsTemplateName"]').inputValue(), + await page.locator('[id="smsTemplateMessage"]').inputValue() + ); + await page.locator('[id="smsTemplateMessage"]').fill('E2E Message'); + console.log( + name, + 'log 3', + await page.locator('[id="smsTemplateName"]').inputValue(), + await page.locator('[id="smsTemplateMessage"]').inputValue() + ); + await page.getByText('Save and preview').click(); + + console.log( + name, + 'log 4', + await page.locator('[id="smsTemplateName"]').inputValue(), + await page.locator('[id="smsTemplateMessage"]').inputValue() + ); } export async function createNhsAppTemplate( @@ -114,13 +182,42 @@ export async function createNhsAppTemplate( '/templates/create-nhs-app-template' ); + console.log( + name, + 'log 1', + await page.locator('[id="nhsAppTemplateName"]').inputValue(), + await page.locator('[id="nhsAppTemplateMessage"]').inputValue() + ); + await page.locator('[id="nhsAppTemplateName"]').fill(name); + console.log( + name, + 'log 2', + await page.locator('[id="nhsAppTemplateName"]').inputValue(), + await page.locator('[id="nhsAppTemplateMessage"]').inputValue() + ); + await page.locator('[id="nhsAppTemplateMessage"]').fill('E2E Message'); + console.log( + name, + 'log 3', + await page.locator('[id="nhsAppTemplateName"]').inputValue(), + await page.locator('[id="nhsAppTemplateMessage"]').inputValue() + ); + await page.getByText('Save and preview').click(); + + console.log( + name, + 'log 4', + await page.locator('[id="nhsAppTemplateName"]').inputValue(), + await page.locator('[id="nhsAppTemplateMessage"]').inputValue() + ); } + export function requestProof( { basePage, letterPage }: CommonLetterStepsProps, channelPath: string, diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts index bd743b21..49b04053 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts @@ -21,7 +21,7 @@ test(`User copies a template`, async ({ page }) => { const channel = 'Email'; const channelPath = 'email'; - const name = 'Test edit'; + const name = 'copy template e2e test'; console.log('name = ', channel, 'path = ', channelPath); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts index 635e4962..c3ce6da4 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-delete-e2e.ts @@ -21,7 +21,7 @@ test(`User deletes a template`, async ({ }; const channel = 'Email'; const channelPath = 'email'; - const name = 'Test delete'; + const name = 'delete template e2e test'; await startPage(props); await startNewTemplate(props); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts index 9e0192f8..34433dd7 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts @@ -22,7 +22,7 @@ test(`User creates and submits a new email template successfully`, async ({ }; const channel = 'Email'; const channelPath = 'email'; - const name = 'E2E Name'; + const name = 'email template e2e test'; await startPage(props); await startNewTemplate(props); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-foreign-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-foreign-letter-e2e.ts index 3e316d35..818f63a1 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-foreign-letter-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-foreign-letter-e2e.ts @@ -36,7 +36,7 @@ for (const { language, inputFileName } of testConfigs) { }; const channel = 'Letter'; - const name = `E2E Name ${language}`; + const name = `${language} language template e2e test`; await startPage(props); await startNewTemplate(props); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts index 40548726..529b6de0 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-letter-e2e.ts @@ -23,7 +23,7 @@ test(`User creates and submits a new letter template successfully`, async ({ }; const channel = 'Letter'; const channelPath = 'letter'; - const name = 'E2E Name'; + const name = 'letter template e2e test'; const language = 'en'; const inputFileName = 'template.pdf'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts index a23d5e37..9e9daa29 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-nhsapp-e2e.ts @@ -20,7 +20,7 @@ test(`User creates and submits a new nhsapp template successfully`, async ({ }; const channel = 'NHS App message'; const channelPath = 'nhs-app'; - const name = 'E2E Name'; + const name = 'nhs app template e2e test'; await startPage(props); await startNewTemplate(props); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts index 70eac491..632ba745 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-sms-e2e.ts @@ -22,7 +22,7 @@ test(`User creates and submits a new sms template successfully`, async ({ }; const channel = 'Text message (SMS)'; const channelPath = 'text-message'; - const name = 'E2E Name'; + const name = 'SMS template e2e test'; await startPage(props); await startNewTemplate(props); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts index af923ee5..73fabd27 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts @@ -20,7 +20,7 @@ test(`User copies a template - routing enabled`, async ({ page }) => { const channel = 'Email'; const channelPath = 'email'; - const name = 'Test edit'; + const name = 'copy template e2e test - routing enabled'; console.log('name = ', channel, 'path = ', channelPath); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts index d1808196..5de7b4d3 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts @@ -21,7 +21,7 @@ test(`User deletes a template - routing enabled`, async ({ }; const channel = 'Email'; const channelPath = 'email'; - const name = 'Test delete' + const name = 'delete template e2e test - routing enabled'; await startPage(props); await startNewTemplate(props); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts index 639c8cd0..7b0ab703 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-email-e2e.ts @@ -20,7 +20,7 @@ test(`User creates and submits a new email template successfully - routing enabl }; const channel = 'Email'; const channelPath = 'email'; - const name = 'E2E Name'; + const name = 'email template e2e test - routing enabled'; await startPage(props); await startNewTemplate(props); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-foreign-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-foreign-letter-e2e.ts index 43866bd0..a546a770 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-foreign-letter-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-foreign-letter-e2e.ts @@ -36,7 +36,7 @@ for (const { language, inputFileName } of testConfigs) { }; const channel = 'Letter'; - const name = `E2E Name ${language}`; + const name = `${language} language template e2e test - routing enabled`; await startPage(props); await startNewTemplate(props); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts index b54f46d9..c63e1df3 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-letter-e2e.ts @@ -23,7 +23,7 @@ test(`User creates and submits a new letter template successfully - routing enab }; const channel = 'Letter'; const channelPath = 'letter'; - const name = 'E2E Name'; + const name = 'letter template e2e test - routing enabled'; const language = 'en'; const inputFileName = 'template.pdf'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts index 43070007..8eeaa93b 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-nhsapp-e2e.ts @@ -18,7 +18,7 @@ test(`User creates and submits a new nhsapp template successfully - routing enab }; const channel = 'NHS App message'; const channelPath = 'nhs-app'; - const name = 'E2E Name'; + const name = 'nhs app template e2e test - routing enabled'; await startPage(props); await startNewTemplate(props); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts index 5d7180de..29f42c7b 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-sms-e2e.ts @@ -20,7 +20,7 @@ test(`User creates and submits a new sms template successfully - routing enabled }; const channel = 'Text message (SMS)'; const channelPath = 'text-message'; - const name = 'E2E Name'; + const name = 'SMS template e2e test - routing enabled'; await startPage(props); await startNewTemplate(props); From ed3665f68f48d97a9a28df1b77acf534431d251c Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Mon, 9 Feb 2026 18:47:11 +0000 Subject: [PATCH 18/27] CCM-14061: Add waitFor --- tests/test-team/functions/template-mgmt-e2e-common-steps.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts index c5b16587..f1bcb50a 100644 --- a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts +++ b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts @@ -82,6 +82,8 @@ export async function createEmailTemplate( '/templates/create-email-template' ); + await expect(page.getByTestId('navigation-links')).toBeVisible(); + console.log( name, 'log 1', From a34d67c982bf7b4ba65cdcbee20872651f1a6e45 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Mon, 9 Feb 2026 18:55:40 +0000 Subject: [PATCH 19/27] CCM-14061: Add waitFor --- tests/test-team/functions/template-mgmt-e2e-common-steps.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts index f1bcb50a..f805574f 100644 --- a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts +++ b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts @@ -141,6 +141,8 @@ export async function createSmsTemplate( '/templates/create-text-message-template' ); + await expect(page.getByTestId('navigation-links')).toBeVisible(); + console.log( name, 'log 1', @@ -184,6 +186,8 @@ export async function createNhsAppTemplate( '/templates/create-nhs-app-template' ); + await expect(page.getByTestId('navigation-links')).toBeVisible(); + console.log( name, 'log 1', From f1d42c70b55030240ff5f90871399e67213c8105 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Tue, 10 Feb 2026 08:29:47 +0000 Subject: [PATCH 20/27] CCM-14061: Update security tests --- tests/security/functions/common-steps.ts | 133 +++++++++--------- .../security/tests/routing-config.security.ts | 26 ++-- .../template-mgmt-cis2-login.security.ts | 10 +- .../template-mgmt-copy.security.ts | 15 +- .../template-mgmt-delete.security.ts | 9 +- .../template-mgmt-email.security.ts | 9 +- .../template-mgmt-letter.security.ts | 4 +- .../template-mgmt-nhsapp.security.ts | 20 ++- .../template-mgmt-sms.security.ts | 8 +- .../template-mgmt-copy.security.ts | 15 +- .../template-mgmt-delete.security.ts | 9 +- .../template-mgmt-email.security.ts | 10 +- .../template-mgmt-letter.security.ts | 4 +- .../template-mgmt-nhsapp.security.ts | 18 +-- .../template-mgmt-sms.security.ts | 10 +- .../template-mgmt-e2e-common-steps.ts | 110 +-------------- .../template-mgmt-email-e2e.ts | 1 + .../template-mgmt-delete-e2e.ts | 1 + 18 files changed, 143 insertions(+), 269 deletions(-) diff --git a/tests/security/functions/common-steps.ts b/tests/security/functions/common-steps.ts index f8a2773d..ff444551 100644 --- a/tests/security/functions/common-steps.ts +++ b/tests/security/functions/common-steps.ts @@ -1,23 +1,22 @@ -import { test, expect } from '@playwright/test'; +import { test, expect, Page } from '@playwright/test'; import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; import { TemplateMgmtLetterPage } from '../pages/template-mgmt-letter-page'; type CommonStepsProps = { basePage: TemplateMgmtBasePage; - baseURL?: string; }; type CommonLetterStepsProps = CommonStepsProps & { letterPage: TemplateMgmtLetterPage; }; -export function startPage({ basePage, baseURL }: CommonStepsProps) { +export function startPage({ basePage }: CommonStepsProps) { return test.step('start page', async () => { await basePage.navigateTo( - `${baseURL}/templates/create-and-submit-templates` + '/templates/create-and-submit-templates' ); await expect(basePage.page).toHaveURL( - `${baseURL}/templates/create-and-submit-templates` + '/templates/create-and-submit-templates' ); await expect(basePage.pageHeader).toHaveText( 'Create and submit a template to NHS Notify' @@ -33,12 +32,12 @@ export function startNewTemplate({ basePage }: CommonStepsProps) { } export function chooseTemplate( - { basePage, baseURL }: CommonStepsProps, + { basePage }: CommonStepsProps, channel: string ) { return test.step('Choose template type', async () => { await expect(basePage.page).toHaveURL( - `${baseURL}/templates/choose-a-template-type` + '/templates/choose-a-template-type' ); await expect(basePage.pageHeader).toHaveText( @@ -52,14 +51,12 @@ export function chooseTemplate( } export function createLetterTemplate( - { basePage, baseURL, letterPage }: CommonLetterStepsProps, + { basePage, letterPage }: CommonLetterStepsProps, name: string ) { return test.step('Create template', async () => { - const pageSlug = 'upload-letter-template'; - await expect(basePage.page).toHaveURL( - `${baseURL}/templates/${pageSlug}` + '/templates/upload-letter-template' ); await expect(basePage.pageHeader).toHaveText( @@ -74,45 +71,61 @@ export function createLetterTemplate( }); } -export function createTemplate( - { basePage, baseURL }: CommonStepsProps, - channel: string, - channelPath: string, - name: string +export async function createEmailTemplate( + page: Page, + name: string, ) { - return test.step('Create template', async () => { + await expect(page).toHaveURL( + '/templates/create-email-template' + ); - const pageSlug = `create-${channelPath}-template` + await expect(page.getByTestId('navigation-links')).toBeVisible(); - await expect(basePage.page).toHaveURL( - `${baseURL}/templates/${pageSlug}` - ); - if (channel === 'Email') { - await expect(basePage.pageHeader).toHaveText(`Create email template`); - } else if (channel === 'Text message (SMS)') { - await expect(basePage.pageHeader).toHaveText( - `Create text message template` - ); - } else { - await expect(basePage.pageHeader).toHaveText( - `Create ${channel} template` - ); - } + await page.getByLabel('Template name').fill(name); - await basePage.fillTextBox('Template name', name); + await page.getByLabel('Subject line').fill('E2E subject'); - if (channel === 'Email') { - await basePage.fillTextBox('Subject line', 'E2E subject'); - } + await page.getByLabel('Message').fill('E2E Message'); - await basePage.fillTextBox('Message', 'E2E Message'); - await basePage.clickButtonByName('Save and preview'); + await page.getByText('Save and preview').click(); +} - }); +export async function createSmsTemplate( + page: Page, + name: string, +) { + await expect(page).toHaveURL( + '/templates/create-text-message-template' + ); + + await expect(page.getByTestId('navigation-links')).toBeVisible(); + + await page.getByLabel('Template name').fill(name); + + await page.getByLabel('Message').fill('E2E Message'); + + await page.getByText('Save and preview').click(); +} + +export async function createNhsAppTemplate( + page: Page, + name: string, +) { + await expect(page).toHaveURL( + '/templates/create-nhs-app-template' + ); + + await expect(page.getByTestId('navigation-links')).toBeVisible(); + + await page.getByLabel('Template name').fill(name); + + await page.getByLabel('Message').fill('E2E Message'); + + await page.getByText('Save and preview').click(); } export function requestProof( - { basePage, baseURL, letterPage }: CommonLetterStepsProps, + { basePage, letterPage }: CommonLetterStepsProps, channelPath: string, routingEnabled: boolean, ) { @@ -121,12 +134,12 @@ export function requestProof( await basePage.clickButtonByName('Go back'); await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/preview-${channelPath}-template/(.*)`) + new RegExp(`/templates/preview-${channelPath}-template/(.*)`) ); await basePage.clickButtonByName('Request a proof'); await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/request-proof-of-template/(.*)`) + new RegExp('/templates/request-proof-of-template/(.*)') ); await basePage.clickButtonByName('Request a proof'); await basePage.checkStatus('Waiting for proof'); @@ -142,14 +155,14 @@ export function requestProof( } export function previewPage( - { basePage, baseURL }: CommonStepsProps, + { basePage }: CommonStepsProps, channelPath: string, name: string ) { return test.step('Preview page', async () => { await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/preview-${channelPath}-template/(.*)`) + new RegExp(`/templates/preview-${channelPath}-template/(.*)`) ); await expect(basePage.pageHeader).toHaveText(name); @@ -157,7 +170,7 @@ export function previewPage( } export function previewPageChooseSubmit( - { basePage, baseURL }: CommonStepsProps, + { basePage }: CommonStepsProps, channelPath: string, ) { return test.step('Preview page - select submit', async () => { @@ -167,28 +180,26 @@ export function previewPageChooseSubmit( await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/submit-${channelPath}-template/(.*)`) + new RegExp(`}/templates/submit-${channelPath}-template/(.*)`) ); }); } export function deleteTemplate( - { basePage, baseURL }: CommonStepsProps, + { basePage }: CommonStepsProps, name:string ) { return test.step('Delete template', async () => { await basePage.goBackLink.click(); await expect(basePage.page).toHaveURL( - // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/message-templates`) + '/templates/message-templates' ); const rowCount = await basePage.tableRows(); await basePage.clickLinkByName('Delete ' + name); await basePage.clickButtonByName('No, go back'); await expect(basePage.page).toHaveURL( - // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/message-templates`) + '/templates/message-templates' ); let rowCountCheck = await basePage.tableRows(); expect(rowCount).toBe(rowCount); @@ -196,8 +207,7 @@ export function deleteTemplate( await basePage.clickLinkByName('Delete ' + name); await basePage.clickButtonByName('Yes, delete template'); await expect(basePage.page).toHaveURL( - // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/message-templates`) + '/templates/message-templates' ); rowCountCheck = await basePage.tableRows(); expect(rowCountCheck).toBe(rowCount-1); @@ -206,14 +216,13 @@ export function deleteTemplate( } export function copyTemplate( - { basePage, baseURL }: CommonStepsProps, + { basePage }: CommonStepsProps, name:string ) { return test.step('Copy template', async () => { await basePage.goBackLink.click(); await expect(basePage.page).toHaveURL( - // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/message-templates`) + '/templates/message-templates' ); const rowCount = await basePage.tableRows(); @@ -225,16 +234,14 @@ export function copyTemplate( } await expect(basePage.page).toHaveURL( - // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/copy-template/(.*)`) + new RegExp(`/templates/copy-template/(.*)`) ); await basePage.checkRadio('Email'); await basePage.clickButtonByName('Continue'); await expect(basePage.page).toHaveURL( - // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/message-templates`) + '/templates/message-templates' ); await basePage.page.reload(); // shouldn't need to do this @@ -258,14 +265,14 @@ export function copyTemplate( } export function submitPage( - { basePage, baseURL }: CommonStepsProps, + { basePage }: CommonStepsProps, channelPath: string, name: string ) { return test.step('Submit page', async () => { await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/submit-${channelPath}-template/(.*)`) + new RegExp(`/templates/submit-${channelPath}-template/(.*)`) ); await expect(basePage.pageHeader).toHaveText('Submit ' + `'` + name + `'`); @@ -275,7 +282,7 @@ export function submitPage( // Submitted Page await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`${baseURL}/templates/${channelPath}-template-submitted/(.*)`) + new RegExp(`/templates/${channelPath}-template-submitted/(.*)`) ); await expect(basePage.pageHeader).toHaveText('Template submitted'); diff --git a/tests/security/tests/routing-config.security.ts b/tests/security/tests/routing-config.security.ts index 28c13d8d..30bc01f3 100644 --- a/tests/security/tests/routing-config.security.ts +++ b/tests/security/tests/routing-config.security.ts @@ -28,7 +28,6 @@ const getSeededTemplateConfig = async (configFile: string | undefined) => { const previewAndSelectTemplate = async ( page: Page, - baseURL: string | undefined, routingConfigId: string, channel: string, channelUrlSegment: string, @@ -37,11 +36,11 @@ const previewAndSelectTemplate = async ( await page.getByTestId(`choose-template-link-${channel}`).click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}\?(.*)`)); + await expect(page).toHaveURL(new RegExp(`/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}\?(.*)`)); await page.getByTestId(`${templateId}-preview-link`).click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}/preview-template/${templateId}\?(.*)`)); + await expect(page).toHaveURL(new RegExp(`/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}/preview-template/${templateId}\?(.*)`)); await expect(page.getByText(templateId)).toBeVisible(); await expect(page.getByText(templateName)).toBeVisible(); @@ -49,42 +48,41 @@ const previewAndSelectTemplate = async ( await page.getByTestId('back-link-bottom').click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}\?(.*)`)); + await expect(page).toHaveURL(new RegExp(`/templates/message-plans/choose-${channelUrlSegment}-template/${routingConfigId}\?(.*)`)); await page.getByTestId(`${templateId}-radio`).check(); await page.getByText('Save and continue').click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-templates/${routingConfigId}(.*)`)); + await expect(page).toHaveURL(new RegExp(`/templates/message-plans/choose-templates/${routingConfigId}(.*)`)); } -test(`User creates a multi-channel routing config`, async ({ page, baseURL, }, { config: { configFile } }) => { +test(`User creates a multi-channel routing config`, async ({ page }, { config: { configFile } }) => { const templates = await getSeededTemplateConfig(configFile); - await page.goto(`${baseURL}/templates/message-plans`); + await page.goto('/templates/message-plans'); await page.getByText('New message plan').click(); - await expect(page).toHaveURL(`${baseURL}/templates/message-plans/choose-message-order`); + await expect(page).toHaveURL('/templates/message-plans/choose-message-order'); await page.getByLabel('NHS App, Email, Text message', { exact: true }).check(); await page.getByText('Save and continue').click(); - await expect(page).toHaveURL(`${baseURL}/templates/message-plans/create-message-plan?messageOrder=NHSAPP%2CEMAIL%2CSMS`); + await expect(page).toHaveURL('/templates/message-plans/create-message-plan?messageOrder=NHSAPP%2CEMAIL%2CSMS'); await page.getByLabel('Message plan name').fill('message plan name'); await page.getByText('Save and continue').click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/choose-templates/(.*)`)); + await expect(page).toHaveURL(new RegExp('/templates/message-plans/choose-templates/(.*)')); const urlSegments = page.url().split('/'); const routingConfigId = urlSegments[urlSegments.length - 1]; await previewAndSelectTemplate( page, - baseURL, routingConfigId, 'NHSAPP', 'nhs-app', @@ -92,7 +90,6 @@ test(`User creates a multi-channel routing config`, async ({ page, baseURL, }, { ); await previewAndSelectTemplate( page, - baseURL, routingConfigId, 'EMAIL', 'email', @@ -100,7 +97,6 @@ test(`User creates a multi-channel routing config`, async ({ page, baseURL, }, { ); await previewAndSelectTemplate( page, - baseURL, routingConfigId, 'SMS', 'text-message', @@ -109,11 +105,11 @@ test(`User creates a multi-channel routing config`, async ({ page, baseURL, }, { await page.getByText('Move to production').click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/get-ready-to-move/${routingConfigId}(.*)`)); + await expect(page).toHaveURL(new RegExp(`/templates/message-plans/get-ready-to-move/${routingConfigId}(.*)`)); await page.getByText('Continue', { exact: true }).click(); - await expect(page).toHaveURL(new RegExp(`${baseURL}/templates/message-plans/review-and-move-to-production/${routingConfigId}(.*)`)); + await expect(page).toHaveURL(new RegExp(`/templates/message-plans/review-and-move-to-production/${routingConfigId}(.*)`)); // remaining pages not ready yet }); diff --git a/tests/security/tests/template-mgmt-cis2-login.security.ts b/tests/security/tests/template-mgmt-cis2-login.security.ts index 96e1d7e8..c31cf9e7 100644 --- a/tests/security/tests/template-mgmt-cis2-login.security.ts +++ b/tests/security/tests/template-mgmt-cis2-login.security.ts @@ -26,26 +26,20 @@ test.setTimeout(180_000); * - CIS2 'prompt=login' works to force a re-authentication */ test('User logs in via CIS2, saves data in templates, logs out and logs back in again', async ({ - baseURL, page, context, }) => { - if (!baseURL) { - throw new Error(`Missing baseURL ${baseURL}`); - } - const basePage = new TemplateMgmtBasePage(page); const letterPage = new TemplateMgmtLetterPage(page); const props = { basePage, - baseURL, letterPage, }; const channel = 'Email'; const channelPath = 'email'; const name = 'E2E Name'; - await startPage({ basePage, baseURL }); + await startPage({ basePage }); await loginWithCis2(basePage.page, 'Message templates'); await startNewTemplate(props); await chooseTemplate(props, channel); @@ -54,6 +48,6 @@ test('User logs in via CIS2, saves data in templates, logs out and logs back in await context.storageState({ path: 'login-state/cis2.json' }); await logOut(basePage); await page.waitForLoadState('networkidle'); - await startPage({ basePage, baseURL }); + await startPage({ basePage }); await loginWithCis2(basePage.page, 'Message templates'); }); diff --git a/tests/security/tests/templates-with-routing-disabled/template-mgmt-copy.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-copy.security.ts index 4b3ff370..f1c3c410 100644 --- a/tests/security/tests/templates-with-routing-disabled/template-mgmt-copy.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-copy.security.ts @@ -2,11 +2,10 @@ import { test } from '@playwright/test'; import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; -import { getRandomChannel } from 'nhs-notify-system-tests-shared'; import { startPage, chooseTemplate, - createTemplate, + createEmailTemplate, previewPage, startNewTemplate, copyTemplate, @@ -14,21 +13,19 @@ import { test.use({ storageState: 'login-state/copy.json' }); -test(`User copies a template`, async ({ page, baseURL }) => { +test(`User copies a template`, async ({ page }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; - const randomChannel = getRandomChannel(); - const channel = randomChannel.name; - const channelPath = randomChannel.path; - const name = 'Test edit'; + const channel = 'Email'; + const channelPath = 'email'; + const name = 'copy template e2e test'; await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); await copyTemplate(props, name); }); diff --git a/tests/security/tests/templates-with-routing-disabled/template-mgmt-delete.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-delete.security.ts index 57bd8159..14b3393a 100644 --- a/tests/security/tests/templates-with-routing-disabled/template-mgmt-delete.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-delete.security.ts @@ -5,7 +5,7 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, + createEmailTemplate, previewPage, startNewTemplate, deleteTemplate, @@ -15,20 +15,19 @@ test.use({ storageState: 'login-state/delete.json' }); test(`User deletes a template`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; + const channel = 'Email'; const channelPath = 'email'; - const name = 'Test delete' + const name = 'delete template e2e test'; await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); await deleteTemplate(props, name); }); diff --git a/tests/security/tests/templates-with-routing-disabled/template-mgmt-email.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-email.security.ts index 08698f9b..43b997eb 100644 --- a/tests/security/tests/templates-with-routing-disabled/template-mgmt-email.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-email.security.ts @@ -5,7 +5,7 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, + createEmailTemplate, previewPage, submitPage, startNewTemplate, @@ -16,20 +16,19 @@ test.use({ storageState: 'login-state/primary.json' }); test(`User creates and submits a new email template successfully`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; + const channel = 'Email'; const channelPath = 'email'; - const name = 'E2E Name'; + const name = 'email template e2e test'; await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); await previewPageChooseSubmit(props, channelPath); await submitPage(props, channelPath, name); diff --git a/tests/security/tests/templates-with-routing-disabled/template-mgmt-letter.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-letter.security.ts index d4b5c0fe..7293dc69 100644 --- a/tests/security/tests/templates-with-routing-disabled/template-mgmt-letter.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-letter.security.ts @@ -15,17 +15,15 @@ test.use({ storageState: 'login-state/primary.json' }); test(`User creates and submits a new letter template successfully`, async ({ page, - baseURL, }) => { test.setTimeout(240_000); // override just for this test const props = { basePage: new TemplateMgmtBasePage(page), letterPage: new TemplateMgmtLetterPage(page), - baseURL, }; const channel = 'Letter'; const channelPath = 'letter'; - const name = 'E2E Name'; + const name = 'letter template e2e test'; await startPage(props); await startNewTemplate(props); diff --git a/tests/security/tests/templates-with-routing-disabled/template-mgmt-nhsapp.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-nhsapp.security.ts index d5aee52d..6f3cb1b8 100644 --- a/tests/security/tests/templates-with-routing-disabled/template-mgmt-nhsapp.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-nhsapp.security.ts @@ -3,7 +3,7 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, + createNhsAppTemplate, previewPage, submitPage, startNewTemplate, @@ -14,21 +14,19 @@ test.use({ storageState: 'login-state/primary.json' }); test(`User creates and submits a new nhsapp template successfully`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'NHS App message'; const channelPath = 'nhs-app'; - const name = 'E2E Name'; + const name = 'nhs app template e2e test'; - await startPage(props); - await startNewTemplate(props); - await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); - await previewPage(props, channelPath, name); - await previewPageChooseSubmit(props, channelPath); - await submitPage(props, channelPath, name); + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createNhsAppTemplate(page, name); + await previewPage(props, channelPath, name); + await previewPageChooseSubmit(props, channelPath); + await submitPage(props, channelPath, name); }); diff --git a/tests/security/tests/templates-with-routing-disabled/template-mgmt-sms.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-sms.security.ts index c6b25e60..18493dfa 100644 --- a/tests/security/tests/templates-with-routing-disabled/template-mgmt-sms.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-sms.security.ts @@ -5,7 +5,7 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, + createSmsTemplate, previewPage, submitPage, startNewTemplate, @@ -16,20 +16,18 @@ test.use({ storageState: 'login-state/primary.json' }); test(`User creates and submits a new sms template successfully`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'Text message (SMS)'; const channelPath = 'text-message'; - const name = 'E2E Name'; + const name = 'SMS template e2e test'; await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createSmsTemplate(page, name); await previewPage(props, channelPath, name); await previewPageChooseSubmit(props, channelPath); await submitPage(props, channelPath, name); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-copy.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-copy.security.ts index d576eae5..c0237eb4 100644 --- a/tests/security/tests/templates-with-routing-enabled/template-mgmt-copy.security.ts +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-copy.security.ts @@ -2,11 +2,10 @@ import { test } from '@playwright/test'; import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; -import { getRandomChannel } from 'nhs-notify-system-tests-shared'; import { startPage, chooseTemplate, - createTemplate, + createEmailTemplate, previewPage, startNewTemplate, copyTemplate, @@ -14,21 +13,19 @@ import { test.use({ storageState: 'login-state/copyRoutingEnabled.json' }); -test(`User copies a template`, async ({ page, baseURL }) => { +test(`User copies a template`, async ({ page }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; - const randomChannel = getRandomChannel(); - const channel = randomChannel.name; - const channelPath = randomChannel.path; - const name = 'Test edit'; + const channel = 'Email'; + const channelPath = 'email'; + const name = 'copy template e2e test - routing enabled'; await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); await copyTemplate(props, name); }); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-delete.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-delete.security.ts index 6c856f69..e1505588 100644 --- a/tests/security/tests/templates-with-routing-enabled/template-mgmt-delete.security.ts +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-delete.security.ts @@ -5,7 +5,7 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, + createEmailTemplate, previewPage, startNewTemplate, deleteTemplate, @@ -15,20 +15,19 @@ test.use({ storageState: 'login-state/deleteRoutingEnabled.json' }); test(`User deletes a template`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; + const channel = 'Email'; const channelPath = 'email'; - const name = 'Test delete' + const name = 'delete template e2e test - routing enabled'; await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); await deleteTemplate(props, name); }); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-email.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-email.security.ts index 8515795d..fd8a02af 100644 --- a/tests/security/tests/templates-with-routing-enabled/template-mgmt-email.security.ts +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-email.security.ts @@ -5,30 +5,26 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, + createEmailTemplate, previewPage, - submitPage, startNewTemplate, - previewPageChooseSubmit, } from '../../functions/common-steps'; test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); test(`User creates and submits a new email template successfully`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'Email'; const channelPath = 'email'; - const name = 'E2E Name'; + const name = 'email template e2e test - routing enabled'; await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); }); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-letter.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-letter.security.ts index 092580c1..6e65e763 100644 --- a/tests/security/tests/templates-with-routing-enabled/template-mgmt-letter.security.ts +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-letter.security.ts @@ -15,17 +15,15 @@ test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); test(`User creates and submits a new letter template successfully`, async ({ page, - baseURL, }) => { test.setTimeout(240_000); // override just for this test const props = { basePage: new TemplateMgmtBasePage(page), letterPage: new TemplateMgmtLetterPage(page), - baseURL, }; const channel = 'Letter'; const channelPath = 'letter'; - const name = 'E2E Name'; + const name = 'letter template e2e test - routing enabled'; await startPage(props); await startNewTemplate(props); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-nhsapp.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-nhsapp.security.ts index 2340cf7f..5e6afd21 100644 --- a/tests/security/tests/templates-with-routing-enabled/template-mgmt-nhsapp.security.ts +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-nhsapp.security.ts @@ -3,30 +3,26 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, + createNhsAppTemplate, previewPage, - submitPage, startNewTemplate, - previewPageChooseSubmit, } from '../../functions/common-steps'; test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); test(`User creates and submits a new nhsapp template successfully`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'NHS App message'; const channelPath = 'nhs-app'; - const name = 'E2E Name'; + const name = 'nhs app template e2e test - routing enabled'; - await startPage(props); - await startNewTemplate(props); - await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); - await previewPage(props, channelPath, name); + await startPage(props); + await startNewTemplate(props); + await chooseTemplate(props, channel); + await createNhsAppTemplate(page, name); + await previewPage(props, channelPath, name); }); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-sms.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-sms.security.ts index 028752e4..a863ad02 100644 --- a/tests/security/tests/templates-with-routing-enabled/template-mgmt-sms.security.ts +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-sms.security.ts @@ -5,30 +5,26 @@ import { TemplateMgmtBasePage } from '../../pages/template-mgmt-base-page'; import { startPage, chooseTemplate, - createTemplate, + createSmsTemplate, previewPage, - submitPage, startNewTemplate, - previewPageChooseSubmit, } from '../../functions/common-steps'; test.use({ storageState: 'login-state/primaryRoutingEnabled.json' }); test(`User creates and submits a new sms template successfully`, async ({ page, - baseURL, }) => { const props = { basePage: new TemplateMgmtBasePage(page), - baseURL, }; const channel = 'Text message (SMS)'; const channelPath = 'text-message'; - const name = 'E2E Name'; + const name = 'SMS template e2e test - routing enabled'; await startPage(props); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createSmsTemplate(page, name); await previewPage(props, channelPath, name); }); diff --git a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts index f805574f..bd651901 100644 --- a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts +++ b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts @@ -84,53 +84,13 @@ export async function createEmailTemplate( await expect(page.getByTestId('navigation-links')).toBeVisible(); - console.log( - name, - 'log 1', - await page.locator('[id="emailTemplateName"]').inputValue(), - await page.locator('[id="emailTemplateSubjectLine"]').inputValue(), - await page.locator('[id="emailTemplateMessage"]').inputValue() - ); - - await page.locator('[id="emailTemplateName"]').fill(name); + await page.getByLabel('Template name').fill(name); - console.log( - name, - 'log 2', - await page.locator('[id="emailTemplateName"]').inputValue(), - await page.locator('[id="emailTemplateSubjectLine"]').inputValue(), - await page.locator('[id="emailTemplateMessage"]').inputValue() - ); + await page.getByLabel('Subject line').fill('E2E subject'); - await page.locator('[id="emailTemplateSubjectLine"]').fill('E2E subject'); - - console.log( - name, - 'log 3', - await page.locator('[id="emailTemplateName"]').inputValue(), - await page.locator('[id="emailTemplateSubjectLine"]').inputValue(), - await page.locator('[id="emailTemplateMessage"]').inputValue() - ); - - await page.locator('[id="emailTemplateMessage"]').fill('E2E Message'); - - console.log( - name, - 'log 4', - await page.locator('[id="emailTemplateName"]').inputValue(), - await page.locator('[id="emailTemplateSubjectLine"]').inputValue(), - await page.locator('[id="emailTemplateMessage"]').inputValue() - ); + await page.getByLabel('Message').fill('E2E Message'); await page.getByText('Save and preview').click(); - - console.log( - name, - 'log 5', - await page.locator('[id="emailTemplateName"]').inputValue(), - await page.locator('[id="emailTemplateSubjectLine"]').inputValue(), - await page.locator('[id="emailTemplateMessage"]').inputValue() - ); } export async function createSmsTemplate( @@ -143,39 +103,11 @@ export async function createSmsTemplate( await expect(page.getByTestId('navigation-links')).toBeVisible(); - console.log( - name, - 'log 1', - await page.locator('[id="smsTemplateName"]').inputValue(), - await page.locator('[id="smsTemplateMessage"]').inputValue() - ); - - await page.locator('[id="smsTemplateName"]').fill(name); - - console.log( - name, - 'log 2', - await page.locator('[id="smsTemplateName"]').inputValue(), - await page.locator('[id="smsTemplateMessage"]').inputValue() - ); - - await page.locator('[id="smsTemplateMessage"]').fill('E2E Message'); + await page.getByLabel('Template name').fill(name); - console.log( - name, - 'log 3', - await page.locator('[id="smsTemplateName"]').inputValue(), - await page.locator('[id="smsTemplateMessage"]').inputValue() - ); + await page.getByLabel('Message').fill('E2E Message'); await page.getByText('Save and preview').click(); - - console.log( - name, - 'log 4', - await page.locator('[id="smsTemplateName"]').inputValue(), - await page.locator('[id="smsTemplateMessage"]').inputValue() - ); } export async function createNhsAppTemplate( @@ -187,40 +119,12 @@ export async function createNhsAppTemplate( ); await expect(page.getByTestId('navigation-links')).toBeVisible(); - - console.log( - name, - 'log 1', - await page.locator('[id="nhsAppTemplateName"]').inputValue(), - await page.locator('[id="nhsAppTemplateMessage"]').inputValue() - ); - await page.locator('[id="nhsAppTemplateName"]').fill(name); + await page.getByLabel('Template name').fill(name); - console.log( - name, - 'log 2', - await page.locator('[id="nhsAppTemplateName"]').inputValue(), - await page.locator('[id="nhsAppTemplateMessage"]').inputValue() - ); - - await page.locator('[id="nhsAppTemplateMessage"]').fill('E2E Message'); - - console.log( - name, - 'log 3', - await page.locator('[id="nhsAppTemplateName"]').inputValue(), - await page.locator('[id="nhsAppTemplateMessage"]').inputValue() - ); + await page.getByLabel('Message').fill('E2E Message'); await page.getByText('Save and preview').click(); - - console.log( - name, - 'log 4', - await page.locator('[id="nhsAppTemplateName"]').inputValue(), - await page.locator('[id="nhsAppTemplateMessage"]').inputValue() - ); } diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts index 34433dd7..25a71616 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-email-e2e.ts @@ -20,6 +20,7 @@ test(`User creates and submits a new email template successfully`, async ({ const props = { basePage: new TemplateMgmtBasePage(page), }; + const channel = 'Email'; const channelPath = 'email'; const name = 'email template e2e test'; diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts index 5de7b4d3..ebac7b31 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-delete-e2e.ts @@ -19,6 +19,7 @@ test(`User deletes a template - routing enabled`, async ({ const props = { basePage: new TemplateMgmtBasePage(page), }; + const channel = 'Email'; const channelPath = 'email'; const name = 'delete template e2e test - routing enabled'; From 53dbc703ef0898dda470c585e4bf5d7a3efff8b9 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Tue, 10 Feb 2026 08:58:43 +0000 Subject: [PATCH 21/27] CCM-14061: Fix security tests --- .github/actions/security-scan/action.yaml | 10 ++++++++++ tests/security/functions/common-steps.ts | 12 ++++++++---- .../tests/template-mgmt-cis2-login.security.ts | 6 +++--- .../template-mgmt-copy.security.ts | 2 +- .../template-mgmt-copy.security.ts | 2 +- .../functions/template-mgmt-e2e-common-steps.ts | 5 +---- .../template-mgmt-cis2-login-e2e.ts | 3 ++- .../template-mgmt-copy-e2e.ts | 2 +- .../template-mgmt-copy-e2e.ts | 2 +- 9 files changed, 28 insertions(+), 16 deletions(-) diff --git a/.github/actions/security-scan/action.yaml b/.github/actions/security-scan/action.yaml index 2429c814..54e9e33f 100644 --- a/.github/actions/security-scan/action.yaml +++ b/.github/actions/security-scan/action.yaml @@ -39,6 +39,16 @@ runs: gh run download "${{ inputs.github_run_id }}" --repo "${{ inputs.github_repository }}" --name "$ARTIFACT_NAME" --dir "$DEST_PATH" shell: bash + - name: Download setup JSON artifact (templates service) + env: + GH_TOKEN: ${{ inputs.github_token }} + run: | + ARTIFACT_NAME="templates-state" + DEST_PATH="./tests/security/lifecycle/templates" + echo "Downloading artifact '$ARTIFACT_NAME' to $DEST_PATH ..." + gh run download "${{ inputs.github_run_id }}" --repo "${{ inputs.github_repository }}" --name "$ARTIFACT_NAME" --dir "$DEST_PATH" + shell: bash + - name: Run test - security scan id: test shell: bash diff --git a/tests/security/functions/common-steps.ts b/tests/security/functions/common-steps.ts index ff444551..070c98d1 100644 --- a/tests/security/functions/common-steps.ts +++ b/tests/security/functions/common-steps.ts @@ -180,7 +180,7 @@ export function previewPageChooseSubmit( await expect(basePage.page).toHaveURL( // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`}/templates/submit-${channelPath}-template/(.*)`) + new RegExp(`/templates/submit-${channelPath}-template/(.*)`) ); }); } @@ -217,7 +217,7 @@ export function deleteTemplate( export function copyTemplate( { basePage }: CommonStepsProps, - name:string + routingEnabled = false, ) { return test.step('Copy template', async () => { await basePage.goBackLink.click(); @@ -247,8 +247,12 @@ export function copyTemplate( await basePage.page.reload(); // shouldn't need to do this await basePage.clickFirstTableRowLink(); - await basePage.checkRadio('Edit template'); - await basePage.clickButtonByName('Continue'); + if (routingEnabled) { + await basePage.page.getByText('Edit template').click(); + } else { + await basePage.checkRadio('Edit template'); + await basePage.clickButtonByName('Continue'); + } const timestamp = Date.now(); const editedTemplateName = `Test edit changed ${timestamp}`; await basePage.fillTextBox('Template name', editedTemplateName); diff --git a/tests/security/tests/template-mgmt-cis2-login.security.ts b/tests/security/tests/template-mgmt-cis2-login.security.ts index c31cf9e7..06455f61 100644 --- a/tests/security/tests/template-mgmt-cis2-login.security.ts +++ b/tests/security/tests/template-mgmt-cis2-login.security.ts @@ -4,7 +4,7 @@ import { loginWithCis2, logOut } from '../functions/login'; import { TemplateMgmtBasePage } from '../pages/template-mgmt-base-page'; import { chooseTemplate, - createTemplate, + createEmailTemplate, previewPage, startNewTemplate, startPage, @@ -37,13 +37,13 @@ test('User logs in via CIS2, saves data in templates, logs out and logs back in }; const channel = 'Email'; const channelPath = 'email'; - const name = 'E2E Name'; + const name = 'CIS2 login test'; await startPage({ basePage }); await loginWithCis2(basePage.page, 'Message templates'); await startNewTemplate(props); await chooseTemplate(props, channel); - await createTemplate(props, channel, channelPath, name); + await createEmailTemplate(page, name); await previewPage(props, channelPath, name); await context.storageState({ path: 'login-state/cis2.json' }); await logOut(basePage); diff --git a/tests/security/tests/templates-with-routing-disabled/template-mgmt-copy.security.ts b/tests/security/tests/templates-with-routing-disabled/template-mgmt-copy.security.ts index f1c3c410..054b3af7 100644 --- a/tests/security/tests/templates-with-routing-disabled/template-mgmt-copy.security.ts +++ b/tests/security/tests/templates-with-routing-disabled/template-mgmt-copy.security.ts @@ -27,5 +27,5 @@ test(`User copies a template`, async ({ page }) => { await chooseTemplate(props, channel); await createEmailTemplate(page, name); await previewPage(props, channelPath, name); - await copyTemplate(props, name); + await copyTemplate(props); }); diff --git a/tests/security/tests/templates-with-routing-enabled/template-mgmt-copy.security.ts b/tests/security/tests/templates-with-routing-enabled/template-mgmt-copy.security.ts index c0237eb4..abd4249e 100644 --- a/tests/security/tests/templates-with-routing-enabled/template-mgmt-copy.security.ts +++ b/tests/security/tests/templates-with-routing-enabled/template-mgmt-copy.security.ts @@ -27,5 +27,5 @@ test(`User copies a template`, async ({ page }) => { await chooseTemplate(props, channel); await createEmailTemplate(page, name); await previewPage(props, channelPath, name); - await copyTemplate(props, name); + await copyTemplate(props, true); }); diff --git a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts index bd651901..50da6d55 100644 --- a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts +++ b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts @@ -224,7 +224,6 @@ export function deleteTemplate( export function copyTemplate( { basePage }: CommonStepsProps, - name: string, routingEnabled = false, ) { return test.step('Copy template', async () => { @@ -243,15 +242,13 @@ export function copyTemplate( } await expect(basePage.page).toHaveURL( - // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`/templates/copy-template/(.*)`) + new RegExp('/templates/copy-template/(.*)') ); await basePage.checkRadio('Email'); await basePage.clickButtonByName('Continue'); await expect(basePage.page).toHaveURL( - // eslint-disable-next-line security/detect-non-literal-regexp '/templates/message-templates' ); diff --git a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts index 084640b9..7a1bd0d5 100644 --- a/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/template-mgmt-cis2-login-e2e.ts @@ -27,6 +27,7 @@ test('User logs in via CIS2, saves data in templates, logs out and logs back in page, context, }) => { + test.setTimeout(120_000); const basePage = new TemplateMgmtBasePage(page); const props = { @@ -34,7 +35,7 @@ test('User logs in via CIS2, saves data in templates, logs out and logs back in }; const channel = 'Email'; const channelPath = 'email'; - const name = 'E2E Name'; + const name = 'CIS2 login test'; await startPage({ basePage }); await loginWithCis2(basePage.page, 'Message templates'); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts index 49b04053..3057de13 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-disabled/template-mgmt-copy-e2e.ts @@ -30,5 +30,5 @@ test(`User copies a template`, async ({ page }) => { await chooseTemplate(props, channel); await createEmailTemplate(page, name); await previewPage(props, channelPath, name); - await copyTemplate(props, name); + await copyTemplate(props); }); diff --git a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts index 73fabd27..ef8f1d0b 100644 --- a/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts +++ b/tests/test-team/template-mgmt-e2e-tests/templates-with-routing-enabled/template-mgmt-copy-e2e.ts @@ -29,5 +29,5 @@ test(`User copies a template - routing enabled`, async ({ page }) => { await chooseTemplate(props, channel); await createEmailTemplate(page, name); await previewPage(props, channelPath, name); - await copyTemplate(props, name, true); + await copyTemplate(props, true); }); From 14b919d5212c18131942c1ecf34cc157e885a659 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Tue, 10 Feb 2026 10:02:59 +0000 Subject: [PATCH 22/27] CCM-14061: Change OUTOFSCOPE to IGNORE --- tests/security/rules.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/security/rules.conf b/tests/security/rules.conf index c790a8ca..ee97e255 100644 --- a/tests/security/rules.conf +++ b/tests/security/rules.conf @@ -13,7 +13,7 @@ # Already using AJAX spider 10109 IGNORE (Modern Web Application) # Timestamp disclosure - false positives -10096 OUTOFSCOPE .*_next/static.* +10096 IGNORE .*_next/static.* # Suspicious comments - false positives 10027 IGNORE (Information Disclosure - Suspicious Comments) # Identifies a 'hot-spot' for potential XSS if input is not validated From 861076abf5d59c05e08ddc27a32dcfc7c44a1c1f Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Tue, 10 Feb 2026 13:06:28 +0000 Subject: [PATCH 23/27] CCM-14061: Review comments --- tests/security/fixtures/clients.ts | 6 +++--- tests/security/fixtures/users.ts | 12 ++++++------ tests/security/lifecycle/templates/setup.ts | 6 +++--- tests/security/rules.conf | 2 +- tests/test-team/fixtures/clients.ts | 6 +++--- tests/test-team/fixtures/users.ts | 12 ++++++------ tests/test-team/lifecycle/templates/setup.ts | 6 +++--- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/security/fixtures/clients.ts b/tests/security/fixtures/clients.ts index d534be97..0b1a3fc4 100644 --- a/tests/security/fixtures/clients.ts +++ b/tests/security/fixtures/clients.ts @@ -45,7 +45,7 @@ export const clients: Record = { name: 'Client 4 Security ZAP Spider Scan', }, }, - PrimaryRoutingEnabled: { + PrimaryRoutingEnabledSec: { templates: { campaignIds: ['PrimaryRoutingEnabled-Campaign'], features: { @@ -57,7 +57,7 @@ export const clients: Record = { name: 'Primary - Routing Enabled', }, }, - CopyRoutingEnabled: { + CopyRoutingEnableSec: { templates: { campaignIds: ['CopyRoutingEnabled-Campaign'], features: { @@ -69,7 +69,7 @@ export const clients: Record = { name: 'Copy - Routing Enabled', }, }, - DeleteRoutingEnabled: { + DeleteRoutingEnabledSec: { templates: { campaignIds: ['DeleteRoutingEnabled-Campaign'], features: { diff --git a/tests/security/fixtures/users.ts b/tests/security/fixtures/users.ts index 19a683fe..c572c4ff 100644 --- a/tests/security/fixtures/users.ts +++ b/tests/security/fixtures/users.ts @@ -19,15 +19,15 @@ export const users: Record = { clientConfig: clients['SecSpider'].auth, }, primaryRoutingEnabled: { - clientKey: 'PrimaryRoutingEnabled', - clientConfig: clients['PrimaryRoutingEnabled'].auth, + clientKey: 'PrimaryRoutingEnabledSec', + clientConfig: clients['PrimaryRoutingEnabledSec'].auth, }, copyRoutingEnabled: { - clientKey: 'CopyRoutingEnabled', - clientConfig: clients['CopyRoutingEnabled'].auth, + clientKey: 'CopyRoutingEnabledSec', + clientConfig: clients['CopyRoutingEnabledSec'].auth, }, deleteRoutingEnabled: { - clientKey: 'DeleteRoutingEnabled', - clientConfig: clients['DeleteRoutingEnabled'].auth, + clientKey: 'DeleteRoutingEnabledSec', + clientConfig: clients['DeleteRoutingEnabledSec'].auth, }, }; diff --git a/tests/security/lifecycle/templates/setup.ts b/tests/security/lifecycle/templates/setup.ts index f18f4c5b..ec91808e 100644 --- a/tests/security/lifecycle/templates/setup.ts +++ b/tests/security/lifecycle/templates/setup.ts @@ -55,7 +55,7 @@ async function main() { const multiChannelRoutingConfigNhsAppTemplate = TemplateFactory.create( randomUUID(), - clientIds['PrimaryRoutingEnabled'], + clientIds['PrimaryRoutingEnabledSec'], TemplateType.NHS_APP, { name: 'multi-channel-routing-config-nhsapp-template-name', @@ -66,7 +66,7 @@ async function main() { const multiChannelRoutingConfigEmailTemplate = TemplateFactory.create( randomUUID(), - clientIds['PrimaryRoutingEnabled'], + clientIds['PrimaryRoutingEnabledSec'], TemplateType.EMAIL, { name: 'multi-channel-routing-config-email-template-name', @@ -78,7 +78,7 @@ async function main() { const multiChannelRoutingConfigSmsTemplate = TemplateFactory.create( randomUUID(), - clientIds['PrimaryRoutingEnabled'], + clientIds['PrimaryRoutingEnabledSec'], TemplateType.SMS, { name: 'multi-channel-routing-config-sms-template-name', diff --git a/tests/security/rules.conf b/tests/security/rules.conf index ee97e255..5d3bf755 100644 --- a/tests/security/rules.conf +++ b/tests/security/rules.conf @@ -13,7 +13,7 @@ # Already using AJAX spider 10109 IGNORE (Modern Web Application) # Timestamp disclosure - false positives -10096 IGNORE .*_next/static.* +10096 IGNORE (Timestamp Disclosure) # Suspicious comments - false positives 10027 IGNORE (Information Disclosure - Suspicious Comments) # Identifies a 'hot-spot' for potential XSS if input is not validated diff --git a/tests/test-team/fixtures/clients.ts b/tests/test-team/fixtures/clients.ts index 178aca0c..fcbc5242 100644 --- a/tests/test-team/fixtures/clients.ts +++ b/tests/test-team/fixtures/clients.ts @@ -37,7 +37,7 @@ export const clients: Record = { name: 'Client 3 Product', }, }, - PrimaryRoutingEnabled: { + PrimaryRoutingEnabledProduct: { templates: { campaignIds: ['PrimaryRoutingEnabled-Campaign'], features: { @@ -49,7 +49,7 @@ export const clients: Record = { name: 'Primary - Routing Enabled', }, }, - CopyRoutingEnabled: { + CopyRoutingEnabledProduct: { templates: { campaignIds: ['CopyRoutingEnabled-Campaign'], features: { @@ -61,7 +61,7 @@ export const clients: Record = { name: 'Copy - Routing Enabled', }, }, - DeleteRoutingEnabled: { + DeleteRoutingEnabledProduct: { templates: { campaignIds: ['DeleteRoutingEnabled-Campaign'], features: { diff --git a/tests/test-team/fixtures/users.ts b/tests/test-team/fixtures/users.ts index acdb6c94..51a5cdcf 100644 --- a/tests/test-team/fixtures/users.ts +++ b/tests/test-team/fixtures/users.ts @@ -15,15 +15,15 @@ export const users: Record = { clientConfig: clients['Client3Product'].auth, }, primaryRoutingEnabled: { - clientKey: 'PrimaryRoutingEnabled', - clientConfig: clients['PrimaryRoutingEnabled'].auth, + clientKey: 'PrimaryRoutingEnabledProduct', + clientConfig: clients['PrimaryRoutingEnabledProduct'].auth, }, copyRoutingEnabled: { - clientKey: 'CopyRoutingEnabled', - clientConfig: clients['CopyRoutingEnabled'].auth, + clientKey: 'CopyRoutingEnabledProduct', + clientConfig: clients['CopyRoutingEnabledProduct'].auth, }, deleteRoutingEnabled: { - clientKey: 'DeleteRoutingEnabled', - clientConfig: clients['DeleteRoutingEnabled'].auth, + clientKey: 'DeleteRoutingEnabledProduct', + clientConfig: clients['DeleteRoutingEnabledProduct'].auth, }, }; diff --git a/tests/test-team/lifecycle/templates/setup.ts b/tests/test-team/lifecycle/templates/setup.ts index eff62182..70c0f2cf 100644 --- a/tests/test-team/lifecycle/templates/setup.ts +++ b/tests/test-team/lifecycle/templates/setup.ts @@ -52,7 +52,7 @@ async function main() { const multiChannelRoutingConfigNhsAppTemplate = TemplateFactory.create( randomUUID(), - clientIds['PrimaryRoutingEnabled'], + clientIds['PrimaryRoutingEnabledProduct'], TemplateType.NHS_APP, { name: 'multi-channel-routing-config-nhsapp-template-name', @@ -63,7 +63,7 @@ async function main() { const multiChannelRoutingConfigEmailTemplate = TemplateFactory.create( randomUUID(), - clientIds['PrimaryRoutingEnabled'], + clientIds['PrimaryRoutingEnabledProduct'], TemplateType.EMAIL, { name: 'multi-channel-routing-config-email-template-name', @@ -75,7 +75,7 @@ async function main() { const multiChannelRoutingConfigSmsTemplate = TemplateFactory.create( randomUUID(), - clientIds['PrimaryRoutingEnabled'], + clientIds['PrimaryRoutingEnabledProduct'], TemplateType.SMS, { name: 'multi-channel-routing-config-sms-template-name', From bb3317a6be910112f4c9c39f06c8ee64a5654147 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Tue, 10 Feb 2026 13:40:19 +0000 Subject: [PATCH 24/27] CCM-14061: Debug --- tests/security/functions/common-steps.ts | 21 ++++++++++++++++--- .../template-mgmt-e2e-common-steps.ts | 21 ++++++++++++++++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/tests/security/functions/common-steps.ts b/tests/security/functions/common-steps.ts index 070c98d1..86560a6a 100644 --- a/tests/security/functions/common-steps.ts +++ b/tests/security/functions/common-steps.ts @@ -87,7 +87,12 @@ export async function createEmailTemplate( await page.getByLabel('Message').fill('E2E Message'); - await page.getByText('Save and preview').click(); + await page.getByText('Save and preview').click({ + position: { + x: 50, + y: 50 + } + }); } export async function createSmsTemplate( @@ -104,7 +109,12 @@ export async function createSmsTemplate( await page.getByLabel('Message').fill('E2E Message'); - await page.getByText('Save and preview').click(); + await page.getByText('Save and preview').click({ + position: { + x: 50, + y: 50 + } + }); } export async function createNhsAppTemplate( @@ -121,7 +131,12 @@ export async function createNhsAppTemplate( await page.getByLabel('Message').fill('E2E Message'); - await page.getByText('Save and preview').click(); + await page.getByText('Save and preview').click({ + position: { + x: 50, + y: 50 + } + }); } export function requestProof( diff --git a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts index 50da6d55..c6be7378 100644 --- a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts +++ b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts @@ -90,7 +90,12 @@ export async function createEmailTemplate( await page.getByLabel('Message').fill('E2E Message'); - await page.getByText('Save and preview').click(); + await page.getByText('Save and preview').click({ + position: { + x: 50, + y: 50 + } + }); } export async function createSmsTemplate( @@ -107,7 +112,12 @@ export async function createSmsTemplate( await page.getByLabel('Message').fill('E2E Message'); - await page.getByText('Save and preview').click(); + await page.getByText('Save and preview').click({ + position: { + x: 50, + y: 50 + } + }); } export async function createNhsAppTemplate( @@ -124,7 +134,12 @@ export async function createNhsAppTemplate( await page.getByLabel('Message').fill('E2E Message'); - await page.getByText('Save and preview').click(); + await page.getByText('Save and preview').click({ + position: { + x: 50, + y: 50 + } + }); } From a398f41d73f6255d07288c19e3ac46112a1990f6 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Tue, 10 Feb 2026 13:55:07 +0000 Subject: [PATCH 25/27] CCM-14061: Fix auth config --- tests/security/fixtures/clients.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/security/fixtures/clients.ts b/tests/security/fixtures/clients.ts index 0b1a3fc4..3db5f01d 100644 --- a/tests/security/fixtures/clients.ts +++ b/tests/security/fixtures/clients.ts @@ -57,7 +57,7 @@ export const clients: Record = { name: 'Primary - Routing Enabled', }, }, - CopyRoutingEnableSec: { + CopyRoutingEnabledSec: { templates: { campaignIds: ['CopyRoutingEnabled-Campaign'], features: { From 5d26944a99e4b0425bceed1bc3dc85ae4391672b Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Tue, 10 Feb 2026 14:18:11 +0000 Subject: [PATCH 26/27] CCM-14061: Test timeout --- tests/security/functions/login.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/security/functions/login.ts b/tests/security/functions/login.ts index daf5b22e..332d2ccc 100644 --- a/tests/security/functions/login.ts +++ b/tests/security/functions/login.ts @@ -19,7 +19,7 @@ async function enterCis2TotpCode( const happyPathSelector = page.getByText(targetHeadingText); const reVerificationSelector = page.locator(`//button[text()=' Re-enter verification code ']`); - await happyPathSelector.or(reVerificationSelector).waitFor({ timeout: 30_000 }); + await happyPathSelector.or(reVerificationSelector).waitFor({ timeout: 60_000 }); if (await happyPathSelector.isVisible()) { return true; } From 78c5ef0bb3ece9f910ea9b4b45bcc689fdeb4d2c Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Tue, 10 Feb 2026 14:45:59 +0000 Subject: [PATCH 27/27] CCM-14061: Fix CI --- tests/security/functions/common-steps.ts | 2 +- tests/test-team/functions/template-mgmt-e2e-common-steps.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/security/functions/common-steps.ts b/tests/security/functions/common-steps.ts index 86560a6a..f099f2ed 100644 --- a/tests/security/functions/common-steps.ts +++ b/tests/security/functions/common-steps.ts @@ -126,7 +126,7 @@ export async function createNhsAppTemplate( ); await expect(page.getByTestId('navigation-links')).toBeVisible(); - + await page.getByLabel('Template name').fill(name); await page.getByLabel('Message').fill('E2E Message'); diff --git a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts index c6be7378..38b1833d 100644 --- a/tests/test-team/functions/template-mgmt-e2e-common-steps.ts +++ b/tests/test-team/functions/template-mgmt-e2e-common-steps.ts @@ -129,7 +129,7 @@ export async function createNhsAppTemplate( ); await expect(page.getByTestId('navigation-links')).toBeVisible(); - + await page.getByLabel('Template name').fill(name); await page.getByLabel('Message').fill('E2E Message');