Skip to content

Commit 4b8a487

Browse files
CCM-11537: Backend filter
1 parent 6c50aeb commit 4b8a487

File tree

34 files changed

+1314
-571
lines changed

34 files changed

+1314
-571
lines changed

frontend/src/__tests__/components/forms/CopyTemplate/CopyTemplate.test.tsx

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { mockDeep } from 'jest-mock-extended';
55
import { render, screen, fireEvent } from '@testing-library/react';
66
import { CopyTemplate, ValidCopyType } from '@forms/CopyTemplate/CopyTemplate';
77
import { TemplateFormState } from 'nhs-notify-web-template-management-utils';
8-
import { ValidatedTemplateDto } from 'nhs-notify-backend-client';
8+
import { TemplateDto } from 'nhs-notify-backend-client';
99

1010
jest.mock('@utils/amplify-utils');
1111

@@ -32,9 +32,7 @@ describe('Choose template page', () => {
3232
it('selects one radio button at a time', () => {
3333
const container = render(
3434
<CopyTemplate
35-
template={mockDeep<
36-
ValidatedTemplateDto & { templateType: ValidCopyType }
37-
>()}
35+
template={mockDeep<TemplateDto & { templateType: ValidCopyType }>()}
3836
/>
3937
);
4038
expect(container.asFragment()).toMatchSnapshot();
@@ -84,9 +82,7 @@ describe('Choose template page', () => {
8482

8583
const container = render(
8684
<CopyTemplate
87-
template={mockDeep<
88-
ValidatedTemplateDto & { templateType: ValidCopyType }
89-
>()}
85+
template={mockDeep<TemplateDto & { templateType: ValidCopyType }>()}
9086
/>
9187
);
9288
expect(container.asFragment()).toMatchSnapshot();
@@ -95,9 +91,7 @@ describe('Choose template page', () => {
9591
test('Client-side validation triggers', () => {
9692
const container = render(
9793
<CopyTemplate
98-
template={mockDeep<
99-
ValidatedTemplateDto & { templateType: ValidCopyType }
100-
>()}
94+
template={mockDeep<TemplateDto & { templateType: ValidCopyType }>()}
10195
/>
10296
);
10397
const submitButton = screen.getByTestId('submit-button');

frontend/src/__tests__/utils/form-actions.test.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
createRoutingConfig,
1919
} from '@utils/form-actions';
2020
import { getSessionServer } from '@utils/amplify-utils';
21-
import { TemplateDto } from 'nhs-notify-backend-client';
21+
import { TemplateDto, TemplateStatus } from 'nhs-notify-backend-client';
2222
import { templateApiClient } from 'nhs-notify-backend-client/src/template-api-client';
2323
import { routingConfigurationApiClient } from 'nhs-notify-backend-client/src/routing-config-api-client';
2424
import { randomUUID } from 'node:crypto';
@@ -527,6 +527,37 @@ describe('form-actions', () => {
527527
expect(actualOrder).toEqual(expectedOrder);
528528
});
529529

530+
test('getTemplates - invalid templates are not listed', async () => {
531+
const validTemplate: TemplateDto = {
532+
templateType: 'SMS',
533+
templateStatus: 'SUBMITTED',
534+
name: 'Template',
535+
message: 'Message',
536+
createdAt: '2020-01-01T00:00:00.000Z',
537+
id: '02',
538+
updatedAt: '2021-01-01T00:00:00.000Z',
539+
};
540+
541+
mockedTemplateClient.listTemplates.mockResolvedValueOnce({
542+
data: [
543+
{
544+
templateType: 'SMS',
545+
templateStatus: undefined as unknown as TemplateStatus,
546+
name: 'Template',
547+
message: 'Message',
548+
createdAt: '2020-01-01T00:00:00.000Z',
549+
id: '01',
550+
updatedAt: '2021-01-01T00:00:00.000Z',
551+
},
552+
validTemplate,
553+
],
554+
});
555+
556+
const response = await getTemplates();
557+
558+
expect(response).toEqual([validTemplate]);
559+
});
560+
530561
describe('setTemplateToSubmitted', () => {
531562
test('submitTemplate successfully', async () => {
532563
const responseData = {

frontend/src/__tests__/utils/message-plans.test.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -251,17 +251,13 @@ describe('Message plans actions', () => {
251251
const completedCount = await countRoutingConfigs('COMPLETED');
252252

253253
expect(draftCount).toEqual(1);
254-
expect(routingConfigApiMock.count).toHaveBeenNthCalledWith(
255-
1,
256-
'token',
257-
'DRAFT'
258-
);
254+
expect(routingConfigApiMock.count).toHaveBeenNthCalledWith(1, 'token', {
255+
status: 'DRAFT',
256+
});
259257
expect(completedCount).toEqual(5);
260-
expect(routingConfigApiMock.count).toHaveBeenNthCalledWith(
261-
2,
262-
'token',
263-
'COMPLETED'
264-
);
258+
expect(routingConfigApiMock.count).toHaveBeenNthCalledWith(2, 'token', {
259+
status: 'COMPLETED',
260+
});
265261
});
266262
});
267263

frontend/src/app/copy-template/[templateId]/page.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22

33
import { redirect, RedirectType } from 'next/navigation';
44
import { CopyTemplate } from '@forms/CopyTemplate/CopyTemplate';
5-
import { TemplatePageProps } from 'nhs-notify-web-template-management-utils';
5+
import {
6+
TemplatePageProps,
7+
validateTemplate,
8+
} from 'nhs-notify-web-template-management-utils';
69
import { getTemplate } from '@utils/form-actions';
7-
import { isTemplateDtoValid } from 'nhs-notify-backend-client';
810

911
const CopyTemplatePage = async (props: TemplatePageProps) => {
1012
const { templateId } = await props.params;
1113

1214
const template = await getTemplate(templateId);
1315

14-
const validatedTemplate = isTemplateDtoValid(template);
16+
const validatedTemplate = validateTemplate(template);
1517

1618
if (!validatedTemplate) {
1719
return redirect('/invalid-template', RedirectType.replace);

frontend/src/components/forms/CopyTemplate/CopyTemplate.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ import {
1010
} from 'nhs-notify-web-template-management-utils';
1111
import { NHSNotifyMain } from '@atoms/NHSNotifyMain/NHSNotifyMain';
1212
import { $CopyTemplate, copyTemplateAction } from './server-action';
13-
import { TemplateType, ValidatedTemplateDto } from 'nhs-notify-backend-client';
13+
import { TemplateDto, TemplateType } from 'nhs-notify-backend-client';
1414
import { validate } from '@utils/client-validate-form';
1515
import Link from 'next/link';
1616
import NotifyBackLink from '@atoms/NHSNotifyBackLink/NHSNotifyBackLink';
1717

1818
export type ValidCopyType = Exclude<TemplateType, 'LETTER'>;
1919

2020
type CopyTemplate = {
21-
template: ValidatedTemplateDto & { templateType: ValidCopyType };
21+
template: TemplateDto & { templateType: ValidCopyType };
2222
};
2323

2424
export const CopyTemplate = ({ template }: CopyTemplate) => {

frontend/src/components/forms/CopyTemplate/server-action.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { createTemplate } from '@utils/form-actions';
55
import { format } from 'date-fns/format';
66
import {
77
TEMPLATE_TYPE_LIST,
8+
TemplateDto,
89
TemplateType,
9-
ValidatedTemplateDto,
1010
} from 'nhs-notify-backend-client';
1111
import content from '@content/content';
1212

@@ -17,7 +17,7 @@ export const $CopyTemplate = z.object({
1717
});
1818

1919
type CopyTemplateActionState = FormState & {
20-
template: ValidatedTemplateDto & {
20+
template: TemplateDto & {
2121
templateType: Exclude<TemplateType, 'LETTER'>;
2222
};
2323
};

frontend/src/utils/form-actions.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
import { getSessionServer } from '@utils/amplify-utils';
44
import {
5+
$TemplateDto,
56
CreateUpdateTemplate,
6-
isTemplateDtoValid,
77
RoutingConfig,
88
TemplateDto,
9-
ValidatedTemplateDto,
109
} from 'nhs-notify-backend-client';
1110
import { logger } from 'nhs-notify-web-template-management-utils/logger';
1211
import { templateApiClient } from 'nhs-notify-backend-client/src/template-api-client';
@@ -182,13 +181,17 @@ export async function getTemplates(): Promise<TemplateDto[]> {
182181
return [];
183182
}
184183

185-
const sortedData = data
186-
.map((template) => isTemplateDtoValid(template))
187-
.filter(
188-
(template): template is ValidatedTemplateDto => template !== undefined
189-
);
184+
const valid = data.filter((d) => {
185+
const { error: validationError, success } = $TemplateDto.safeParse(d);
190186

191-
return sortAscByUpdatedAt(sortedData);
187+
if (!success) {
188+
logger.error('Listed invalid template', validationError);
189+
}
190+
191+
return success;
192+
});
193+
194+
return sortAscByUpdatedAt(valid);
192195
}
193196

194197
export async function createRoutingConfig(

frontend/src/utils/message-plans.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export async function countRoutingConfigs(
5252

5353
const { data, error } = await routingConfigurationApiClient.count(
5454
accessToken,
55-
status
55+
{ status }
5656
);
5757

5858
if (error) {

infrastructure/terraform/modules/backend-api/spec.tmpl.json

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@
763763
],
764764
"type": "object"
765765
},
766-
"TemplateStatus": {
766+
"TemplateStatusActive": {
767767
"enum": [
768768
"DELETED",
769769
"NOT_YET_SUBMITTED",
@@ -778,6 +778,19 @@
778778
],
779779
"type": "string"
780780
},
781+
"TemplateStatus": {
782+
"anyOf": [
783+
{
784+
"$ref": "#/components/schemas/TemplateStatusActive"
785+
},
786+
{
787+
"enum": [
788+
"DELETED"
789+
],
790+
"type": "string"
791+
}
792+
]
793+
},
781794
"TemplateSuccess": {
782795
"properties": {
783796
"data": {
@@ -1853,6 +1866,40 @@
18531866
"/v1/templates": {
18541867
"get": {
18551868
"description": "List all templates",
1869+
"parameters": [
1870+
{
1871+
"description": "Filter by a single active status",
1872+
"in": "query",
1873+
"name": "templateStatus",
1874+
"schema": {
1875+
"$ref": "#/components/schemas/TemplateStatusActive"
1876+
}
1877+
},
1878+
{
1879+
"description": "Filter by a single template type",
1880+
"in": "query",
1881+
"name": "templateType",
1882+
"schema": {
1883+
"$ref": "#/components/schemas/TemplateType"
1884+
}
1885+
},
1886+
{
1887+
"description": "Filter by a single language",
1888+
"in": "query",
1889+
"name": "language",
1890+
"schema": {
1891+
"$ref": "#/components/schemas/Language"
1892+
}
1893+
},
1894+
{
1895+
"description": "Filter by a single accessible letter type",
1896+
"in": "query",
1897+
"name": "letterType",
1898+
"schema": {
1899+
"$ref": "#/components/schemas/LetterType"
1900+
}
1901+
}
1902+
],
18561903
"responses": {
18571904
"200": {
18581905
"content": {

0 commit comments

Comments
 (0)