Skip to content

Commit f8c777d

Browse files
committed
CCM-11544 Fix error handling
1 parent b0ea30c commit f8c777d

File tree

12 files changed

+129
-77
lines changed

12 files changed

+129
-77
lines changed

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

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,9 @@ describe('ChooseLanguageLetterTemplates', () => {
340340
templateList: languageLetterTemplates,
341341
cascadeIndex: 3,
342342
errorState: {
343-
formErrors: ['You have not chosen any templates'],
343+
fieldErrors: {
344+
'language-templates': ['Choose one or more templates'],
345+
},
344346
},
345347
errorType: 'missing',
346348
},
@@ -358,7 +360,7 @@ describe('ChooseLanguageLetterTemplates', () => {
358360
);
359361
expect(formErrorMessage).toHaveClass('nhsuk-error-message');
360362
expect(formErrorMessage).toHaveTextContent(
361-
'You have not chosen any templates'
363+
'Choose one or more templates'
362364
);
363365
});
364366

@@ -371,7 +373,9 @@ describe('ChooseLanguageLetterTemplates', () => {
371373
templateList: languageLetterTemplates,
372374
cascadeIndex: 3,
373375
errorState: {
374-
formErrors: ['You have not chosen any templates'],
376+
fieldErrors: {
377+
'language-templates': ['Choose one or more templates'],
378+
},
375379
},
376380
errorType: 'missing',
377381
},
@@ -394,9 +398,11 @@ describe('ChooseLanguageLetterTemplates', () => {
394398
templateList: languageLetterTemplates,
395399
cascadeIndex: 3,
396400
errorState: {
397-
formErrors: [
398-
'You can only choose one template for each language',
399-
],
401+
fieldErrors: {
402+
'language-templates': [
403+
'Choose only one template for each language',
404+
],
405+
},
400406
},
401407
errorType: 'duplicate',
402408
},
@@ -423,7 +429,7 @@ describe('ChooseLanguageLetterTemplates', () => {
423429
const errorListItem = within(errorSummary).getByRole('listitem');
424430
expect(
425431
within(errorListItem).getByText(
426-
'You can only choose one template for each language'
432+
'Choose only one template for each language'
427433
)
428434
).toBeInTheDocument();
429435
});
@@ -437,9 +443,11 @@ describe('ChooseLanguageLetterTemplates', () => {
437443
templateList: languageLetterTemplates,
438444
cascadeIndex: 3,
439445
errorState: {
440-
formErrors: [
441-
'You can only choose one template for each language',
442-
],
446+
fieldErrors: {
447+
'language-templates': [
448+
'Choose only one template for each language',
449+
],
450+
},
443451
},
444452
errorType: 'duplicate',
445453
},
@@ -457,7 +465,7 @@ describe('ChooseLanguageLetterTemplates', () => {
457465
);
458466
expect(formErrorMessage).toHaveClass('nhsuk-error-message');
459467
expect(formErrorMessage).toHaveTextContent(
460-
'You can only choose one template for each language'
468+
'Choose only one template for each language'
461469
);
462470
});
463471

@@ -470,9 +478,11 @@ describe('ChooseLanguageLetterTemplates', () => {
470478
templateList: languageLetterTemplates,
471479
cascadeIndex: 3,
472480
errorState: {
473-
formErrors: [
474-
'You can only choose one template for each language',
475-
],
481+
fieldErrors: {
482+
'language-templates': [
483+
'Choose only one template for each language',
484+
],
485+
},
476486
},
477487
errorType: 'duplicate',
478488
},

frontend/src/__tests__/components/forms/ChooseLanguageLetterTemplates/__snapshots__/ChooseLanguageLetterTemplates.test.tsx.snap

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ exports[`ChooseLanguageLetterTemplates error handling when duplicate languages a
2929
class="nhsuk-list nhsuk-error-summary__list"
3030
>
3131
<li>
32-
<span
33-
class="nhsuk-error-message"
32+
<a
33+
href="#language-templates"
3434
>
35-
You can only choose one template for each language
36-
</span>
35+
Choose only one template for each language
36+
</a>
3737
</li>
3838
</ul>
3939
</div>
@@ -102,7 +102,7 @@ exports[`ChooseLanguageLetterTemplates error handling when duplicate languages a
102102
>
103103
Error:
104104
</span>
105-
You can only choose one template for each language
105+
Choose only one template for each language
106106
</span>
107107
<div
108108
aria-describedby="language-templates--error-message"
@@ -516,11 +516,11 @@ exports[`ChooseLanguageLetterTemplates error handling when no template is select
516516
class="nhsuk-list nhsuk-error-summary__list"
517517
>
518518
<li>
519-
<span
520-
class="nhsuk-error-message"
519+
<a
520+
href="#language-templates"
521521
>
522-
You have not chosen any templates
523-
</span>
522+
Choose one or more templates
523+
</a>
524524
</li>
525525
</ul>
526526
</div>
@@ -589,7 +589,7 @@ exports[`ChooseLanguageLetterTemplates error handling when no template is select
589589
>
590590
Error:
591591
</span>
592-
You have not chosen any templates
592+
Choose one or more templates
593593
</span>
594594
<div
595595
aria-describedby="language-templates--error-message"

frontend/src/__tests__/components/forms/ChooseLanguageLetterTemplates/server-action.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,11 @@ describe('chooseLanguageLetterTemplatesAction', () => {
261261
);
262262

263263
expect(result.errorType).toBe('duplicate');
264-
expect(result.errorState?.formErrors).toHaveLength(1);
265-
expect(result.errorState?.formErrors?.[0]).toBe(
266-
'You can only choose one template for each language'
264+
expect(result.errorState?.fieldErrors?.['language-templates']).toHaveLength(
265+
1
266+
);
267+
expect(result.errorState?.fieldErrors?.['language-templates']?.[0]).toBe(
268+
'Choose only one template for each language'
267269
);
268270
});
269271

frontend/src/__tests__/components/molecules/LanguageLetterTemplates.test.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,11 @@ describe('LanguageLetterTemplates', () => {
9797
GERMAN_LETTER_TEMPLATE,
9898
]}
9999
errorState={{
100-
fieldErrors: {},
101-
formErrors: ['Please select at least one language template'],
100+
fieldErrors: {
101+
'language-templates': [
102+
'Please select at least one language template',
103+
],
104+
},
102105
}}
103106
selectedTemplates={[]}
104107
routingConfigId='routing-config-id'
@@ -122,8 +125,11 @@ describe('LanguageLetterTemplates', () => {
122125
GERMAN_LETTER_TEMPLATE,
123126
]}
124127
errorState={{
125-
fieldErrors: {},
126-
formErrors: ['Choose only one template for each language'],
128+
fieldErrors: {
129+
'language-templates': [
130+
'Choose only one template for each language',
131+
],
132+
},
127133
}}
128134
selectedTemplates={[]}
129135
routingConfigId='routing-config-id'

frontend/src/components/atoms/NHSNotifyButton/NHSNotifyButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export function NHSNotifyButton({
1010
return (
1111
<Button
1212
preventDoubleClick
13-
debounceTimeout={10_000}
13+
debounceTimeout={5000}
1414
onClick={() => {}}
1515
href={href}
1616
{...rest}

frontend/src/components/forms/ChooseLanguageLetterTemplates/ChooseLanguageLetterTemplates.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export function ChooseLanguageLetterTemplates(
4747
);
4848

4949
const formValidate = validate(
50-
$ChooseLanguageLetterTemplates(content.error.missing.hintText),
50+
$ChooseLanguageLetterTemplates(content.error.missing.linkText),
5151
setErrorState
5252
);
5353

@@ -56,20 +56,24 @@ export function ChooseLanguageLetterTemplates(
5656
const selectedLanguageTemplateIds =
5757
getSelectedLanguageTemplateIds(cascadeItem);
5858

59-
const errorHintText =
60-
state.errorType === 'duplicate'
61-
? content.error.duplicate.hintText
62-
: content.error.missing.hintText;
63-
6459
const initialSelectedTemplates =
6560
state.selectedTemplateIds ??
6661
selectedLanguageTemplateIds.map((item) => item.templateId);
6762

63+
const errorMessage = (errorState || state.errorState)?.fieldErrors?.[
64+
'language-templates'
65+
]?.[0];
66+
const isDuplicateError = errorMessage === content.error.duplicate.linkText;
67+
68+
const errorHintText = isDuplicateError
69+
? content.error.duplicate.hintText
70+
: content.error.missing.hintText;
71+
6872
return (
6973
<NHSNotifyMain>
7074
<NhsNotifyErrorSummary
7175
hint={errorHintText}
72-
errorState={state.errorState || errorState}
76+
errorState={errorState || state.errorState}
7377
/>
7478
<div className='nhsuk-grid-row'>
7579
<div className='nhsuk-grid-column-full'>
@@ -126,7 +130,7 @@ export function ChooseLanguageLetterTemplates(
126130
<LanguageLetterTemplates
127131
routingConfigId={messagePlan.id}
128132
templateList={templateList}
129-
errorState={state.errorState || errorState || null}
133+
errorState={errorState || state.errorState || null}
130134
selectedTemplates={initialSelectedTemplates}
131135
/>
132136
) : (

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

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,19 @@ export const $ChooseLanguageLetterTemplates = (errorMessage: string) =>
2424
lockNumber: $LockNumber,
2525
})
2626
.catchall(z.string())
27-
.refine(
28-
(data) =>
29-
Object.keys(data).some(
30-
(key) => key.startsWith('template_') && data[key]
31-
),
32-
{
33-
message: errorMessage,
27+
.superRefine((data, ctx) => {
28+
const hasTemplates = Object.keys(data).some(
29+
(key) => key.startsWith('template_') && data[key]
30+
);
31+
32+
if (!hasTemplates) {
33+
ctx.addIssue({
34+
code: 'custom',
35+
message: errorMessage,
36+
path: ['language-templates'],
37+
});
3438
}
35-
);
39+
});
3640

3741
export async function chooseLanguageLetterTemplatesAction(
3842
formState: ChooseLanguageLetterTemplatesFormState,
@@ -41,12 +45,14 @@ export async function chooseLanguageLetterTemplatesAction(
4145
const { messagePlan, cascadeIndex, templateList } = formState;
4246

4347
const parsedForm = $ChooseLanguageLetterTemplates(
44-
content.error.missing.hintText
48+
content.error.missing.linkText
4549
).safeParse(Object.fromEntries(formData.entries()));
4650

4751
if (!parsedForm.success) {
4852
return {
4953
...formState,
54+
selectedTemplateIds: [],
55+
errorType: 'missing',
5056
errorState: z.flattenError(parsedForm.error) as FormState['errorState'],
5157
};
5258
}
@@ -74,7 +80,9 @@ export async function chooseLanguageLetterTemplatesAction(
7480
selectedTemplateIds,
7581
errorType: 'duplicate',
7682
errorState: {
77-
formErrors: [content.error.duplicate.hintText],
83+
fieldErrors: {
84+
'language-templates': [content.error.duplicate.linkText],
85+
},
7886
},
7987
};
8088
}

frontend/src/components/molecules/ChannelTemplates/ChannelTemplates.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export function ChannelTemplates({
3939
{tableHintText}
4040
</HintText>
4141
<Radios
42-
id={'channelTemplate'}
42+
id='channelTemplate'
4343
error={errorState?.fieldErrors?.['channelTemplate']?.join(', ')}
4444
errorProps={{ id: 'channelTemplate--error-message' }}
4545
>

frontend/src/components/molecules/LanguageLetterTemplates/LanguageLetterTemplates.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ export function LanguageLetterTemplates({
3434
</HintText>
3535
<Checkboxes
3636
id='language-templates'
37-
error={errorState?.formErrors?.[0] || ''}
37+
error={
38+
errorState?.fieldErrors?.['language-templates']?.join(', ') || ''
39+
}
3840
errorProps={{ id: 'language-templates--error-message' }}
3941
>
4042
<Table

frontend/src/utils/client-validate-form.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ export const validate = (
1414

1515
const validationResult = $schema.safeParse(data);
1616

17-
if (!validationResult.success) {
17+
if (validationResult.success) {
18+
cb({});
19+
} else {
1820
event.preventDefault();
1921

2022
const error = validationResult.error.flatten();

0 commit comments

Comments
 (0)