Skip to content

Commit a086307

Browse files
authored
Updates to Fix Issues from Improved Forms Engine Plugin Package (#1109)
* Updates to resolve type issues (when forms-engine-plugin package has relative paths, making types better resolvable)
1 parent 763f57c commit a086307

18 files changed

Lines changed: 172 additions & 102 deletions

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"license": "SEE LICENSE IN LICENSE",
4747
"dependencies": {
4848
"@aws-sdk/client-sns": "^3.997.0",
49-
"@defra/forms-engine-plugin": "^4.7.2",
49+
"@defra/forms-engine-plugin": "^4.7.3",
5050
"@defra/forms-model": "^3.0.647",
5151
"@defra/hapi-tracing": "^1.30.0",
5252
"@elastic/ecs-pino-format": "^1.5.0",

src/server/index.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ describe('Model cache', () => {
494494
const mockYar = {
495495
flash: mockFlash
496496
}
497-
const mockRequest = /** @type {any} */ {
497+
const mockRequest = {
498498
params: {
499499
slug: 'test-form'
500500
},
@@ -511,6 +511,7 @@ describe('Model cache', () => {
511511
expect(pluginObject).toBeDefined()
512512
const saveAndExitFunc = pluginObject.options.saveAndExit
513513
expect(saveAndExitFunc).toBeDefined()
514+
// @ts-expect-error - partial mock objects for tests
514515
saveAndExitFunc(mockRequest, mockH, undefined)
515516
expect(mockFlash).toHaveBeenCalledWith(
516517
'SAVE_AND_EXIT_PAYLOAD',

src/server/messaging/formAdapterEventPublisher.test.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { PublishCommand } from '@aws-sdk/client-sns'
2+
import { FormStatus } from '@defra/forms-model'
23

34
import { publishFormAdapterEvent } from '~/src/server/messaging/formAdapterEventPublisher.js'
45
import { getSNSClient } from '~/src/server/messaging/sns.js'
@@ -33,7 +34,7 @@ const basePayload = {
3334
formSlug: 'test-form',
3435
formName: 'Test Form',
3536
referenceNumber: 'REF-123456',
36-
status: 'live',
37+
status: FormStatus.Live,
3738
isPreview: false,
3839
notificationEmail: 'test@example.com'
3940
},
@@ -54,7 +55,7 @@ describe('formAdapterEventPublisher', () => {
5455
/** @type {FormAdapterSubmissionMessagePayload} */
5556
let mockPayload
5657

57-
/** @type {any} */
58+
/** @type {{ send: jest.Mock }} */
5859
let mockSnsClient
5960

6061
beforeEach(() => {
@@ -65,10 +66,14 @@ describe('formAdapterEventPublisher', () => {
6566
meta: { ...basePayload.meta }
6667
})
6768

68-
mockSnsClient = {
69-
send: jest.fn()
70-
}
71-
jest.mocked(getSNSClient).mockReturnValue(mockSnsClient)
69+
mockSnsClient = { send: jest.fn() }
70+
jest
71+
.mocked(getSNSClient)
72+
.mockReturnValue(
73+
/** @type {import('@aws-sdk/client-sns').SNSClient} */ (
74+
/** @type {unknown} */ (mockSnsClient)
75+
)
76+
)
7277
})
7378

7479
describe('publishFormAdapterEvent', () => {
@@ -123,7 +128,7 @@ describe('formAdapterEventPublisher', () => {
123128
formSlug: 'complex-form',
124129
formName: 'Complex Form',
125130
referenceNumber: 'COMPLEX-REF',
126-
status: 'live',
131+
status: FormStatus.Live,
127132
isPreview: false,
128133
notificationEmail: 'complex@example.com'
129134
},
@@ -263,12 +268,18 @@ describe('per-form topic routing (SNS_FORM_TOPIC_ARN_MAP)', () => {
263268
meta: { ...basePayload.meta, formId: mappedFormId }
264269
}
265270

266-
/** @type {any} */
271+
/** @type {{ send: jest.Mock }} */
267272
let mockSnsClient
268273

269274
beforeEach(() => {
270275
mockSnsClient = { send: jest.fn() }
271-
jest.mocked(getSNSClient).mockReturnValue(mockSnsClient)
276+
jest
277+
.mocked(getSNSClient)
278+
.mockReturnValue(
279+
/** @type {import('@aws-sdk/client-sns').SNSClient} */ (
280+
/** @type {unknown} */ (mockSnsClient)
281+
)
282+
)
272283
})
273284

274285
it('publishes to form-specific topic in addition to global topic when formId is mapped', async () => {

src/server/messaging/formAdapterEventPublisher.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const snsFormTopicArnMap: Record<string, string> = snsFormTopicArnMapRaw
1717
* Validate form adapter submission payload against schema
1818
* @param submissionPayload - Form submission payload to validate
1919
* @returns Validated payload
20-
* @throws Error if validation fails
20+
* @throws {Error} if validation fails
2121
*/
2222
function validateFormAdapterPayload(
2323
submissionPayload: FormAdapterSubmissionMessagePayload
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { type FormPageViewModel } from '@defra/forms-engine-plugin/types'
2+
3+
/**
4+
* Extends {@link FormPageViewModel} with template variables specific to the feedback page.
5+
*/
6+
export interface FeedbackPageViewModel extends FormPageViewModel {
7+
hidePhaseBanner?: boolean
8+
submitButtonText: string
9+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { type SummaryViewModel } from '@defra/forms-engine-plugin/engine/models/SummaryViewModel.js'
2+
import { type GovukField } from '@defra/forms-model'
3+
4+
/**
5+
* Extends {@link SummaryViewModel} with an optional confirmation email field
6+
* rendered on the summary page when the user opts in to receive a confirmation email.
7+
*/
8+
export interface SummaryViewModelWithEmail extends SummaryViewModel {
9+
userConfirmationEmailField?: GovukField
10+
}

src/server/plugins/FeedbackPageController.test.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ describe('FeedbackPageController', () => {
2121
const response = {
2222
code: jest.fn().mockImplementation(() => response)
2323
}
24-
const h: FormResponseToolkit = {
24+
const h = {
2525
redirect: jest.fn().mockReturnValue(response),
26-
view: jest.fn()
27-
}
26+
view: jest.fn(),
27+
continue: Symbol('continue')
28+
} as unknown as FormResponseToolkit
2829

2930
beforeEach(() => {
3031
model = new FormModel(definition, {
@@ -70,11 +71,12 @@ describe('FeedbackPageController', () => {
7071
errors: [
7172
{
7273
name: 'PMPyjg',
73-
path: '/feedback',
74-
text: 'Select how you feel about this service'
74+
path: ['feedback'],
75+
text: 'Select how you feel about this service',
76+
href: '#PMPyjg'
7577
}
7678
]
77-
} as FormContext
79+
} as unknown as FormContext
7880

7981
jest
8082
.spyOn(controller as unknown as QuestionPageController, 'getState')

src/server/plugins/FeedbackPageController.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,25 @@ import {
66
type FormContextRequest
77
} from '@defra/forms-engine-plugin/engine/types.js'
88
import {
9-
type FormPageViewModel,
109
type FormRequestPayload,
1110
type FormResponseToolkit
1211
} from '@defra/forms-engine-plugin/types'
1312

13+
import { type FeedbackPageViewModel } from '~/src/server/models/FeedbackPageViewModel.js'
14+
1415
export class FeedbackPageController extends QuestionPageController {
1516
allowSaveAndExit = false
1617

1718
getViewModel(
1819
request: FormContextRequest,
1920
context: FormContext
20-
): FormPageViewModel {
21+
): FeedbackPageViewModel {
2122
const viewModel = super.getViewModel(request, context)
2223
return {
2324
...viewModel,
2425
hidePhaseBanner: true,
2526
submitButtonText: 'Send feedback',
26-
name: context.state.formName
27+
name: context.state.formName as string | undefined
2728
}
2829
}
2930

@@ -63,10 +64,11 @@ export class FeedbackPageController extends QuestionPageController {
6364
// Save state
6465
await this.setState(request, state)
6566

66-
const summary = new SummaryPageController(
67-
model,
68-
context.pageMap.get(context.paths[0])
69-
)
67+
const pageController = context.pageMap.get(context.paths[0])
68+
if (!pageController) {
69+
throw new Error('Summary page controller not found')
70+
}
71+
const summary = new SummaryPageController(model, pageController.pageDef)
7072
return summary.handleFormSubmit(request, context, h)
7173
}
7274
}

src/server/plugins/SummaryPageWithConfirmationEmailController.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@ describe('SummaryPageWithConfirmationEmailController', () => {
2727
const response = {
2828
code: jest.fn().mockImplementation(() => response)
2929
}
30-
const h: FormResponseToolkit = {
30+
const h = {
3131
redirect: jest.fn().mockReturnValue(response),
32-
view: jest.fn()
33-
}
32+
view: jest.fn(),
33+
continue: Symbol('continue')
34+
} as unknown as FormResponseToolkit
3435

3536
beforeEach(() => {
3637
model = new FormModel(definition, {

0 commit comments

Comments
 (0)