Skip to content

Commit f1df8be

Browse files
committed
CCM-11492 Tests WIP
1 parent ec56e09 commit f1df8be

File tree

15 files changed

+579
-27
lines changed

15 files changed

+579
-27
lines changed

frontend/src/content/content.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,23 +1062,23 @@ const messagePlanFallbackConditions: Record<
10621062
NHS_APP: {
10631063
title: 'Fallback conditions',
10641064
content: {
1065-
stop: 'If first message read within 24 hours, no further messages sent.',
1065+
stop: 'If first message read within 24 hours, no further messages sent.', // TODO: change
10661066
continue:
10671067
'If first message not read within 24 hours, second message sent.',
10681068
},
10691069
},
10701070
SMS: {
10711071
title: 'Fallback conditions',
10721072
content: {
1073-
stop: 'If first message read within 24 hours, no further messages sent.',
1073+
stop: 'If first message read within 24 hours, no further messages sent.', // TODO: change
10741074
continue:
10751075
'If first message not read within 24 hours, second message sent.',
10761076
},
10771077
},
10781078
EMAIL: {
10791079
title: 'Fallback conditions',
10801080
content: {
1081-
stop: 'If first message read within 24 hours, no further messages sent.',
1081+
stop: 'If first message read within 24 hours, no further messages sent.', // TODO: change
10821082
continue:
10831083
'If first message not read within 24 hours, second message sent.',
10841084
},

lambdas/backend-client/src/types/generated/types.gen.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,16 @@ export type CascadeGroupTranslations = CascadeGroupBase & {
5050
export type CascadeItem = CascadeItemBase &
5151
(
5252
| {
53-
defaultTemplateId: string | null;
5453
conditionalTemplates?: Array<
5554
ConditionalTemplateLanguage | ConditionalTemplateAccessible
5655
>;
56+
defaultTemplateId: string | null;
5757
}
5858
| {
59-
defaultTemplateId?: string | null;
6059
conditionalTemplates: Array<
6160
ConditionalTemplateLanguage | ConditionalTemplateAccessible
6261
>;
62+
defaultTemplateId?: string | null;
6363
}
6464
);
6565

tests/test-team/helpers/enum.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1-
export const ROUTING_CONFIG_MESSAGE_ORDER_OPTION_MAPPINGS = [
1+
export const MESSAGE_ORDERS = [
2+
'NHSAPP',
3+
'NHSAPP,EMAIL',
4+
'NHSAPP,SMS',
5+
'NHSAPP,EMAIL,SMS',
6+
'NHSAPP,SMS,EMAIL',
7+
'NHSAPP,SMS,LETTER',
8+
'NHSAPP,EMAIL,SMS,LETTER',
9+
'LETTER',
10+
] as const;
11+
12+
export type MessageOrder = (typeof MESSAGE_ORDERS)[number];
13+
14+
export const ROUTING_CONFIG_MESSAGE_ORDER_OPTION_MAPPINGS: Array<{
15+
messageOrder: MessageOrder;
16+
label: string;
17+
}> = [
218
{
319
messageOrder: 'NHSAPP',
420
label: 'NHS App only',

tests/test-team/helpers/factories/routing-config-factory.ts

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,31 @@
11
import { randomUUID } from 'node:crypto';
22
import {
3+
CascadeGroupName,
4+
Channel,
5+
ChannelType,
36
CreateUpdateRoutingConfig,
47
RoutingConfig,
58
} from 'nhs-notify-backend-client';
69
import type {
7-
FactoryRoutingConfig,
10+
FactoryRoutingConfigWithModifiers,
811
RoutingConfigDbEntry,
912
} from '../../helpers/types';
1013
import { TestUser } from 'helpers/auth/cognito-auth-helper';
14+
import {
15+
MessageOrder,
16+
ROUTING_CONFIG_MESSAGE_ORDER_OPTION_MAPPINGS,
17+
} from 'helpers/enum';
1118

1219
export const RoutingConfigFactory = {
13-
create(
14-
user: TestUser,
15-
routingConfig: Partial<RoutingConfig> = {}
16-
): FactoryRoutingConfig {
20+
create(user: TestUser, routingConfig: Partial<RoutingConfig> = {}) {
1721
const apiPayload: CreateUpdateRoutingConfig = {
1822
campaignId: user.campaignIds?.[0] ?? 'campaign',
1923
cascade: [
2024
{
2125
cascadeGroups: ['standard'],
2226
channel: 'NHSAPP',
2327
channelType: 'primary',
24-
defaultTemplateId: '90e46ece-4a3b-47bd-b781-f986b42a5a09',
28+
defaultTemplateId: null,
2529
},
2630
],
2731
cascadeGroupOverrides: [{ name: 'standard' }],
@@ -45,10 +49,67 @@ export const RoutingConfigFactory = {
4549
...apiResponse,
4650
};
4751

48-
return {
52+
const factoryObj: FactoryRoutingConfigWithModifiers = {
4953
apiPayload,
5054
apiResponse,
5155
dbEntry,
56+
57+
addTemplate(channel: Channel, templateId?: string) {
58+
const id = templateId ?? randomUUID();
59+
for (const key of ['apiPayload', 'apiResponse', 'dbEntry'] as const) {
60+
for (const cascadeItem of this[key].cascade) {
61+
if (cascadeItem.channel === channel)
62+
cascadeItem.defaultTemplateId = id;
63+
}
64+
}
65+
return this;
66+
},
67+
68+
withTemplates(...channels: Channel[]) {
69+
for (const channel of channels) {
70+
this.addTemplate(channel);
71+
}
72+
return this;
73+
},
5274
};
75+
76+
return factoryObj;
77+
},
78+
79+
createWithChannels(
80+
user: TestUser,
81+
channels: Channel[],
82+
routingConfig: Partial<RoutingConfig> = {}
83+
) {
84+
const cascade = channels.map((channel) => ({
85+
cascadeGroups: ['standard' as CascadeGroupName],
86+
channel: channel,
87+
channelType: 'primary' as ChannelType,
88+
defaultTemplateId: null,
89+
}));
90+
return this.create(user, {
91+
cascade,
92+
...routingConfig,
93+
});
94+
},
95+
96+
createForMessageOrder(
97+
user: TestUser,
98+
messageOrder: MessageOrder,
99+
routingConfig: Partial<RoutingConfig> = {}
100+
) {
101+
const channels = messageOrder.split(',') as Channel[];
102+
103+
const nameMapping = ROUTING_CONFIG_MESSAGE_ORDER_OPTION_MAPPINGS.find(
104+
(mapItem) => mapItem.messageOrder === messageOrder
105+
);
106+
const planName = nameMapping
107+
? `Test config for ${nameMapping.label}`
108+
: 'Test config';
109+
110+
return this.createWithChannels(user, channels, {
111+
name: planName,
112+
...routingConfig,
113+
});
53114
},
54115
};

tests/test-team/helpers/types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type {
2+
Channel,
23
CreateUpdateRoutingConfig,
34
RoutingConfig,
45
} from 'nhs-notify-backend-client';
@@ -81,3 +82,11 @@ export type FactoryRoutingConfig = {
8182
apiResponse: RoutingConfig;
8283
dbEntry: RoutingConfigDbEntry;
8384
};
85+
86+
export type FactoryRoutingConfigWithModifiers = FactoryRoutingConfig & {
87+
addTemplate: (
88+
channel: Channel,
89+
templateId?: string
90+
) => FactoryRoutingConfigWithModifiers;
91+
withTemplates: (...channels: Channel[]) => FactoryRoutingConfigWithModifiers;
92+
};
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { Locator, type Page } from '@playwright/test';
2+
import { TemplateMgmtBasePageDynamic } from 'pages/template-mgmt-base-page-dynamic';
3+
4+
export class RoutingChooseTemplatesPage extends TemplateMgmtBasePageDynamic {
5+
static readonly pageUrlSegment = 'message-plans/choose-templates';
6+
7+
public readonly errorSummary: Locator;
8+
9+
public readonly changeNameLink: Locator;
10+
11+
public readonly routingConfigId: Locator;
12+
13+
public readonly messagePlanStatus: Locator;
14+
15+
public readonly channelBlocks: Locator;
16+
17+
public readonly moveToProductionButton: Locator;
18+
19+
public readonly saveAndCloseButton: Locator;
20+
21+
constructor(page: Page) {
22+
super(page);
23+
this.errorSummary = page.locator('.nhsuk-error-summary');
24+
this.changeNameLink = page.getByTestId('change-message-plan-name-link');
25+
this.routingConfigId = page.locator(
26+
'[class*=create-edit-message-plan-routing-config-id]'
27+
);
28+
this.messagePlanStatus = page.locator('strong.nhsuk-tag');
29+
this.channelBlocks = page.locator('[data-testid^="message-plan-block-"]');
30+
this.moveToProductionButton = page.getByTestId('move-to-production-cta');
31+
this.saveAndCloseButton = page.getByTestId('save-and-close-cta');
32+
}
33+
34+
public messagePlanChannel(channel: string) {
35+
return {
36+
block: this.page.getByTestId(`message-plan-block-${channel}`),
37+
number: this.page
38+
.getByTestId(`message-plan-block-${channel}`)
39+
.locator('[class*=message-plan-block-number]'),
40+
heading: this.page
41+
.getByTestId(`message-plan-block-${channel}`)
42+
.getByRole('heading', { level: 3 }),
43+
templateName: this.page.getByTestId(`template-name-${channel}`),
44+
fallbackConditions: this.page.getByTestId(
45+
`message-plan-fallback-conditions-${channel}`
46+
),
47+
changeTemplateLink: this.page.getByTestId(
48+
`change-template-link-${channel}`
49+
),
50+
chooseTemplateLink: this.page.getByTestId(
51+
`choose-template-link-${channel}`
52+
),
53+
removeTemplateLink: this.page.getByTestId(
54+
`remove-template-link-${channel}`
55+
),
56+
async clickChooseTemplateLink() {
57+
await this.chooseTemplateLink.click();
58+
},
59+
async clickChangeTemplateLink() {
60+
await this.changeTemplateLink.click();
61+
},
62+
async clickRemoveTemplateLink() {
63+
await this.removeTemplateLink.click();
64+
},
65+
};
66+
}
67+
68+
public readonly nhsApp = this.messagePlanChannel('NHSAPP');
69+
70+
public readonly sms = this.messagePlanChannel('SMS');
71+
72+
public readonly email = this.messagePlanChannel('EMAIL');
73+
74+
public readonly letter = this.messagePlanChannel('LETTER');
75+
76+
async clickMoveToProduction() {
77+
await this.moveToProductionButton.click();
78+
}
79+
80+
async clickSaveAndClose() {
81+
await this.saveAndCloseButton.click();
82+
}
83+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { TemplateMgmtBasePageNonDynamic } from '../template-mgmt-base-page-non-dynamic';
2+
3+
export class RoutingInvalidMessagePlanPage extends TemplateMgmtBasePageNonDynamic {
4+
static readonly pageUrlSegment = 'message-plans/invalid';
5+
}

tests/test-team/pages/routing-message-plans-page.ts renamed to tests/test-team/pages/routing/message-plans-page.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Locator, type Page } from '@playwright/test';
2-
import { TemplateMgmtBasePageNonDynamic } from './template-mgmt-base-page-non-dynamic';
2+
import { TemplateMgmtBasePageNonDynamic } from '../template-mgmt-base-page-non-dynamic';
33

44
export class RoutingMessagePlansPage extends TemplateMgmtBasePageNonDynamic {
55
static readonly pageUrlSegment = 'message-plans';

tests/test-team/pages/template-mgmt-base-page-dynamic.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ export abstract class TemplateMgmtBasePageDynamic extends TemplateMgmtBasePage {
88
super(page);
99
}
1010

11-
async loadPage(templateId: string) {
11+
async loadPage(idParameter: string) {
1212
const { appUrlSegment, pageUrlSegment } = this
1313
.constructor as typeof TemplateMgmtBasePageDynamic;
1414

1515
if (!pageUrlSegment) {
1616
throw new Error('pageUrlSegment is not defined');
1717
}
1818

19-
await this.navigateTo(`/${appUrlSegment}/${pageUrlSegment}/${templateId}`);
19+
await this.navigateTo(`/${appUrlSegment}/${pageUrlSegment}/${idParameter}`);
2020
}
2121
}

tests/test-team/pages/template-mgmt-base-page.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ export abstract class TemplateMgmtBasePage {
6969
.and(page.getByText('Skip to main content'));
7070
}
7171

72-
abstract loadPage(templateId?: string): Promise<void>;
72+
abstract loadPage(idParameter?: string): Promise<void>;
7373

74-
async attemptToLoadPageExpectFailure(templateId?: string) {
75-
await this.loadPage(templateId);
74+
async attemptToLoadPageExpectFailure(idParameter?: string) {
75+
await this.loadPage(idParameter);
7676
}
7777

7878
async navigateTo(url: string) {

0 commit comments

Comments
 (0)