@defra/forms-engine-plugin 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/src/client/javascripts/application.js +87 -0
- package/src/client/javascripts/file-upload.js +386 -0
- package/src/client/stylesheets/_code.scss +33 -0
- package/src/client/stylesheets/_govuk-frontend.scss +4 -0
- package/src/client/stylesheets/_prose.scss +56 -0
- package/src/client/stylesheets/_service-banner.scss +24 -0
- package/src/client/stylesheets/_summary-list.scss +28 -0
- package/src/client/stylesheets/_tag-env.scss +24 -0
- package/src/client/stylesheets/application.scss +14 -0
- package/src/common/cookies.js +58 -0
- package/src/common/cookies.test.js +23 -0
- package/src/common/types.js +5 -0
- package/src/config/index.ts +271 -0
- package/src/index.ts +31 -0
- package/src/server/common/helpers/logging/logger-options.test.ts +50 -0
- package/src/server/common/helpers/logging/logger-options.ts +46 -0
- package/src/server/common/helpers/logging/logger.ts +7 -0
- package/src/server/common/helpers/logging/request-logger.ts +9 -0
- package/src/server/common/helpers/logging/request-tracing.js +10 -0
- package/src/server/common/helpers/redis-client.js +70 -0
- package/src/server/constants.js +1 -0
- package/src/server/forms/README.md +10 -0
- package/src/server/forms/components.json +1015 -0
- package/src/server/forms/report-a-terrorist.json +270 -0
- package/src/server/forms/runner-components-test.json +365 -0
- package/src/server/forms/test.json +581 -0
- package/src/server/index.test.ts +582 -0
- package/src/server/index.ts +140 -0
- package/src/server/plugins/blankie.test.ts +73 -0
- package/src/server/plugins/blankie.ts +48 -0
- package/src/server/plugins/crumb.ts +20 -0
- package/src/server/plugins/engine/README.md +87 -0
- package/src/server/plugins/engine/components/AutocompleteField.test.ts +294 -0
- package/src/server/plugins/engine/components/AutocompleteField.ts +49 -0
- package/src/server/plugins/engine/components/CheckboxesField.test.ts +379 -0
- package/src/server/plugins/engine/components/CheckboxesField.ts +106 -0
- package/src/server/plugins/engine/components/ComponentBase.ts +97 -0
- package/src/server/plugins/engine/components/ComponentCollection.ts +278 -0
- package/src/server/plugins/engine/components/DatePartsField.test.ts +822 -0
- package/src/server/plugins/engine/components/DatePartsField.ts +264 -0
- package/src/server/plugins/engine/components/Details.test.ts +49 -0
- package/src/server/plugins/engine/components/Details.ts +30 -0
- package/src/server/plugins/engine/components/EmailAddressField.test.ts +395 -0
- package/src/server/plugins/engine/components/EmailAddressField.ts +55 -0
- package/src/server/plugins/engine/components/FileUploadField.test.ts +778 -0
- package/src/server/plugins/engine/components/FileUploadField.ts +262 -0
- package/src/server/plugins/engine/components/FormComponent.ts +249 -0
- package/src/server/plugins/engine/components/Html.test.ts +48 -0
- package/src/server/plugins/engine/components/Html.ts +29 -0
- package/src/server/plugins/engine/components/InsetText.test.ts +48 -0
- package/src/server/plugins/engine/components/InsetText.ts +27 -0
- package/src/server/plugins/engine/components/List.test.ts +76 -0
- package/src/server/plugins/engine/components/List.ts +72 -0
- package/src/server/plugins/engine/components/ListFormComponent.ts +140 -0
- package/src/server/plugins/engine/components/MonthYearField.test.ts +567 -0
- package/src/server/plugins/engine/components/MonthYearField.ts +222 -0
- package/src/server/plugins/engine/components/MultilineTextField.test.ts +558 -0
- package/src/server/plugins/engine/components/MultilineTextField.ts +138 -0
- package/src/server/plugins/engine/components/NumberField.test.ts +701 -0
- package/src/server/plugins/engine/components/NumberField.ts +163 -0
- package/src/server/plugins/engine/components/RadiosField.test.ts +288 -0
- package/src/server/plugins/engine/components/RadiosField.ts +24 -0
- package/src/server/plugins/engine/components/SelectField.test.ts +288 -0
- package/src/server/plugins/engine/components/SelectField.ts +47 -0
- package/src/server/plugins/engine/components/SelectionControlField.ts +43 -0
- package/src/server/plugins/engine/components/TelephoneNumberField.test.ts +356 -0
- package/src/server/plugins/engine/components/TelephoneNumberField.ts +67 -0
- package/src/server/plugins/engine/components/TextField.test.ts +489 -0
- package/src/server/plugins/engine/components/TextField.ts +96 -0
- package/src/server/plugins/engine/components/UkAddressField.test.ts +623 -0
- package/src/server/plugins/engine/components/UkAddressField.ts +172 -0
- package/src/server/plugins/engine/components/YesNoField.test.ts +248 -0
- package/src/server/plugins/engine/components/YesNoField.ts +31 -0
- package/src/server/plugins/engine/components/constants.ts +1 -0
- package/src/server/plugins/engine/components/helpers.ts +330 -0
- package/src/server/plugins/engine/components/index.ts +24 -0
- package/src/server/plugins/engine/components/types.ts +117 -0
- package/src/server/plugins/engine/configureEnginePlugin.ts +47 -0
- package/src/server/plugins/engine/helpers.test.ts +791 -0
- package/src/server/plugins/engine/helpers.ts +379 -0
- package/src/server/plugins/engine/index.ts +7 -0
- package/src/server/plugins/engine/models/FormModel.test.ts +42 -0
- package/src/server/plugins/engine/models/FormModel.ts +443 -0
- package/src/server/plugins/engine/models/RepeatingSummaryViewModel.ts +0 -0
- package/src/server/plugins/engine/models/Section.ts +0 -0
- package/src/server/plugins/engine/models/SummaryViewModel.test.ts +209 -0
- package/src/server/plugins/engine/models/SummaryViewModel.ts +220 -0
- package/src/server/plugins/engine/models/index.ts +2 -0
- package/src/server/plugins/engine/models/types.ts +114 -0
- package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +143 -0
- package/src/server/plugins/engine/outputFormatters/human/v1.ts +73 -0
- package/src/server/plugins/engine/outputFormatters/index.test.ts +17 -0
- package/src/server/plugins/engine/outputFormatters/index.ts +44 -0
- package/src/server/plugins/engine/outputFormatters/machine/v1.test.ts +229 -0
- package/src/server/plugins/engine/outputFormatters/machine/v1.ts +140 -0
- package/src/server/plugins/engine/outputFormatters/machine/v2.test.ts +229 -0
- package/src/server/plugins/engine/outputFormatters/machine/v2.ts +153 -0
- package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +1108 -0
- package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +446 -0
- package/src/server/plugins/engine/pageControllers/PageController.test.ts +205 -0
- package/src/server/plugins/engine/pageControllers/PageController.ts +176 -0
- package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +1264 -0
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +561 -0
- package/src/server/plugins/engine/pageControllers/README.md +28 -0
- package/src/server/plugins/engine/pageControllers/RepeatPageController.test.ts +264 -0
- package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +458 -0
- package/src/server/plugins/engine/pageControllers/StartPageController.ts +18 -0
- package/src/server/plugins/engine/pageControllers/StatusPageController.ts +50 -0
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +261 -0
- package/src/server/plugins/engine/pageControllers/TerminalController.test.ts +28 -0
- package/src/server/plugins/engine/pageControllers/TerminalPageController.ts +19 -0
- package/src/server/plugins/engine/pageControllers/helpers.test.ts +198 -0
- package/src/server/plugins/engine/pageControllers/helpers.ts +101 -0
- package/src/server/plugins/engine/pageControllers/index.ts +10 -0
- package/src/server/plugins/engine/pageControllers/validationOptions.ts +89 -0
- package/src/server/plugins/engine/plugin.ts +673 -0
- package/src/server/plugins/engine/services/formSubmissionService.js +46 -0
- package/src/server/plugins/engine/services/formsService.js +46 -0
- package/src/server/plugins/engine/services/formsService.test.js +90 -0
- package/src/server/plugins/engine/services/index.js +3 -0
- package/src/server/plugins/engine/services/notifyService.test.ts +132 -0
- package/src/server/plugins/engine/services/notifyService.ts +64 -0
- package/src/server/plugins/engine/services/uploadService.js +60 -0
- package/src/server/plugins/engine/types.ts +315 -0
- package/src/server/plugins/engine/views/components/autocompletefield.html +5 -0
- package/src/server/plugins/engine/views/components/checkboxesfield.html +5 -0
- package/src/server/plugins/engine/views/components/datepartsfield.html +5 -0
- package/src/server/plugins/engine/views/components/details.html +6 -0
- package/src/server/plugins/engine/views/components/emailaddressfield.html +5 -0
- package/src/server/plugins/engine/views/components/fileuploadfield-key.html +8 -0
- package/src/server/plugins/engine/views/components/fileuploadfield-value.html +3 -0
- package/src/server/plugins/engine/views/components/fileuploadfield.html +24 -0
- package/src/server/plugins/engine/views/components/html.html +3 -0
- package/src/server/plugins/engine/views/components/insettext.html +7 -0
- package/src/server/plugins/engine/views/components/list.html +36 -0
- package/src/server/plugins/engine/views/components/monthyearfield.html +5 -0
- package/src/server/plugins/engine/views/components/multilinetextfield.html +10 -0
- package/src/server/plugins/engine/views/components/numberfield.html +5 -0
- package/src/server/plugins/engine/views/components/radiosfield.html +5 -0
- package/src/server/plugins/engine/views/components/selectfield.html +5 -0
- package/src/server/plugins/engine/views/components/telephonenumberfield.html +5 -0
- package/src/server/plugins/engine/views/components/textfield.html +5 -0
- package/src/server/plugins/engine/views/components/ukaddressfield.html +25 -0
- package/src/server/plugins/engine/views/components/yesnofield.html +5 -0
- package/src/server/plugins/engine/views/file-upload.html +45 -0
- package/src/server/plugins/engine/views/index.html +39 -0
- package/src/server/plugins/engine/views/item-delete.html +56 -0
- package/src/server/plugins/engine/views/partials/components.html +6 -0
- package/src/server/plugins/engine/views/partials/conditional-components.html +3 -0
- package/src/server/plugins/engine/views/partials/debug.html +44 -0
- package/src/server/plugins/engine/views/partials/form.html +15 -0
- package/src/server/plugins/engine/views/partials/heading.html +16 -0
- package/src/server/plugins/engine/views/partials/preview-banner.html +32 -0
- package/src/server/plugins/engine/views/partials/preview-banner.test.js +122 -0
- package/src/server/plugins/engine/views/partials/warn-missing-notification-email.html +10 -0
- package/src/server/plugins/engine/views/repeat-list-summary.html +53 -0
- package/src/server/plugins/errorPages.ts +58 -0
- package/src/server/plugins/nunjucks/context.js +88 -0
- package/src/server/plugins/nunjucks/context.test.js +142 -0
- package/src/server/plugins/nunjucks/enviroment.test.js +201 -0
- package/src/server/plugins/nunjucks/environment.js +116 -0
- package/src/server/plugins/nunjucks/filters/answer.js +27 -0
- package/src/server/plugins/nunjucks/filters/answer.test.js +89 -0
- package/src/server/plugins/nunjucks/filters/evaluate.js +21 -0
- package/src/server/plugins/nunjucks/filters/field.js +28 -0
- package/src/server/plugins/nunjucks/filters/field.test.js +75 -0
- package/src/server/plugins/nunjucks/filters/highlight.js +11 -0
- package/src/server/plugins/nunjucks/filters/href.js +30 -0
- package/src/server/plugins/nunjucks/filters/href.test.js +80 -0
- package/src/server/plugins/nunjucks/filters/index.js +8 -0
- package/src/server/plugins/nunjucks/filters/inspect.js +15 -0
- package/src/server/plugins/nunjucks/filters/page.js +24 -0
- package/src/server/plugins/nunjucks/filters/page.test.js +65 -0
- package/src/server/plugins/nunjucks/index.js +3 -0
- package/src/server/plugins/nunjucks/plugin.js +40 -0
- package/src/server/plugins/nunjucks/render.js +42 -0
- package/src/server/plugins/nunjucks/types.js +40 -0
- package/src/server/plugins/pulse.ts +11 -0
- package/src/server/plugins/router.ts +201 -0
- package/src/server/plugins/session.ts +28 -0
- package/src/server/routes/health.js +13 -0
- package/src/server/routes/health.test.js +35 -0
- package/src/server/routes/index.test.ts +125 -0
- package/src/server/routes/index.ts +2 -0
- package/src/server/routes/public.ts +47 -0
- package/src/server/routes/types.ts +48 -0
- package/src/server/schemas/index.ts +34 -0
- package/src/server/secure-context.js +43 -0
- package/src/server/services/cacheService.test.ts +276 -0
- package/src/server/services/cacheService.ts +131 -0
- package/src/server/services/httpService.test.js +491 -0
- package/src/server/services/httpService.ts +50 -0
- package/src/server/services/index.ts +1 -0
- package/src/server/types.ts +54 -0
- package/src/server/utils/notify.test.ts +37 -0
- package/src/server/utils/notify.ts +50 -0
- package/src/server/utils/secure-context/get-trust-store-certs.js +11 -0
- package/src/server/utils/secure-context/get-trust-store-certs.test.js +19 -0
- package/src/server/utils/utils.js +24 -0
- package/src/server/utils/utils.test.js +54 -0
- package/src/server/views/404.html +16 -0
- package/src/server/views/500.html +19 -0
- package/src/server/views/components/debug/macro.njk +3 -0
- package/src/server/views/components/debug/template.njk +13 -0
- package/src/server/views/components/service-banner/macro.njk +3 -0
- package/src/server/views/components/service-banner/template.njk +20 -0
- package/src/server/views/components/service-banner/template.test.js +43 -0
- package/src/server/views/components/tag-env/macro.njk +3 -0
- package/src/server/views/components/tag-env/template.njk +30 -0
- package/src/server/views/components/tag-env/template.test.js +66 -0
- package/src/server/views/confirmation.html +19 -0
- package/src/server/views/help/accessibility-statement.html +58 -0
- package/src/server/views/help/cookie-preferences.html +57 -0
- package/src/server/views/help/cookies.html +71 -0
- package/src/server/views/help/get-support.html +37 -0
- package/src/server/views/help/privacy-notice.html +68 -0
- package/src/server/views/help/terms-and-conditions.html +83 -0
- package/src/server/views/layout.html +199 -0
- package/src/server/views/summary.html +50 -0
- package/src/typings/hapi/index.d.ts +95 -0
- package/src/typings/hapi-tracing/index.d.ts +6 -0
- package/src/typings/index.d.ts +3 -0
- package/src/typings/joi/index.d.ts +22 -0
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
import { type Server } from '@hapi/hapi'
|
|
2
|
+
import { StatusCodes } from 'http-status-codes'
|
|
3
|
+
|
|
4
|
+
import { createServer } from '~/src/server/index.js'
|
|
5
|
+
import {
|
|
6
|
+
getFormDefinition,
|
|
7
|
+
getFormMetadata
|
|
8
|
+
} from '~/src/server/plugins/engine/services/formsService.js'
|
|
9
|
+
import { getUploadStatus } from '~/src/server/plugins/engine/services/uploadService.js'
|
|
10
|
+
import {
|
|
11
|
+
FileStatus,
|
|
12
|
+
UploadStatus,
|
|
13
|
+
type UploadStatusResponse
|
|
14
|
+
} from '~/src/server/plugins/engine/types.js'
|
|
15
|
+
import { FormStatus } from '~/src/server/routes/types.js'
|
|
16
|
+
import * as fixtures from '~/test/fixtures/index.js'
|
|
17
|
+
|
|
18
|
+
jest.mock('~/src/server/plugins/engine/services/formsService.js')
|
|
19
|
+
jest.mock('~/src/server/plugins/engine/services/uploadService.js')
|
|
20
|
+
|
|
21
|
+
describe('Model cache', () => {
|
|
22
|
+
let server: Server
|
|
23
|
+
|
|
24
|
+
const getCacheSize = () => {
|
|
25
|
+
return server.app.models.size
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const getCacheItem = (key: string) => {
|
|
29
|
+
return server.app.models.get(key)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
beforeAll(async () => {
|
|
33
|
+
server = await createServer()
|
|
34
|
+
await server.initialize()
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
jest.mocked(getFormMetadata).mockResolvedValue(fixtures.form.metadata)
|
|
39
|
+
server.app.models.clear()
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
afterAll(async () => {
|
|
43
|
+
await server.stop()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe('Success responses', () => {
|
|
47
|
+
test('Dispatch page with the correct state returns 302', async () => {
|
|
48
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
49
|
+
...fixtures.form.metadata,
|
|
50
|
+
live: fixtures.form.state
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
jest.mocked(getFormDefinition).mockResolvedValue(fixtures.form.definition)
|
|
54
|
+
|
|
55
|
+
const options = {
|
|
56
|
+
method: 'GET',
|
|
57
|
+
url: '/slug'
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const res = await server.inject(options)
|
|
61
|
+
|
|
62
|
+
expect(res.statusCode).toBe(StatusCodes.MOVED_TEMPORARILY)
|
|
63
|
+
expect(res.headers.location).toBe('/slug/page-one')
|
|
64
|
+
expect(getCacheSize()).toBe(1)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test('Dispatch preview page with the correct live state returns 302', async () => {
|
|
68
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
69
|
+
...fixtures.form.metadata,
|
|
70
|
+
live: fixtures.form.state
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
jest.mocked(getFormDefinition).mockResolvedValue(fixtures.form.definition)
|
|
74
|
+
|
|
75
|
+
const options = {
|
|
76
|
+
method: 'GET',
|
|
77
|
+
url: '/preview/live/slug'
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const res = await server.inject(options)
|
|
81
|
+
|
|
82
|
+
expect(res.statusCode).toBe(StatusCodes.MOVED_TEMPORARILY)
|
|
83
|
+
expect(res.headers.location).toBe('/preview/live/slug/page-one')
|
|
84
|
+
expect(getCacheSize()).toBe(1)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('Dispatch preview page with the correct draft state returns 302', async () => {
|
|
88
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
89
|
+
...fixtures.form.metadata,
|
|
90
|
+
draft: fixtures.form.state
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
jest.mocked(getFormDefinition).mockResolvedValue(fixtures.form.definition)
|
|
94
|
+
|
|
95
|
+
const options = {
|
|
96
|
+
method: 'GET',
|
|
97
|
+
url: '/preview/draft/slug'
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const res = await server.inject(options)
|
|
101
|
+
|
|
102
|
+
expect(res.statusCode).toBe(StatusCodes.MOVED_TEMPORARILY)
|
|
103
|
+
expect(res.headers.location).toBe('/preview/draft/slug/page-one')
|
|
104
|
+
expect(getCacheSize()).toBe(1)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
test('Get page with the correct live state returns 200', async () => {
|
|
108
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
109
|
+
...fixtures.form.metadata,
|
|
110
|
+
live: fixtures.form.state
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
jest.mocked(getFormDefinition).mockResolvedValue(fixtures.form.definition)
|
|
114
|
+
|
|
115
|
+
const options = {
|
|
116
|
+
method: 'GET',
|
|
117
|
+
url: '/slug/page-one'
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const res = await server.inject(options)
|
|
121
|
+
|
|
122
|
+
expect(res.statusCode).toBe(StatusCodes.OK)
|
|
123
|
+
expect(getCacheSize()).toBe(1)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test('Get preview page with the correct live state returns 200', async () => {
|
|
127
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
128
|
+
...fixtures.form.metadata,
|
|
129
|
+
live: fixtures.form.state
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
jest.mocked(getFormDefinition).mockResolvedValue(fixtures.form.definition)
|
|
133
|
+
|
|
134
|
+
const options = {
|
|
135
|
+
method: 'GET',
|
|
136
|
+
url: '/preview/live/slug/page-one'
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const res = await server.inject(options)
|
|
140
|
+
|
|
141
|
+
expect(res.statusCode).toBe(StatusCodes.OK)
|
|
142
|
+
expect(getCacheSize()).toBe(1)
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
test('Get preview page with the correct draft state returns 200', async () => {
|
|
146
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
147
|
+
...fixtures.form.metadata,
|
|
148
|
+
draft: fixtures.form.state
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
jest.mocked(getFormDefinition).mockResolvedValue(fixtures.form.definition)
|
|
152
|
+
|
|
153
|
+
const options = {
|
|
154
|
+
method: 'GET',
|
|
155
|
+
url: '/preview/draft/slug/page-one'
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const res = await server.inject(options)
|
|
159
|
+
|
|
160
|
+
expect(res.statusCode).toBe(StatusCodes.OK)
|
|
161
|
+
expect(getCacheSize()).toBe(1)
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
test('Get page with the correct state returns 200', async () => {
|
|
165
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
166
|
+
...fixtures.form.metadata,
|
|
167
|
+
live: fixtures.form.state
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
jest.mocked(getFormDefinition).mockResolvedValue(fixtures.form.definition)
|
|
171
|
+
|
|
172
|
+
const options = {
|
|
173
|
+
method: 'GET',
|
|
174
|
+
url: '/slug/page-one'
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const res = await server.inject(options)
|
|
178
|
+
|
|
179
|
+
expect(res.statusCode).toBe(StatusCodes.OK)
|
|
180
|
+
expect(getCacheSize()).toBe(1)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
test('Get page with the correct state populates the cache correctly', async () => {
|
|
184
|
+
jest.mocked(getFormMetadata).mockResolvedValue({
|
|
185
|
+
...fixtures.form.metadata,
|
|
186
|
+
draft: fixtures.form.state,
|
|
187
|
+
live: fixtures.form.state
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
jest.mocked(getFormDefinition).mockResolvedValue(fixtures.form.definition)
|
|
191
|
+
|
|
192
|
+
// Populate live/live cache item
|
|
193
|
+
const options1 = {
|
|
194
|
+
method: 'GET',
|
|
195
|
+
url: '/slug/page-one'
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const res1 = await server.inject(options1)
|
|
199
|
+
|
|
200
|
+
expect(res1.statusCode).toBe(StatusCodes.OK)
|
|
201
|
+
expect(getCacheSize()).toBe(1)
|
|
202
|
+
|
|
203
|
+
// Populate live/preview cache item
|
|
204
|
+
const options2 = {
|
|
205
|
+
method: 'GET',
|
|
206
|
+
url: '/preview/live/slug/page-one'
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const res2 = await server.inject(options2)
|
|
210
|
+
|
|
211
|
+
expect(res2.statusCode).toBe(StatusCodes.OK)
|
|
212
|
+
expect(getCacheSize()).toBe(2)
|
|
213
|
+
|
|
214
|
+
// Populate draft/preview cache item
|
|
215
|
+
const options3 = {
|
|
216
|
+
method: 'GET',
|
|
217
|
+
url: '/preview/draft/slug/page-one'
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const res3 = await server.inject(options3)
|
|
221
|
+
|
|
222
|
+
expect(res3.statusCode).toBe(StatusCodes.OK)
|
|
223
|
+
expect(getCacheSize()).toBe(3)
|
|
224
|
+
|
|
225
|
+
// Execute each request again and
|
|
226
|
+
// assert the cache size is unchanged
|
|
227
|
+
await server.inject(options1)
|
|
228
|
+
await server.inject(options2)
|
|
229
|
+
await server.inject(options3)
|
|
230
|
+
|
|
231
|
+
expect(getCacheSize()).toBe(3)
|
|
232
|
+
|
|
233
|
+
// Check models cache item is regenerated on an update to the state
|
|
234
|
+
const now2 = new Date()
|
|
235
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
236
|
+
...fixtures.form.metadata,
|
|
237
|
+
draft: fixtures.form.state,
|
|
238
|
+
live: { ...fixtures.form.state, updatedAt: now2 }
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
await server.inject(options1)
|
|
242
|
+
|
|
243
|
+
// Expect `getFormDefinition` to be called as the updatedAt has moved on
|
|
244
|
+
expect(getFormDefinition).toHaveBeenLastCalledWith(
|
|
245
|
+
fixtures.form.metadata.id,
|
|
246
|
+
FormStatus.Live
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
// Assert the live/live cache item has the correct updatedAt timestamp
|
|
250
|
+
expect(
|
|
251
|
+
getCacheItem(`${fixtures.form.metadata.id}_live_false`)?.updatedAt
|
|
252
|
+
).toBe(now2)
|
|
253
|
+
|
|
254
|
+
// Expect the cache size to remain unchanged
|
|
255
|
+
expect(getCacheSize()).toBe(3)
|
|
256
|
+
|
|
257
|
+
// Assert the number of times `getFormDefinition`
|
|
258
|
+
// has only been called 4 times for the 7 requests
|
|
259
|
+
expect(getFormDefinition).toHaveBeenCalledTimes(4)
|
|
260
|
+
})
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
describe('Error responses', () => {
|
|
264
|
+
test('Dispatch page without the correct state returns 404', async () => {
|
|
265
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce(fixtures.form.metadata)
|
|
266
|
+
|
|
267
|
+
const options = {
|
|
268
|
+
method: 'GET',
|
|
269
|
+
url: '/slug'
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const res = await server.inject(options)
|
|
273
|
+
|
|
274
|
+
expect(res.statusCode).toBe(StatusCodes.NOT_FOUND)
|
|
275
|
+
expect(getCacheSize()).toBe(0)
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
test('Dispatch preview page without the correct draft state returns 404', async () => {
|
|
279
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce(fixtures.form.metadata)
|
|
280
|
+
|
|
281
|
+
const options = {
|
|
282
|
+
method: 'GET',
|
|
283
|
+
url: '/preview/draft/slug'
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const res = await server.inject(options)
|
|
287
|
+
|
|
288
|
+
expect(res.statusCode).toBe(StatusCodes.NOT_FOUND)
|
|
289
|
+
expect(getCacheSize()).toBe(0)
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
test('Dispatch preview page without the correct live state returns 404', async () => {
|
|
293
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce(fixtures.form.metadata)
|
|
294
|
+
|
|
295
|
+
const options = {
|
|
296
|
+
method: 'GET',
|
|
297
|
+
url: '/preview/live/slug'
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const res = await server.inject(options)
|
|
301
|
+
|
|
302
|
+
expect(res.statusCode).toBe(StatusCodes.NOT_FOUND)
|
|
303
|
+
expect(getCacheSize()).toBe(0)
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
test('Dispatch page with the correct live state but no definition returns 404', async () => {
|
|
307
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
308
|
+
...fixtures.form.metadata,
|
|
309
|
+
live: fixtures.form.state
|
|
310
|
+
})
|
|
311
|
+
jest.mocked(getFormDefinition).mockResolvedValue(undefined)
|
|
312
|
+
|
|
313
|
+
const options = {
|
|
314
|
+
method: 'GET',
|
|
315
|
+
url: '/slug'
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const res = await server.inject(options)
|
|
319
|
+
|
|
320
|
+
expect(res.statusCode).toBe(StatusCodes.NOT_FOUND)
|
|
321
|
+
expect(getCacheSize()).toBe(0)
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
test('Dispatch preview page with the correct draft state but no definition returns 404', async () => {
|
|
325
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
326
|
+
...fixtures.form.metadata,
|
|
327
|
+
live: fixtures.form.state
|
|
328
|
+
})
|
|
329
|
+
jest.mocked(getFormDefinition).mockResolvedValue(undefined)
|
|
330
|
+
|
|
331
|
+
const options = {
|
|
332
|
+
method: 'GET',
|
|
333
|
+
url: '/preview/draft/slug'
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const res = await server.inject(options)
|
|
337
|
+
|
|
338
|
+
expect(res.statusCode).toBe(StatusCodes.NOT_FOUND)
|
|
339
|
+
expect(getCacheSize()).toBe(0)
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
test('Dispatch preview page with the correct live state but no definition returns 404', async () => {
|
|
343
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
344
|
+
...fixtures.form.metadata,
|
|
345
|
+
live: fixtures.form.state
|
|
346
|
+
})
|
|
347
|
+
jest.mocked(getFormDefinition).mockResolvedValue(undefined)
|
|
348
|
+
|
|
349
|
+
const options = {
|
|
350
|
+
method: 'GET',
|
|
351
|
+
url: '/preview/live/slug'
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const res = await server.inject(options)
|
|
355
|
+
|
|
356
|
+
expect(res.statusCode).toBe(StatusCodes.NOT_FOUND)
|
|
357
|
+
expect(getCacheSize()).toBe(0)
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
test('Get page without the correct state returns 404', async () => {
|
|
361
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce(fixtures.form.metadata)
|
|
362
|
+
|
|
363
|
+
const options = {
|
|
364
|
+
method: 'GET',
|
|
365
|
+
url: '/slug/page-one'
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const res = await server.inject(options)
|
|
369
|
+
|
|
370
|
+
expect(res.statusCode).toBe(StatusCodes.NOT_FOUND)
|
|
371
|
+
expect(getCacheSize()).toBe(0)
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
test('Get preview page without the correct draft state returns 404', async () => {
|
|
375
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce(fixtures.form.metadata)
|
|
376
|
+
|
|
377
|
+
const options = {
|
|
378
|
+
method: 'GET',
|
|
379
|
+
url: '/preview/draft/slug/page-one'
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const res = await server.inject(options)
|
|
383
|
+
|
|
384
|
+
expect(res.statusCode).toBe(StatusCodes.NOT_FOUND)
|
|
385
|
+
expect(getCacheSize()).toBe(0)
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
test('Get preview page without the correct live state returns 404', async () => {
|
|
389
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce(fixtures.form.metadata)
|
|
390
|
+
|
|
391
|
+
const options = {
|
|
392
|
+
method: 'GET',
|
|
393
|
+
url: '/preview/live/slug/page-one'
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const res = await server.inject(options)
|
|
397
|
+
|
|
398
|
+
expect(res.statusCode).toBe(StatusCodes.NOT_FOUND)
|
|
399
|
+
expect(getCacheSize()).toBe(0)
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
test('Get page with the correct live state but no definition returns 404', async () => {
|
|
403
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
404
|
+
...fixtures.form.metadata,
|
|
405
|
+
live: fixtures.form.state
|
|
406
|
+
})
|
|
407
|
+
jest.mocked(getFormDefinition).mockResolvedValue(undefined)
|
|
408
|
+
|
|
409
|
+
const options = {
|
|
410
|
+
method: 'GET',
|
|
411
|
+
url: '/slug/page-one'
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const res = await server.inject(options)
|
|
415
|
+
|
|
416
|
+
expect(res.statusCode).toBe(StatusCodes.NOT_FOUND)
|
|
417
|
+
expect(getCacheSize()).toBe(0)
|
|
418
|
+
})
|
|
419
|
+
|
|
420
|
+
test('Get preview page with the correct draft state but no definition returns 404', async () => {
|
|
421
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
422
|
+
...fixtures.form.metadata,
|
|
423
|
+
live: fixtures.form.state
|
|
424
|
+
})
|
|
425
|
+
jest.mocked(getFormDefinition).mockResolvedValue(undefined)
|
|
426
|
+
|
|
427
|
+
const options = {
|
|
428
|
+
method: 'GET',
|
|
429
|
+
url: '/preview/draft/slug/page-one'
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const res = await server.inject(options)
|
|
433
|
+
|
|
434
|
+
expect(res.statusCode).toBe(StatusCodes.NOT_FOUND)
|
|
435
|
+
expect(getCacheSize()).toBe(0)
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
test('Get preview page with the correct live state but no definition returns 404', async () => {
|
|
439
|
+
jest.mocked(getFormMetadata).mockResolvedValueOnce({
|
|
440
|
+
...fixtures.form.metadata,
|
|
441
|
+
live: fixtures.form.state
|
|
442
|
+
})
|
|
443
|
+
jest.mocked(getFormDefinition).mockResolvedValue(undefined)
|
|
444
|
+
|
|
445
|
+
const options = {
|
|
446
|
+
method: 'GET',
|
|
447
|
+
url: '/preview/live/slug/page-one'
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const res = await server.inject(options)
|
|
451
|
+
|
|
452
|
+
expect(res.statusCode).toBe(StatusCodes.NOT_FOUND)
|
|
453
|
+
expect(getCacheSize()).toBe(0)
|
|
454
|
+
})
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
describe('Help pages', () => {
|
|
458
|
+
test('Contextual help page returns 200', async () => {
|
|
459
|
+
jest.mocked(getFormMetadata).mockResolvedValue({
|
|
460
|
+
...fixtures.form.metadata,
|
|
461
|
+
draft: fixtures.form.state,
|
|
462
|
+
live: fixtures.form.state
|
|
463
|
+
})
|
|
464
|
+
|
|
465
|
+
const options = {
|
|
466
|
+
method: 'GET',
|
|
467
|
+
url: '/help/get-support/slug'
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const res = await server.inject(options)
|
|
471
|
+
|
|
472
|
+
expect(res.statusCode).toBe(StatusCodes.OK)
|
|
473
|
+
})
|
|
474
|
+
|
|
475
|
+
test('Privacy notice page returns 200', async () => {
|
|
476
|
+
jest.mocked(getFormMetadata).mockResolvedValue({
|
|
477
|
+
...fixtures.form.metadata,
|
|
478
|
+
draft: fixtures.form.state,
|
|
479
|
+
live: fixtures.form.state
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
const options = {
|
|
483
|
+
method: 'GET',
|
|
484
|
+
url: '/help/privacy/slug'
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
const res = await server.inject(options)
|
|
488
|
+
|
|
489
|
+
expect(res.statusCode).toBe(StatusCodes.OK)
|
|
490
|
+
})
|
|
491
|
+
})
|
|
492
|
+
})
|
|
493
|
+
|
|
494
|
+
describe('Upload status route', () => {
|
|
495
|
+
let server: Server
|
|
496
|
+
|
|
497
|
+
beforeAll(async () => {
|
|
498
|
+
server = await createServer()
|
|
499
|
+
await server.initialize()
|
|
500
|
+
})
|
|
501
|
+
|
|
502
|
+
afterAll(async () => {
|
|
503
|
+
await server.stop()
|
|
504
|
+
})
|
|
505
|
+
|
|
506
|
+
beforeEach(() => {
|
|
507
|
+
jest.resetAllMocks()
|
|
508
|
+
})
|
|
509
|
+
|
|
510
|
+
test('GET /upload-status/{uploadId} returns upload status with 200 when successful', async () => {
|
|
511
|
+
const mockStatus: UploadStatusResponse = {
|
|
512
|
+
uploadStatus: UploadStatus.ready,
|
|
513
|
+
metadata: {
|
|
514
|
+
retrievalKey: 'some-key'
|
|
515
|
+
},
|
|
516
|
+
form: {
|
|
517
|
+
file: {
|
|
518
|
+
fileId: 'some-file-id',
|
|
519
|
+
filename: 'some-file-name',
|
|
520
|
+
contentLength: 1024,
|
|
521
|
+
fileStatus: FileStatus.complete
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
numberOfRejectedFiles: 0
|
|
525
|
+
}
|
|
526
|
+
jest.mocked(getUploadStatus).mockResolvedValueOnce(mockStatus)
|
|
527
|
+
|
|
528
|
+
const options = {
|
|
529
|
+
method: 'GET',
|
|
530
|
+
url: '/upload-status/123e4567-e89b-12d3-a456-426614174000'
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
const res = await server.inject(options)
|
|
534
|
+
|
|
535
|
+
expect(res.statusCode).toBe(StatusCodes.OK)
|
|
536
|
+
expect(res.result).toEqual(mockStatus)
|
|
537
|
+
expect(getUploadStatus).toHaveBeenCalledWith(
|
|
538
|
+
'123e4567-e89b-12d3-a456-426614174000'
|
|
539
|
+
)
|
|
540
|
+
})
|
|
541
|
+
|
|
542
|
+
test('GET /upload-status/{uploadId} returns 400 when status check fails', async () => {
|
|
543
|
+
jest.mocked(getUploadStatus).mockResolvedValueOnce(undefined)
|
|
544
|
+
|
|
545
|
+
const options = {
|
|
546
|
+
method: 'GET',
|
|
547
|
+
url: '/upload-status/123e4567-e89b-12d3-a456-426614174000'
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const res = await server.inject(options)
|
|
551
|
+
|
|
552
|
+
expect(res.statusCode).toBe(StatusCodes.BAD_REQUEST)
|
|
553
|
+
expect(res.result).toEqual({ error: 'Status check failed' })
|
|
554
|
+
})
|
|
555
|
+
|
|
556
|
+
test('GET /upload-status/{uploadId} returns 500 when exception occurs', async () => {
|
|
557
|
+
jest
|
|
558
|
+
.mocked(getUploadStatus)
|
|
559
|
+
.mockRejectedValueOnce(new Error('Service unavailable'))
|
|
560
|
+
|
|
561
|
+
const options = {
|
|
562
|
+
method: 'GET',
|
|
563
|
+
url: '/upload-status/123e4567-e89b-12d3-a456-426614174000'
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
const res = await server.inject(options)
|
|
567
|
+
|
|
568
|
+
expect(res.statusCode).toBe(StatusCodes.INTERNAL_SERVER_ERROR)
|
|
569
|
+
expect(res.result).toEqual({ error: 'Status check error' })
|
|
570
|
+
})
|
|
571
|
+
|
|
572
|
+
test('GET /upload-status/{uploadId} returns 400 for invalid uploadId format', async () => {
|
|
573
|
+
const options = {
|
|
574
|
+
method: 'GET',
|
|
575
|
+
url: '/upload-status/not-a-valid-guid'
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
const res = await server.inject(options)
|
|
579
|
+
|
|
580
|
+
expect(res.statusCode).toBe(StatusCodes.BAD_REQUEST)
|
|
581
|
+
})
|
|
582
|
+
})
|