@defra/forms-engine-plugin 4.7.2 → 4.8.0

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.
Files changed (407) hide show
  1. package/.public/javascripts/shared.min.js +1 -1
  2. package/.public/javascripts/shared.min.js.map +1 -1
  3. package/.server/client/javascripts/geospatial-map.d.ts +6 -6
  4. package/.server/client/javascripts/geospatial-map.js +3 -3
  5. package/.server/client/javascripts/location-map.d.ts +1 -1
  6. package/.server/client/javascripts/location-map.js +1 -1
  7. package/.server/client/javascripts/map.d.ts +5 -1
  8. package/.server/client/javascripts/map.js +10 -2
  9. package/.server/client/javascripts/map.js.map +1 -1
  10. package/.server/client/javascripts/shared.d.ts +7 -7
  11. package/.server/server/index.d.ts +1 -1
  12. package/.server/server/plugins/crumb.d.ts +1 -1
  13. package/.server/server/plugins/engine/beta/form-context.d.ts +6 -6
  14. package/.server/server/plugins/engine/components/AutocompleteField.d.ts +4 -4
  15. package/.server/server/plugins/engine/components/CheckboxesField.d.ts +2 -2
  16. package/.server/server/plugins/engine/components/CheckboxesField.js +2 -2
  17. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
  18. package/.server/server/plugins/engine/components/ComponentBase.d.ts +5 -5
  19. package/.server/server/plugins/engine/components/ComponentCollection.d.ts +8 -8
  20. package/.server/server/plugins/engine/components/DatePartsField.d.ts +11 -11
  21. package/.server/server/plugins/engine/components/DeclarationField.d.ts +3 -3
  22. package/.server/server/plugins/engine/components/Details.d.ts +1 -1
  23. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +22 -22
  24. package/.server/server/plugins/engine/components/EmailAddressField.d.ts +4 -4
  25. package/.server/server/plugins/engine/components/FileUploadField.d.ts +3 -3
  26. package/.server/server/plugins/engine/components/FormComponent.d.ts +10 -10
  27. package/.server/server/plugins/engine/components/GeospatialField.d.ts +6 -6
  28. package/.server/server/plugins/engine/components/HiddenField.d.ts +2 -2
  29. package/.server/server/plugins/engine/components/Html.d.ts +1 -1
  30. package/.server/server/plugins/engine/components/InsetText.d.ts +1 -1
  31. package/.server/server/plugins/engine/components/LatLongField.d.ts +22 -22
  32. package/.server/server/plugins/engine/components/List.d.ts +8 -8
  33. package/.server/server/plugins/engine/components/ListFormComponent.d.ts +10 -10
  34. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +6 -6
  35. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +14 -14
  36. package/.server/server/plugins/engine/components/Markdown.d.ts +1 -1
  37. package/.server/server/plugins/engine/components/MonthYearField.d.ts +11 -11
  38. package/.server/server/plugins/engine/components/MultilineTextField.d.ts +5 -5
  39. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +1 -1
  40. package/.server/server/plugins/engine/components/NumberField.d.ts +3 -3
  41. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +1 -1
  42. package/.server/server/plugins/engine/components/PaymentField.d.ts +12 -12
  43. package/.server/server/plugins/engine/components/RadiosField.d.ts +1 -1
  44. package/.server/server/plugins/engine/components/SelectField.d.ts +4 -4
  45. package/.server/server/plugins/engine/components/SelectionControlField.d.ts +10 -10
  46. package/.server/server/plugins/engine/components/TelephoneNumberField.d.ts +4 -4
  47. package/.server/server/plugins/engine/components/TextField.d.ts +2 -2
  48. package/.server/server/plugins/engine/components/UkAddressField.d.ts +11 -11
  49. package/.server/server/plugins/engine/components/YesNoField.d.ts +2 -2
  50. package/.server/server/plugins/engine/components/helpers/__stubs__/geospatial.d.ts +1 -1
  51. package/.server/server/plugins/engine/components/helpers/components.d.ts +5 -5
  52. package/.server/server/plugins/engine/components/helpers/geospatial.d.ts +1 -1
  53. package/.server/server/plugins/engine/components/index.d.ts +27 -27
  54. package/.server/server/plugins/engine/components/types.d.ts +1 -1
  55. package/.server/server/plugins/engine/configureEnginePlugin.d.ts +4 -4
  56. package/.server/server/plugins/engine/date-helper.d.ts +1 -1
  57. package/.server/server/plugins/engine/helpers.d.ts +8 -8
  58. package/.server/server/plugins/engine/index.d.ts +5 -5
  59. package/.server/server/plugins/engine/models/FormModel.d.ts +6 -6
  60. package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +6 -6
  61. package/.server/server/plugins/engine/models/index.d.ts +2 -2
  62. package/.server/server/plugins/engine/models/types.d.ts +4 -4
  63. package/.server/server/plugins/engine/options.d.ts +1 -1
  64. package/.server/server/plugins/engine/options.js +1 -1
  65. package/.server/server/plugins/engine/options.test.js +1 -1
  66. package/.server/server/plugins/engine/outputFormatters/adapter/v1.d.ts +4 -4
  67. package/.server/server/plugins/engine/outputFormatters/human/v1.d.ts +4 -4
  68. package/.server/server/plugins/engine/outputFormatters/index.d.ts +5 -5
  69. package/.server/server/plugins/engine/outputFormatters/machine/v1.d.ts +4 -4
  70. package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +4 -4
  71. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +8 -8
  72. package/.server/server/plugins/engine/pageControllers/PageController.d.ts +6 -6
  73. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +8 -8
  74. package/.server/server/plugins/engine/pageControllers/RepeatPageController.d.ts +5 -5
  75. package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +4 -4
  76. package/.server/server/plugins/engine/pageControllers/StatusPageController.d.ts +4 -4
  77. package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +5 -5
  78. package/.server/server/plugins/engine/pageControllers/TerminalPageController.d.ts +3 -3
  79. package/.server/server/plugins/engine/pageControllers/__stubs__/request.d.ts +2 -2
  80. package/.server/server/plugins/engine/pageControllers/errors.d.ts +1 -1
  81. package/.server/server/plugins/engine/pageControllers/helpers/pages.d.ts +2 -2
  82. package/.server/server/plugins/engine/pageControllers/helpers/state.d.ts +5 -5
  83. package/.server/server/plugins/engine/pageControllers/helpers/state.js +1 -1
  84. package/.server/server/plugins/engine/pageControllers/helpers/state.js.map +1 -1
  85. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +1 -1
  86. package/.server/server/plugins/engine/pageControllers/index.d.ts +7 -7
  87. package/.server/server/plugins/engine/plugin.d.ts +1 -1
  88. package/.server/server/plugins/engine/routes/file-upload.d.ts +1 -1
  89. package/.server/server/plugins/engine/routes/index.d.ts +3 -3
  90. package/.server/server/plugins/engine/routes/payment-helper.d.ts +3 -3
  91. package/.server/server/plugins/engine/routes/payment-helper.js +2 -2
  92. package/.server/server/plugins/engine/routes/payment.js +5 -5
  93. package/.server/server/plugins/engine/routes/payment.test.js +1 -1
  94. package/.server/server/plugins/engine/routes/questions.d.ts +2 -2
  95. package/.server/server/plugins/engine/routes/repeaters/item-delete.d.ts +2 -2
  96. package/.server/server/plugins/engine/routes/repeaters/summary.d.ts +2 -2
  97. package/.server/server/plugins/engine/services/index.d.ts +3 -3
  98. package/.server/server/plugins/engine/services/notifyService.d.ts +4 -4
  99. package/.server/server/plugins/engine/services/uploadService.d.ts +2 -2
  100. package/.server/server/plugins/engine/services/uploadService.js +1 -1
  101. package/.server/server/plugins/engine/types/index.d.ts +10 -10
  102. package/.server/server/plugins/engine/types/schema.d.ts +1 -1
  103. package/.server/server/plugins/engine/types.d.ts +25 -16
  104. package/.server/server/plugins/engine/types.js.map +1 -1
  105. package/.server/server/plugins/engine/validationHelpers.d.ts +2 -2
  106. package/.server/server/plugins/engine/vision.d.ts +1 -1
  107. package/.server/server/plugins/map/index.d.ts +1 -1
  108. package/.server/server/plugins/map/index.js +1 -1
  109. package/.server/server/plugins/map/routes/get-os-token.d.ts +11 -1
  110. package/.server/server/plugins/map/routes/get-os-token.js +12 -2
  111. package/.server/server/plugins/map/routes/get-os-token.js.map +1 -1
  112. package/.server/server/plugins/map/routes/index.d.ts +4 -4
  113. package/.server/server/plugins/map/routes/index.js +3 -2
  114. package/.server/server/plugins/map/routes/index.js.map +1 -1
  115. package/.server/server/plugins/map/routes/vts/esri-aerial.json +23 -0
  116. package/.server/server/plugins/map/service.d.ts +1 -1
  117. package/.server/server/plugins/map/service.js +5 -2
  118. package/.server/server/plugins/map/service.js.map +1 -1
  119. package/.server/server/plugins/map/test/__stubs__/find.d.ts +1 -1
  120. package/.server/server/plugins/map/test/__stubs__/find.js +1 -1
  121. package/.server/server/plugins/nunjucks/context.d.ts +2 -2
  122. package/.server/server/plugins/nunjucks/context.js +2 -2
  123. package/.server/server/plugins/nunjucks/context.test.js +1 -1
  124. package/.server/server/plugins/nunjucks/enviroment.test.js +1 -1
  125. package/.server/server/plugins/nunjucks/environment.d.ts +3 -3
  126. package/.server/server/plugins/nunjucks/environment.js +3 -3
  127. package/.server/server/plugins/nunjucks/filters/answer.d.ts +1 -1
  128. package/.server/server/plugins/nunjucks/filters/answer.js +2 -2
  129. package/.server/server/plugins/nunjucks/filters/answer.test.js +1 -1
  130. package/.server/server/plugins/nunjucks/filters/evaluate.d.ts +1 -1
  131. package/.server/server/plugins/nunjucks/filters/evaluate.js +1 -1
  132. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  133. package/.server/server/plugins/nunjucks/filters/field.js +1 -1
  134. package/.server/server/plugins/nunjucks/filters/field.test.js +1 -1
  135. package/.server/server/plugins/nunjucks/filters/href.d.ts +1 -1
  136. package/.server/server/plugins/nunjucks/filters/href.js +1 -1
  137. package/.server/server/plugins/nunjucks/filters/href.test.js +1 -1
  138. package/.server/server/plugins/nunjucks/filters/index.d.ts +8 -8
  139. package/.server/server/plugins/nunjucks/filters/page.d.ts +1 -1
  140. package/.server/server/plugins/nunjucks/filters/page.js +1 -1
  141. package/.server/server/plugins/nunjucks/filters/page.test.js +1 -1
  142. package/.server/server/plugins/nunjucks/index.d.ts +3 -3
  143. package/.server/server/plugins/nunjucks/render.d.ts +2 -2
  144. package/.server/server/plugins/nunjucks/render.js +1 -1
  145. package/.server/server/plugins/nunjucks/types.d.ts +1 -1
  146. package/.server/server/plugins/nunjucks/types.js +1 -1
  147. package/.server/server/plugins/payment/helper.d.ts +2 -2
  148. package/.server/server/plugins/payment/helper.js +1 -1
  149. package/.server/server/plugins/payment/service.d.ts +3 -3
  150. package/.server/server/plugins/payment/service.js +1 -1
  151. package/.server/server/plugins/postcode-lookup/index.d.ts +1 -1
  152. package/.server/server/plugins/postcode-lookup/index.js +1 -1
  153. package/.server/server/plugins/postcode-lookup/models/index.d.ts +6 -6
  154. package/.server/server/plugins/postcode-lookup/models/index.js +1 -1
  155. package/.server/server/plugins/postcode-lookup/routes/index.d.ts +6 -6
  156. package/.server/server/plugins/postcode-lookup/routes/index.js +15 -15
  157. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  158. package/.server/server/plugins/postcode-lookup/service.d.ts +1 -1
  159. package/.server/server/plugins/postcode-lookup/service.js +5 -2
  160. package/.server/server/plugins/postcode-lookup/service.js.map +1 -1
  161. package/.server/server/plugins/postcode-lookup/types.js +1 -1
  162. package/.server/server/routes/index.d.ts +2 -2
  163. package/.server/server/routes/types.d.ts +1 -1
  164. package/.server/server/schemas/index.d.ts +2 -2
  165. package/.server/server/services/cacheService.d.ts +8 -8
  166. package/.server/server/services/cacheService.js +2 -5
  167. package/.server/server/services/cacheService.js.map +1 -1
  168. package/.server/server/services/httpService.test.js +1 -1
  169. package/.server/server/services/index.d.ts +1 -1
  170. package/.server/server/types.d.ts +7 -7
  171. package/.server/server/utils/file-form-service.d.ts +2 -2
  172. package/.server/server/utils/file-form-service.js +1 -1
  173. package/package.json +8 -4
  174. package/src/client/javascripts/application.js +1 -1
  175. package/src/client/javascripts/geospatial-map.js +4 -4
  176. package/src/client/javascripts/location-map.js +2 -2
  177. package/src/client/javascripts/map.js +13 -4
  178. package/src/client/javascripts/shared.js +7 -7
  179. package/src/index.ts +3 -3
  180. package/src/server/common/helpers/logging/logger-options.ts +1 -1
  181. package/src/server/common/helpers/logging/logger.ts +1 -1
  182. package/src/server/common/helpers/logging/request-logger.ts +1 -1
  183. package/src/server/common/helpers/logging/request-tracing.js +1 -1
  184. package/src/server/common/helpers/redis-client.js +2 -2
  185. package/src/server/index.ts +13 -13
  186. package/src/server/plugins/crumb.ts +2 -2
  187. package/src/server/plugins/engine/beta/form-context.ts +9 -9
  188. package/src/server/plugins/engine/components/AutocompleteField.ts +3 -3
  189. package/src/server/plugins/engine/components/CheckboxesField.ts +7 -8
  190. package/src/server/plugins/engine/components/ComponentBase.ts +5 -5
  191. package/src/server/plugins/engine/components/ComponentCollection.ts +9 -9
  192. package/src/server/plugins/engine/components/DatePartsField.ts +8 -8
  193. package/src/server/plugins/engine/components/DeclarationField.ts +3 -3
  194. package/src/server/plugins/engine/components/Details.ts +1 -1
  195. package/src/server/plugins/engine/components/EastingNorthingField.ts +9 -9
  196. package/src/server/plugins/engine/components/EmailAddressField.ts +3 -3
  197. package/src/server/plugins/engine/components/FileUploadField.ts +6 -6
  198. package/src/server/plugins/engine/components/FormComponent.ts +4 -4
  199. package/src/server/plugins/engine/components/GeospatialField.ts +5 -5
  200. package/src/server/plugins/engine/components/HiddenField.ts +4 -4
  201. package/src/server/plugins/engine/components/Html.ts +1 -1
  202. package/src/server/plugins/engine/components/InsetText.ts +1 -1
  203. package/src/server/plugins/engine/components/LatLongField.ts +9 -9
  204. package/src/server/plugins/engine/components/List.ts +2 -2
  205. package/src/server/plugins/engine/components/ListFormComponent.ts +4 -4
  206. package/src/server/plugins/engine/components/LocationFieldBase.ts +5 -5
  207. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +5 -5
  208. package/src/server/plugins/engine/components/Markdown.ts +1 -1
  209. package/src/server/plugins/engine/components/MonthYearField.ts +8 -8
  210. package/src/server/plugins/engine/components/MultilineTextField.ts +4 -4
  211. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +2 -2
  212. package/src/server/plugins/engine/components/NumberField.ts +3 -3
  213. package/src/server/plugins/engine/components/OsGridRefField.ts +2 -2
  214. package/src/server/plugins/engine/components/PaymentField.ts +8 -8
  215. package/src/server/plugins/engine/components/RadiosField.ts +1 -1
  216. package/src/server/plugins/engine/components/SelectField.ts +2 -2
  217. package/src/server/plugins/engine/components/SelectionControlField.ts +4 -4
  218. package/src/server/plugins/engine/components/TelephoneNumberField.ts +4 -4
  219. package/src/server/plugins/engine/components/TextField.ts +3 -3
  220. package/src/server/plugins/engine/components/UkAddressField.ts +7 -7
  221. package/src/server/plugins/engine/components/YesNoField.ts +5 -5
  222. package/src/server/plugins/engine/components/helpers/__stubs__/geospatial.ts +1 -1
  223. package/src/server/plugins/engine/components/helpers/components.ts +8 -8
  224. package/src/server/plugins/engine/components/helpers/geospatial.ts +1 -1
  225. package/src/server/plugins/engine/components/index.ts +27 -27
  226. package/src/server/plugins/engine/components/types.ts +1 -1
  227. package/src/server/plugins/engine/configureEnginePlugin.ts +10 -10
  228. package/src/server/plugins/engine/date-helper.ts +1 -1
  229. package/src/server/plugins/engine/helpers.ts +8 -8
  230. package/src/server/plugins/engine/index.ts +8 -8
  231. package/src/server/plugins/engine/models/FormModel.ts +15 -15
  232. package/src/server/plugins/engine/models/SummaryViewModel.ts +10 -10
  233. package/src/server/plugins/engine/models/index.ts +2 -2
  234. package/src/server/plugins/engine/models/types.ts +4 -4
  235. package/src/server/plugins/engine/options.js +3 -3
  236. package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +6 -6
  237. package/src/server/plugins/engine/outputFormatters/human/v1.ts +9 -9
  238. package/src/server/plugins/engine/outputFormatters/index.ts +8 -8
  239. package/src/server/plugins/engine/outputFormatters/machine/v1.ts +7 -7
  240. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +6 -6
  241. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +9 -9
  242. package/src/server/plugins/engine/pageControllers/PageController.ts +7 -7
  243. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +13 -13
  244. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +6 -6
  245. package/src/server/plugins/engine/pageControllers/StartPageController.ts +3 -3
  246. package/src/server/plugins/engine/pageControllers/StatusPageController.ts +5 -5
  247. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +12 -12
  248. package/src/server/plugins/engine/pageControllers/TerminalPageController.ts +3 -3
  249. package/src/server/plugins/engine/pageControllers/__stubs__/request.ts +3 -3
  250. package/src/server/plugins/engine/pageControllers/__stubs__/server.ts +2 -2
  251. package/src/server/plugins/engine/pageControllers/errors.ts +1 -1
  252. package/src/server/plugins/engine/pageControllers/helpers/pages.ts +2 -2
  253. package/src/server/plugins/engine/pageControllers/helpers/state.ts +9 -9
  254. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +5 -5
  255. package/src/server/plugins/engine/pageControllers/index.ts +7 -7
  256. package/src/server/plugins/engine/pageControllers/validationOptions.ts +1 -1
  257. package/src/server/plugins/engine/plugin.ts +14 -14
  258. package/src/server/plugins/engine/routes/file-upload.ts +2 -2
  259. package/src/server/plugins/engine/routes/index.ts +10 -10
  260. package/src/server/plugins/engine/routes/payment-helper.js +4 -4
  261. package/src/server/plugins/engine/routes/payment.js +9 -9
  262. package/src/server/plugins/engine/routes/questions.ts +10 -10
  263. package/src/server/plugins/engine/routes/repeaters/item-delete.ts +6 -6
  264. package/src/server/plugins/engine/routes/repeaters/summary.ts +5 -5
  265. package/src/server/plugins/engine/services/formSubmissionService.js +2 -2
  266. package/src/server/plugins/engine/services/index.js +3 -3
  267. package/src/server/plugins/engine/services/localFormsService.js +2 -2
  268. package/src/server/plugins/engine/services/notifyService.ts +9 -9
  269. package/src/server/plugins/engine/services/uploadService.js +3 -3
  270. package/src/server/plugins/engine/types/index.ts +10 -10
  271. package/src/server/plugins/engine/types/schema.ts +2 -2
  272. package/src/server/plugins/engine/types.ts +22 -17
  273. package/src/server/plugins/engine/validationHelpers.ts +3 -3
  274. package/src/server/plugins/engine/vision.ts +3 -3
  275. package/src/server/plugins/map/index.js +2 -2
  276. package/src/server/plugins/map/routes/get-os-token.js +15 -3
  277. package/src/server/plugins/map/routes/index.js +7 -5
  278. package/src/server/plugins/map/routes/vts/esri-aerial.json +23 -0
  279. package/src/server/plugins/map/service.js +7 -4
  280. package/src/server/plugins/map/test/__stubs__/find.js +1 -1
  281. package/src/server/plugins/nunjucks/context.js +5 -5
  282. package/src/server/plugins/nunjucks/environment.js +6 -6
  283. package/src/server/plugins/nunjucks/filters/answer.js +3 -3
  284. package/src/server/plugins/nunjucks/filters/evaluate.js +2 -2
  285. package/src/server/plugins/nunjucks/filters/field.js +1 -1
  286. package/src/server/plugins/nunjucks/filters/href.js +2 -2
  287. package/src/server/plugins/nunjucks/filters/index.js +8 -8
  288. package/src/server/plugins/nunjucks/filters/page.js +1 -1
  289. package/src/server/plugins/nunjucks/index.js +3 -3
  290. package/src/server/plugins/nunjucks/plugin.js +3 -3
  291. package/src/server/plugins/nunjucks/render.js +2 -2
  292. package/src/server/plugins/nunjucks/types.js +1 -1
  293. package/src/server/plugins/payment/helper.js +2 -2
  294. package/src/server/plugins/payment/service.js +4 -4
  295. package/src/server/plugins/postcode-lookup/index.js +2 -2
  296. package/src/server/plugins/postcode-lookup/models/index.js +3 -3
  297. package/src/server/plugins/postcode-lookup/routes/index.js +24 -14
  298. package/src/server/plugins/postcode-lookup/service.js +7 -4
  299. package/src/server/plugins/postcode-lookup/types.js +1 -1
  300. package/src/server/plugins/session.ts +1 -1
  301. package/src/server/routes/index.ts +2 -2
  302. package/src/server/routes/public.ts +1 -1
  303. package/src/server/routes/types.ts +1 -1
  304. package/src/server/schemas/index.ts +2 -2
  305. package/src/server/secure-context.js +1 -1
  306. package/src/server/services/cacheService.ts +13 -18
  307. package/src/server/services/httpService.ts +1 -1
  308. package/src/server/services/index.ts +1 -1
  309. package/src/server/types.ts +7 -7
  310. package/src/server/utils/notify.ts +2 -2
  311. package/src/server/utils/utils.js +1 -1
  312. package/src/typings/hapi/index.d.ts +4 -4
  313. package/src/typings/joi/index.d.ts +1 -1
  314. package/src/server/common/helpers/logging/logger-options.test.ts +0 -50
  315. package/src/server/index.test.ts +0 -644
  316. package/src/server/plugins/engine/beta/form-context.test.ts +0 -373
  317. package/src/server/plugins/engine/components/AutocompleteField.test.ts +0 -362
  318. package/src/server/plugins/engine/components/CheckboxesField.test.ts +0 -486
  319. package/src/server/plugins/engine/components/DatePartsField.test.ts +0 -927
  320. package/src/server/plugins/engine/components/DeclarationField.test.ts +0 -560
  321. package/src/server/plugins/engine/components/Details.test.ts +0 -49
  322. package/src/server/plugins/engine/components/EastingNorthingField.test.ts +0 -727
  323. package/src/server/plugins/engine/components/EmailAddressField.test.ts +0 -445
  324. package/src/server/plugins/engine/components/FileUploadField.test.ts +0 -1079
  325. package/src/server/plugins/engine/components/GeospatialField.test.ts +0 -380
  326. package/src/server/plugins/engine/components/HiddenField.test.ts +0 -188
  327. package/src/server/plugins/engine/components/Html.test.ts +0 -48
  328. package/src/server/plugins/engine/components/InsetText.test.ts +0 -48
  329. package/src/server/plugins/engine/components/LatLongField.test.ts +0 -898
  330. package/src/server/plugins/engine/components/List.test.ts +0 -79
  331. package/src/server/plugins/engine/components/LocationFieldBase.test.ts +0 -253
  332. package/src/server/plugins/engine/components/LocationFieldHelpers.test.ts +0 -743
  333. package/src/server/plugins/engine/components/Markdown.test.ts +0 -48
  334. package/src/server/plugins/engine/components/MonthYearField.test.ts +0 -617
  335. package/src/server/plugins/engine/components/MultilineTextField.test.ts +0 -647
  336. package/src/server/plugins/engine/components/NationalGridFieldNumberField.test.ts +0 -449
  337. package/src/server/plugins/engine/components/NumberField.test.ts +0 -723
  338. package/src/server/plugins/engine/components/OsGridRefField.test.ts +0 -460
  339. package/src/server/plugins/engine/components/PaymentField.test.ts +0 -745
  340. package/src/server/plugins/engine/components/RadiosField.test.ts +0 -297
  341. package/src/server/plugins/engine/components/SelectField.test.ts +0 -289
  342. package/src/server/plugins/engine/components/TelephoneNumberField.test.ts +0 -384
  343. package/src/server/plugins/engine/components/TextField.test.ts +0 -521
  344. package/src/server/plugins/engine/components/UkAddressField.test.ts +0 -806
  345. package/src/server/plugins/engine/components/YesNoField.test.ts +0 -256
  346. package/src/server/plugins/engine/components/helpers/components.test.ts +0 -399
  347. package/src/server/plugins/engine/components/helpers/geospatial.test.js +0 -55
  348. package/src/server/plugins/engine/components/helpers/helpers.test.ts +0 -219
  349. package/src/server/plugins/engine/date-helper.test.ts +0 -47
  350. package/src/server/plugins/engine/helpers.test.ts +0 -868
  351. package/src/server/plugins/engine/models/FormModel.test.ts +0 -725
  352. package/src/server/plugins/engine/models/SummaryViewModel.test.ts +0 -472
  353. package/src/server/plugins/engine/options.test.js +0 -63
  354. package/src/server/plugins/engine/outputFormatters/adapter/v1.location.test.ts +0 -356
  355. package/src/server/plugins/engine/outputFormatters/adapter/v1.test.ts +0 -871
  356. package/src/server/plugins/engine/outputFormatters/human/v1.payment.test.ts +0 -147
  357. package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +0 -145
  358. package/src/server/plugins/engine/outputFormatters/index.test.ts +0 -17
  359. package/src/server/plugins/engine/outputFormatters/machine/v1.test.ts +0 -268
  360. package/src/server/plugins/engine/outputFormatters/machine/v2.location.test.ts +0 -341
  361. package/src/server/plugins/engine/outputFormatters/machine/v2.payment.test.ts +0 -115
  362. package/src/server/plugins/engine/outputFormatters/machine/v2.test.ts +0 -311
  363. package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +0 -1372
  364. package/src/server/plugins/engine/pageControllers/PageController.test.ts +0 -246
  365. package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +0 -1686
  366. package/src/server/plugins/engine/pageControllers/RepeatPageController.test.ts +0 -279
  367. package/src/server/plugins/engine/pageControllers/StartPageController.test.ts +0 -32
  368. package/src/server/plugins/engine/pageControllers/StatusPageController.test.ts +0 -32
  369. package/src/server/plugins/engine/pageControllers/SummaryPageController.test.ts +0 -89
  370. package/src/server/plugins/engine/pageControllers/TerminalController.test.ts +0 -37
  371. package/src/server/plugins/engine/pageControllers/errors.test.ts +0 -78
  372. package/src/server/plugins/engine/pageControllers/helpers/helpers.test.ts +0 -182
  373. package/src/server/plugins/engine/pageControllers/helpers/state.test.ts +0 -359
  374. package/src/server/plugins/engine/pageControllers/helpers/submission.test.ts +0 -373
  375. package/src/server/plugins/engine/referenceNumbers.test.ts +0 -74
  376. package/src/server/plugins/engine/routes/index.test.ts +0 -332
  377. package/src/server/plugins/engine/routes/payment-helper.test.js +0 -136
  378. package/src/server/plugins/engine/routes/payment.test.js +0 -180
  379. package/src/server/plugins/engine/routes/questions.test.ts +0 -502
  380. package/src/server/plugins/engine/routes/repeaters/item-delete.test.ts +0 -83
  381. package/src/server/plugins/engine/routes/repeaters/summary.test.ts +0 -75
  382. package/src/server/plugins/engine/services/formsService.test.js +0 -26
  383. package/src/server/plugins/engine/services/notifyService.test.ts +0 -310
  384. package/src/server/plugins/engine/types/schema.test.ts +0 -234
  385. package/src/server/plugins/engine/views/components/service-banner/template.test.js +0 -43
  386. package/src/server/plugins/engine/views/components/tag-env/template.test.js +0 -28
  387. package/src/server/plugins/engine/views/partials/preview-banner.test.js +0 -122
  388. package/src/server/plugins/map/routes/get-os-token.test.js +0 -55
  389. package/src/server/plugins/map/service.test.js +0 -144
  390. package/src/server/plugins/nunjucks/context.test.js +0 -109
  391. package/src/server/plugins/nunjucks/enviroment.test.js +0 -207
  392. package/src/server/plugins/nunjucks/filters/answer.test.js +0 -92
  393. package/src/server/plugins/nunjucks/filters/field.test.js +0 -75
  394. package/src/server/plugins/nunjucks/filters/href.test.js +0 -80
  395. package/src/server/plugins/nunjucks/filters/merge.test.js +0 -15
  396. package/src/server/plugins/nunjucks/filters/page.test.js +0 -65
  397. package/src/server/plugins/payment/helper.test.js +0 -29
  398. package/src/server/plugins/payment/service.test.js +0 -218
  399. package/src/server/plugins/postcode-lookup/service.test.js +0 -177
  400. package/src/server/postcode-lookup.test.ts +0 -64
  401. package/src/server/routes/dummy-api.test.ts +0 -97
  402. package/src/server/services/cacheService.test.ts +0 -308
  403. package/src/server/services/httpService.test.js +0 -491
  404. package/src/server/utils/file-form-service.test.js +0 -127
  405. package/src/server/utils/notify.test.ts +0 -37
  406. package/src/server/utils/secure-context/get-trust-store-certs.test.js +0 -19
  407. package/src/server/utils/utils.test.js +0 -69
@@ -1,1079 +0,0 @@
1
- import {
2
- ComponentType,
3
- type FileUploadFieldComponent,
4
- type FormMetadata
5
- } from '@defra/forms-model'
6
- import Boom from '@hapi/boom'
7
-
8
- import { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'
9
- import {
10
- FileUploadField,
11
- tempItemSchema
12
- } from '~/src/server/plugins/engine/components/FileUploadField.js'
13
- import {
14
- getAnswer,
15
- type Field
16
- } from '~/src/server/plugins/engine/components/helpers/components.js'
17
- import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
18
- import { InvalidComponentStateError } from '~/src/server/plugins/engine/pageControllers/errors.js'
19
- import {
20
- createPage,
21
- type PageControllerClass
22
- } from '~/src/server/plugins/engine/pageControllers/helpers/pages.js'
23
- import { validationOptions as opts } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'
24
- import { type Services } from '~/src/server/plugins/engine/types/index.js'
25
- import {
26
- FileStatus,
27
- UploadStatus,
28
- type FormContext,
29
- type UploadState
30
- } from '~/src/server/plugins/engine/types.js'
31
- import { type FormRequestPayload } from '~/src/server/routes/types.js'
32
- import definition from '~/test/form/definitions/file-upload-basic.js'
33
- import { getFormData, getFormState } from '~/test/helpers/component-helpers.js'
34
-
35
- describe('FileUploadField', () => {
36
- let model: FormModel
37
-
38
- const validTempState: UploadState = [
39
- {
40
- uploadId: '3075efea-e5de-476f-a0bf-9ae7ef56ca69',
41
- status: {
42
- uploadStatus: UploadStatus.pending,
43
- metadata: {
44
- retrievalKey: 'enrique.chase@defra.gov.uk'
45
- },
46
- form: {
47
- file: {
48
- fileId: 'fcb4f0f8-6862-4836-86dc-f56ff900b0ff',
49
- filename: 'SampleJPGImage_30mbmb.jpg',
50
- fileStatus: FileStatus.pending,
51
- contentLength: 30789588,
52
- errorMessage: 'The selected file has not fully uploaded'
53
- }
54
- },
55
- numberOfRejectedFiles: 0
56
- }
57
- },
58
- {
59
- uploadId: 'c7e8c8f1-fa5b-4587-966a-96066c6356bb',
60
- status: {
61
- uploadStatus: UploadStatus.ready,
62
- metadata: {
63
- retrievalKey: 'enrique.chase@defra.gov.uk'
64
- },
65
- form: {
66
- file: {
67
- fileId: 'e1d6cf98-35a7-4f97-8a28-cdd2b115d8fa',
68
- filename: 'virus.txt',
69
- fileStatus: FileStatus.rejected,
70
- contentLength: 9662,
71
- errorMessage: 'The selected file contains a virus'
72
- }
73
- },
74
- numberOfRejectedFiles: 1
75
- }
76
- },
77
- {
78
- uploadId: 'ec9f9b26-76c6-4ede-8aaa-3d4e02fe9984',
79
- status: {
80
- uploadStatus: UploadStatus.ready,
81
- metadata: {
82
- retrievalKey: 'enrique.chase@defra.gov.uk'
83
- },
84
- form: {
85
- file: {
86
- fileId: '71fb359c-dee7-4c2e-8701-239eb892765a',
87
- filename: 'SampleJPGImage_20mbmb.jpg',
88
- fileStatus: FileStatus.complete,
89
- contentLength: 21348301
90
- }
91
- },
92
- numberOfRejectedFiles: 0
93
- }
94
- }
95
- ]
96
-
97
- const validState: UploadState = [
98
- {
99
- uploadId: '3075efea-e5de-476f-a0bf-9ae7ef56ca69',
100
- status: {
101
- uploadStatus: UploadStatus.ready,
102
- metadata: {
103
- retrievalKey: 'enrique.chase@defra.gov.uk'
104
- },
105
- form: {
106
- file: {
107
- fileId: 'fcb4f0f8-6862-4836-86dc-f56ff900b0ff',
108
- filename: 'SampleJPGImage_30mbmb.jpg',
109
- fileStatus: FileStatus.complete,
110
- contentLength: 30789588
111
- }
112
- },
113
- numberOfRejectedFiles: 0
114
- }
115
- },
116
- {
117
- uploadId: 'c7e8c8f1-fa5b-4587-966a-96066c6356bb',
118
- status: {
119
- uploadStatus: UploadStatus.ready,
120
- metadata: {
121
- retrievalKey: 'enrique.chase@defra.gov.uk'
122
- },
123
- form: {
124
- file: {
125
- fileId: 'e1d6cf98-35a7-4f97-8a28-cdd2b115d8fa',
126
- filename: 'error-messages.txt',
127
- fileStatus: FileStatus.complete,
128
- contentLength: 9662
129
- }
130
- },
131
- numberOfRejectedFiles: 0
132
- }
133
- },
134
- {
135
- uploadId: 'ec9f9b26-76c6-4ede-8aaa-3d4e02fe9984',
136
- status: {
137
- uploadStatus: UploadStatus.ready,
138
- metadata: {
139
- retrievalKey: 'enrique.chase@defra.gov.uk'
140
- },
141
- form: {
142
- file: {
143
- fileId: '71fb359c-dee7-4c2e-8701-239eb892765a',
144
- filename: 'SampleJPGImage_20mbmb.jpg',
145
- fileStatus: FileStatus.complete,
146
- contentLength: 21348301
147
- }
148
- },
149
- numberOfRejectedFiles: 0
150
- }
151
- }
152
- ]
153
-
154
- beforeEach(() => {
155
- model = new FormModel(definition, {
156
- basePath: 'test'
157
- })
158
- })
159
-
160
- describe('Defaults', () => {
161
- let def: FileUploadFieldComponent
162
- let page: PageControllerClass
163
- let collection: ComponentCollection
164
- let field: Field
165
-
166
- beforeEach(() => {
167
- def = {
168
- title: 'Example file upload field',
169
- shortDescription: 'Example file upload',
170
- name: 'myComponent',
171
- type: ComponentType.FileUploadField,
172
- options: {},
173
- schema: {}
174
- } satisfies FileUploadFieldComponent
175
-
176
- page = createPage(model, definition.pages[0])
177
- collection = new ComponentCollection([def], { page, model })
178
- field = collection.fields[0]
179
- })
180
-
181
- describe('Schema', () => {
182
- it('uses component short description as label', () => {
183
- const { formSchema } = collection
184
- const { keys } = formSchema.describe()
185
-
186
- expect(keys).toHaveProperty(
187
- 'myComponent',
188
- expect.objectContaining({
189
- flags: expect.objectContaining({
190
- label: 'Example file upload'
191
- })
192
- })
193
- )
194
- })
195
-
196
- it('uses component title as label', () => {
197
- def = {
198
- title: 'Example file upload field',
199
- name: 'myComponent',
200
- type: ComponentType.FileUploadField,
201
- options: {},
202
- schema: {}
203
- } satisfies FileUploadFieldComponent
204
-
205
- page = createPage(model, definition.pages[0])
206
- collection = new ComponentCollection([def], { page, model })
207
-
208
- const { formSchema } = collection
209
- const { keys } = formSchema.describe()
210
-
211
- expect(keys).toHaveProperty(
212
- 'myComponent',
213
- expect.objectContaining({
214
- flags: expect.objectContaining({
215
- label: 'Example file upload field'
216
- })
217
- })
218
- )
219
- })
220
-
221
- it('uses component name as keys', () => {
222
- const { formSchema } = collection
223
- const { keys } = formSchema.describe()
224
-
225
- expect(field.keys).toEqual(['myComponent'])
226
- expect(field.collection).toBeUndefined()
227
-
228
- for (const key of field.keys) {
229
- expect(keys).toHaveProperty(key)
230
- }
231
- })
232
-
233
- it('is required by default', () => {
234
- const { formSchema } = collection
235
- const { keys } = formSchema.describe()
236
-
237
- expect(keys).toHaveProperty(
238
- 'myComponent',
239
- expect.objectContaining({
240
- flags: expect.objectContaining({
241
- presence: 'required'
242
- })
243
- })
244
- )
245
- })
246
-
247
- it('is optional when configured', () => {
248
- const collectionOptional = new ComponentCollection(
249
- [{ ...def, options: { required: false } }],
250
- { model }
251
- )
252
-
253
- const { formSchema } = collectionOptional
254
- const { keys } = formSchema.describe()
255
-
256
- expect(keys).toHaveProperty(
257
- 'myComponent',
258
- expect.objectContaining({
259
- flags: expect.objectContaining({
260
- presence: 'optional'
261
- })
262
- })
263
- )
264
-
265
- const result = collectionOptional.validate(getFormData())
266
- expect(result.errors).toBeUndefined()
267
- })
268
-
269
- it('accepts valid values', () => {
270
- const result1 = collection.validate(getFormData(validState))
271
- const result2 = tempItemSchema.validate(validTempState[0], opts)
272
- const result3 = tempItemSchema.validate(validTempState[1], opts)
273
- const result4 = tempItemSchema.validate(validTempState[2], opts)
274
-
275
- expect(result1.errors).toBeUndefined()
276
- expect(result2.error).toBeUndefined()
277
- expect(result3.error).toBeUndefined()
278
- expect(result4.error).toBeUndefined()
279
- })
280
-
281
- it('adds errors for empty value', () => {
282
- const result = collection.validate(getFormData())
283
-
284
- expect(result.errors).toEqual([
285
- expect.objectContaining({
286
- text: 'Select example file upload'
287
- })
288
- ])
289
- })
290
-
291
- it('adds errors for empty value with no shortDescription', () => {
292
- def = {
293
- title: 'Example file upload field',
294
- name: 'myComponent',
295
- type: ComponentType.FileUploadField,
296
- options: {},
297
- schema: {}
298
- } satisfies FileUploadFieldComponent
299
-
300
- collection = new ComponentCollection([def], { model })
301
- const result = collection.validate(getFormData())
302
-
303
- expect(result.errors).toEqual([
304
- expect.objectContaining({
305
- text: 'Select example file upload field'
306
- })
307
- ])
308
- })
309
-
310
- it('adds errors for invalid values', () => {
311
- const result1 = collection.validate(getFormData(['invalid']))
312
- const result2 = collection.validate(
313
- // @ts-expect-error - Allow invalid param for test
314
- getFormData({ unknown: 'invalid' })
315
- )
316
-
317
- expect(result1.errors).toBeTruthy()
318
- expect(result2.errors).toBeTruthy()
319
- })
320
- })
321
-
322
- describe('State', () => {
323
- it('returns text from state', () => {
324
- const state1 = getFormState(validState)
325
- const state2 = getFormState(null)
326
-
327
- const answer1 = getAnswer(field, state1)
328
- const answer2 = getAnswer(field, state2)
329
-
330
- expect(answer1).toBe('Uploaded 3 files')
331
- expect(answer2).toBe('')
332
- })
333
-
334
- it('returns payload from state', () => {
335
- const state1 = getFormState(validState)
336
- const state2 = getFormState(null)
337
-
338
- const payload1 = field.getFormDataFromState(state1)
339
- const payload2 = field.getFormDataFromState(state2)
340
-
341
- expect(payload1).toEqual(getFormData(validState))
342
- expect(payload2).toEqual(getFormData())
343
- })
344
-
345
- it('returns value from state', () => {
346
- const state1 = getFormState(validState)
347
- const state2 = getFormState(null)
348
-
349
- const value1 = field.getFormValueFromState(state1)
350
- const value2 = field.getFormValueFromState(state2)
351
-
352
- expect(value1).toBe(validState)
353
- expect(value2).toBeUndefined()
354
- })
355
-
356
- it('returns context for conditions and form submission', () => {
357
- const state1 = getFormState(validState)
358
- const state2 = getFormState(null)
359
-
360
- const value1 = field.getContextValueFromState(state1)
361
- const value2 = field.getContextValueFromState(state2)
362
-
363
- const { file: file1 } = validState[0].status.form
364
- const { file: file2 } = validState[1].status.form
365
- const { file: file3 } = validState[2].status.form
366
-
367
- expect(value1).toEqual([file1.fileId, file2.fileId, file3.fileId])
368
- expect(value2).toBeNull()
369
- })
370
-
371
- it('returns state from payload', () => {
372
- const payload1 = getFormData(validState)
373
- const payload2 = getFormData()
374
-
375
- const value1 = field.getStateFromValidForm(payload1)
376
- const value2 = field.getStateFromValidForm(payload2)
377
-
378
- expect(value1).toEqual(getFormState(validState))
379
- expect(value2).toEqual(getFormState(null))
380
- })
381
- })
382
-
383
- describe('View model', () => {
384
- it('sets Nunjucks component defaults', () => {
385
- const viewModel = field.getViewModel(getFormData(validState))
386
-
387
- expect(viewModel).toEqual(
388
- expect.objectContaining({
389
- label: { text: def.title },
390
- name: 'file', // hardcoded to 'file' for CDP
391
- id: 'myComponent',
392
- value: '', // input type=file can't have a default value
393
- upload: {
394
- count: 3,
395
- summaryList: {
396
- classes: 'govuk-summary-list--long-key',
397
- rows: [
398
- {
399
- key: {
400
- html: expect.stringContaining('SampleJPGImage_30mbmb.jpg')
401
- },
402
- value: {
403
- html: expect.stringContaining('Uploaded')
404
- },
405
- actions: {
406
- items: [
407
- {
408
- href: `/test/file-upload-component/${validState[0].status.form.file.fileId}/confirm-delete`,
409
- text: 'Remove',
410
- attributes: { id: 'myComponent__0' },
411
- classes: 'govuk-link--no-visited-state',
412
- visuallyHiddenText: 'SampleJPGImage_30mbmb.jpg'
413
- }
414
- ]
415
- }
416
- },
417
- {
418
- key: {
419
- html: expect.stringContaining('error-messages.txt')
420
- },
421
- value: {
422
- html: expect.stringContaining('Uploaded')
423
- },
424
- actions: {
425
- items: [
426
- {
427
- href: `/test/file-upload-component/${validState[1].status.form.file.fileId}/confirm-delete`,
428
- text: 'Remove',
429
- attributes: { id: 'myComponent__1' },
430
- classes: 'govuk-link--no-visited-state',
431
- visuallyHiddenText: 'error-messages.txt'
432
- }
433
- ]
434
- }
435
- },
436
- {
437
- key: {
438
- html: expect.stringContaining('SampleJPGImage_20mbmb.jpg')
439
- },
440
- value: {
441
- html: expect.stringContaining('Uploaded')
442
- },
443
- actions: {
444
- items: [
445
- {
446
- href: `/test/file-upload-component/${validState[2].status.form.file.fileId}/confirm-delete`,
447
- text: 'Remove',
448
- attributes: { id: 'myComponent__2' },
449
- classes: 'govuk-link--no-visited-state',
450
- visuallyHiddenText: 'SampleJPGImage_20mbmb.jpg'
451
- }
452
- ]
453
- }
454
- }
455
- ]
456
- }
457
- },
458
- multiple: true
459
- })
460
- )
461
- })
462
-
463
- it('sets Nunjucks component defaults (preview URL direct access)', () => {
464
- const viewModel = field.getViewModel(
465
- getFormData(validState),
466
- undefined,
467
-
468
- // Preview URL '?force'
469
- { force: '' }
470
- )
471
-
472
- expect(viewModel).toEqual(
473
- expect.objectContaining({
474
- label: { text: def.title },
475
- name: 'file', // hardcoded to 'file' for CDP
476
- id: 'myComponent',
477
- value: '', // input type=file can't have a default value
478
- upload: {
479
- count: 3,
480
- summaryList: {
481
- classes: 'govuk-summary-list--long-key',
482
- rows: [
483
- {
484
- key: {
485
- html: expect.stringContaining('SampleJPGImage_30mbmb.jpg')
486
- },
487
- value: {
488
- html: expect.stringContaining('Uploaded')
489
- },
490
- actions: {
491
- items: []
492
- }
493
- },
494
- {
495
- key: {
496
- html: expect.stringContaining('error-messages.txt')
497
- },
498
- value: {
499
- html: expect.stringContaining('Uploaded')
500
- },
501
- actions: {
502
- items: []
503
- }
504
- },
505
- {
506
- key: {
507
- html: expect.stringContaining('SampleJPGImage_20mbmb.jpg')
508
- },
509
- value: {
510
- html: expect.stringContaining('Uploaded')
511
- },
512
- actions: {
513
- items: []
514
- }
515
- }
516
- ]
517
- }
518
- }
519
- })
520
- )
521
- })
522
-
523
- it('sets Nunjucks component defaults with temp valid state', () => {
524
- const viewModel = field.getViewModel(getFormData(validTempState))
525
-
526
- expect(viewModel).toEqual(
527
- expect.objectContaining({
528
- label: { text: def.title },
529
- name: 'file', // hardcoded to 'file' for CDP
530
- id: 'myComponent',
531
- value: '', // input type=file can't have a default value
532
- upload: {
533
- count: 1,
534
- summaryList: {
535
- classes: 'govuk-summary-list--long-key',
536
- rows: [
537
- {
538
- key: {
539
- html: expect.stringContaining('SampleJPGImage_20mbmb.jpg')
540
- },
541
- value: {
542
- html: expect.stringContaining('Uploaded')
543
- },
544
- actions: {
545
- items: [
546
- {
547
- href: `/test/file-upload-component/${validState[2].status.form.file.fileId}/confirm-delete`,
548
- text: 'Remove',
549
- attributes: { id: 'myComponent__0' },
550
- classes: 'govuk-link--no-visited-state',
551
- visuallyHiddenText: 'SampleJPGImage_20mbmb.jpg'
552
- }
553
- ]
554
- }
555
- }
556
- ]
557
- }
558
- },
559
- multiple: true
560
- })
561
- )
562
- })
563
-
564
- it('sets Nunjucks component defaults with temp valid state with errors (on POST)', () => {
565
- const viewModel = field.getViewModel(getFormData(validTempState), [])
566
-
567
- expect(viewModel).toEqual(
568
- expect.objectContaining({
569
- label: { text: def.title },
570
- name: 'file', // hardcoded to 'file' for CDP
571
- id: 'myComponent',
572
- value: '', // input type=file can't have a default value
573
- upload: {
574
- count: 1,
575
- summaryList: {
576
- classes: 'govuk-summary-list--long-key',
577
- rows: [
578
- {
579
- key: {
580
- html: expect.stringContaining('SampleJPGImage_20mbmb.jpg')
581
- },
582
- value: {
583
- html: expect.stringContaining('Uploaded')
584
- },
585
- actions: {
586
- items: [
587
- {
588
- href: `/test/file-upload-component/${validState[2].status.form.file.fileId}/confirm-delete`,
589
- text: 'Remove',
590
- attributes: { id: 'myComponent__0' },
591
- classes: 'govuk-link--no-visited-state',
592
- visuallyHiddenText: 'SampleJPGImage_20mbmb.jpg'
593
- }
594
- ]
595
- }
596
- }
597
- ]
598
- }
599
- },
600
- multiple: true
601
- })
602
- )
603
- })
604
- })
605
-
606
- describe('AllPossibleErrors', () => {
607
- it('should return errors', () => {
608
- const errors = field.getAllPossibleErrors()
609
- expect(errors.baseErrors).not.toBeEmpty()
610
- expect(errors.advancedSettingsErrors).not.toBeEmpty()
611
- })
612
- })
613
- })
614
-
615
- describe('Validation', () => {
616
- describe.each([
617
- {
618
- description: 'Schema min and max',
619
- component: {
620
- title: 'Example file upload field',
621
- name: 'myComponent',
622
- type: ComponentType.FileUploadField,
623
- options: {},
624
- schema: {
625
- min: 1,
626
- max: 2
627
- }
628
- } satisfies FileUploadFieldComponent,
629
- assertions: [
630
- {
631
- input: getFormData([]),
632
- output: {
633
- value: getFormData([]),
634
- errors: [
635
- expect.objectContaining({
636
- text: 'Example file upload field must contain at least 1 items'
637
- })
638
- ]
639
- }
640
- },
641
- {
642
- input: getFormData(validState),
643
- output: {
644
- value: getFormData(validState),
645
- errors: [
646
- expect.objectContaining({
647
- text: 'Example file upload field must contain less than or equal to 2 items'
648
- })
649
- ]
650
- }
651
- }
652
- ]
653
- },
654
- {
655
- description: 'Schema default min',
656
- component: {
657
- title: 'Example file upload field',
658
- name: 'myComponent',
659
- type: ComponentType.FileUploadField,
660
- options: {},
661
- schema: {}
662
- } satisfies FileUploadFieldComponent,
663
- assertions: [
664
- {
665
- input: getFormData([]),
666
- output: {
667
- value: getFormData([]),
668
- errors: [
669
- expect.objectContaining({
670
- text: 'Example file upload field must contain at least 1 items'
671
- })
672
- ]
673
- }
674
- }
675
- ]
676
- },
677
- {
678
- description: 'Schema length',
679
- component: {
680
- title: 'Example file upload field',
681
- name: 'myComponent',
682
- type: ComponentType.FileUploadField,
683
- options: {},
684
- schema: {
685
- length: 4
686
- }
687
- } satisfies FileUploadFieldComponent,
688
- assertions: [
689
- {
690
- input: getFormData([]),
691
- output: {
692
- value: getFormData([]),
693
- errors: [
694
- expect.objectContaining({
695
- text: 'Example file upload field must contain 4 items'
696
- })
697
- ]
698
- }
699
- },
700
- {
701
- input: getFormData(validState),
702
- output: {
703
- value: getFormData(validState),
704
- errors: [
705
- expect.objectContaining({
706
- text: 'Example file upload field must contain 4 items'
707
- })
708
- ]
709
- }
710
- },
711
- {
712
- input: getFormData([...validState, ...validState]),
713
- output: {
714
- value: getFormData([...validState, ...validState]),
715
- errors: [
716
- expect.objectContaining({
717
- text: 'Example file upload field must contain 4 items'
718
- })
719
- ]
720
- }
721
- }
722
- ]
723
- },
724
- {
725
- description: 'Optional',
726
- component: {
727
- title: 'Example file upload field',
728
- name: 'myComponent',
729
- type: ComponentType.FileUploadField,
730
- options: {
731
- required: false
732
- },
733
- schema: {}
734
- } satisfies FileUploadFieldComponent,
735
- assertions: [
736
- {
737
- input: getFormData([]),
738
- output: {
739
- value: getFormData([])
740
- }
741
- },
742
- {
743
- input: getFormData(),
744
- output: {
745
- value: getFormData()
746
- }
747
- }
748
- ]
749
- },
750
- {
751
- description: 'Optional schema min and max',
752
- component: {
753
- title: 'Example file upload field',
754
- name: 'myComponent',
755
- type: ComponentType.FileUploadField,
756
- options: {
757
- required: false
758
- },
759
- schema: {
760
- min: 1,
761
- max: 2
762
- }
763
- } satisfies FileUploadFieldComponent,
764
- assertions: [
765
- {
766
- input: getFormData(),
767
- output: {
768
- value: getFormData()
769
- }
770
- },
771
- {
772
- input: getFormData([]),
773
- output: {
774
- value: getFormData([]),
775
- errors: [
776
- expect.objectContaining({
777
- text: 'Example file upload field must contain at least 1 items'
778
- })
779
- ]
780
- }
781
- },
782
- {
783
- input: getFormData(validState),
784
- output: {
785
- value: getFormData(validState),
786
- errors: [
787
- expect.objectContaining({
788
- text: 'Example file upload field must contain less than or equal to 2 items'
789
- })
790
- ]
791
- }
792
- }
793
- ]
794
- },
795
- {
796
- description: 'Optional schema length',
797
- component: {
798
- title: 'Example file upload field',
799
- name: 'myComponent',
800
- type: ComponentType.FileUploadField,
801
- options: {
802
- required: false
803
- },
804
- schema: {
805
- length: 4
806
- }
807
- } satisfies FileUploadFieldComponent,
808
- assertions: [
809
- {
810
- input: getFormData(),
811
- output: {
812
- value: getFormData()
813
- }
814
- },
815
- {
816
- input: getFormData([]),
817
- output: {
818
- value: getFormData([]),
819
- errors: [
820
- expect.objectContaining({
821
- text: 'Example file upload field must contain 4 items'
822
- })
823
- ]
824
- }
825
- },
826
- {
827
- input: getFormData(validState),
828
- output: {
829
- value: getFormData(validState),
830
- errors: [
831
- expect.objectContaining({
832
- text: 'Example file upload field must contain 4 items'
833
- })
834
- ]
835
- }
836
- },
837
- {
838
- input: getFormData([...validState, ...validState]),
839
- output: {
840
- value: getFormData([...validState, ...validState]),
841
- errors: [
842
- expect.objectContaining({
843
- text: 'Example file upload field must contain 4 items'
844
- })
845
- ]
846
- }
847
- }
848
- ]
849
- }
850
- ])('$description', ({ component: def, assertions }) => {
851
- let collection: ComponentCollection
852
-
853
- beforeEach(() => {
854
- collection = new ComponentCollection([def], { model })
855
- })
856
-
857
- it.each([...assertions])(
858
- 'validates custom example',
859
- ({ input, output }) => {
860
- const result = collection.validate(input)
861
- expect(result).toEqual(output)
862
- }
863
- )
864
- })
865
- })
866
-
867
- describe('onSubmit', () => {
868
- let fileUploadField: FileUploadField
869
- let mockRequest: FormRequestPayload
870
- let mockMetadata: FormMetadata
871
- let mockContext: FormContext
872
- let mockPersistFiles: jest.Mock
873
-
874
- beforeEach(() => {
875
- // Create a FileUploadField instance
876
- const componentDef: FileUploadFieldComponent = {
877
- name: 'fileUpload',
878
- title: 'Upload something',
879
- type: ComponentType.FileUploadField,
880
- options: {},
881
- schema: {}
882
- }
883
-
884
- const page = model.pages.find((p) => p.path === '/file-upload-component')
885
- fileUploadField = new FileUploadField(componentDef, {
886
- model,
887
- page
888
- })
889
-
890
- // Mock persistFiles
891
- mockPersistFiles = jest.fn().mockResolvedValue(undefined)
892
-
893
- // Mock request
894
- mockRequest = {
895
- app: {
896
- model: {
897
- services: {
898
- formSubmissionService: {
899
- persistFiles: mockPersistFiles
900
- }
901
- }
902
- }
903
- }
904
- } as unknown as FormRequestPayload
905
-
906
- // Mock metadata
907
- mockMetadata = {
908
- notificationEmail: 'test@example.com'
909
- } as FormMetadata
910
-
911
- // Mock context with state
912
- mockContext = {
913
- state: {
914
- fileUpload: validState
915
- }
916
- } as unknown as FormContext
917
- })
918
-
919
- afterEach(() => {
920
- jest.clearAllMocks()
921
- })
922
-
923
- it('should successfully persist files', async () => {
924
- await fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
925
-
926
- expect(mockPersistFiles).toHaveBeenCalledTimes(1)
927
- expect(mockPersistFiles).toHaveBeenCalledWith(
928
- [
929
- {
930
- fileId: 'fcb4f0f8-6862-4836-86dc-f56ff900b0ff',
931
- initiatedRetrievalKey: 'enrique.chase@defra.gov.uk'
932
- },
933
- {
934
- fileId: 'e1d6cf98-35a7-4f97-8a28-cdd2b115d8fa',
935
- initiatedRetrievalKey: 'enrique.chase@defra.gov.uk'
936
- },
937
- {
938
- fileId: '71fb359c-dee7-4c2e-8701-239eb892765a',
939
- initiatedRetrievalKey: 'enrique.chase@defra.gov.uk'
940
- }
941
- ],
942
- 'test@example.com'
943
- )
944
- })
945
-
946
- it('should fail when notificationEmail is not set', async () => {
947
- mockMetadata.notificationEmail = undefined
948
-
949
- await expect(
950
- fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
951
- ).rejects.toThrow('Unexpected missing notificationEmail in metadata')
952
- })
953
-
954
- it('should fail when notificationEmail is empty string', async () => {
955
- mockMetadata.notificationEmail = ''
956
-
957
- await expect(
958
- fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
959
- ).rejects.toThrow('Unexpected missing notificationEmail in metadata')
960
- })
961
-
962
- it('should not call persistFiles when no files in state', async () => {
963
- mockContext.state = {}
964
-
965
- await fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
966
-
967
- expect(mockPersistFiles).not.toHaveBeenCalled()
968
- })
969
-
970
- it('should not call persistFiles when empty array in state', async () => {
971
- mockContext.state = { fileUpload: [] }
972
-
973
- await fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
974
-
975
- expect(mockPersistFiles).not.toHaveBeenCalled()
976
- })
977
-
978
- it('should throw Error when formSubmissionService is not available', async () => {
979
- if (!mockRequest.app.model) {
980
- throw new Error('Invalid test setup')
981
- }
982
-
983
- mockRequest.app.model.services = {} as unknown as Services
984
-
985
- await expect(
986
- fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
987
- ).rejects.toThrow('No form submission service available in app model')
988
- })
989
-
990
- it('should throw InvalidComponentStateError when persistFiles throws 403 Forbidden', async () => {
991
- const forbiddenError = Boom.forbidden('Invalid retrieval key')
992
- mockPersistFiles.mockRejectedValue(forbiddenError)
993
-
994
- await expect(
995
- fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
996
- ).rejects.toThrow(InvalidComponentStateError)
997
-
998
- const error = await fileUploadField
999
- .onSubmit(mockRequest, mockMetadata, mockContext)
1000
- .catch((e: unknown) => e)
1001
-
1002
- expect(error).toBeInstanceOf(InvalidComponentStateError)
1003
- expect((error as InvalidComponentStateError).component).toBe(
1004
- fileUploadField
1005
- )
1006
- expect((error as InvalidComponentStateError).userMessage).toBe(
1007
- 'There was a problem with your uploaded files. Re-upload them before submitting the form again.'
1008
- )
1009
- })
1010
-
1011
- it('should throw InvalidComponentStateError when persistFiles throws 410 Gone', async () => {
1012
- const goneError = Boom.resourceGone('File has expired')
1013
- mockPersistFiles.mockRejectedValue(goneError)
1014
-
1015
- await expect(
1016
- fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
1017
- ).rejects.toThrow(InvalidComponentStateError)
1018
-
1019
- const error = await fileUploadField
1020
- .onSubmit(mockRequest, mockMetadata, mockContext)
1021
- .catch((e: unknown) => e)
1022
-
1023
- expect(error).toBeInstanceOf(InvalidComponentStateError)
1024
- expect((error as InvalidComponentStateError).component).toBe(
1025
- fileUploadField
1026
- )
1027
- expect((error as InvalidComponentStateError).userMessage).toBe(
1028
- 'There was a problem with your uploaded files. Re-upload them before submitting the form again.'
1029
- )
1030
- })
1031
-
1032
- it('should throw InvalidComponentStateError when persistFiles throws 404 Not Found', async () => {
1033
- const notFoundError = Boom.notFound('File not found')
1034
- mockPersistFiles.mockRejectedValue(notFoundError)
1035
-
1036
- await expect(
1037
- fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
1038
- ).rejects.toThrow(InvalidComponentStateError)
1039
-
1040
- const error = await fileUploadField
1041
- .onSubmit(mockRequest, mockMetadata, mockContext)
1042
- .catch((e: unknown) => e)
1043
-
1044
- expect(error).toBeInstanceOf(InvalidComponentStateError)
1045
- expect((error as InvalidComponentStateError).component).toBe(
1046
- fileUploadField
1047
- )
1048
- expect((error as InvalidComponentStateError).userMessage).toBe(
1049
- 'There was a problem with your uploaded files. Re-upload them before submitting the form again.'
1050
- )
1051
- })
1052
-
1053
- it('should re-throw other Boom errors without wrapping', async () => {
1054
- const serverError = Boom.internal('Internal server error')
1055
- mockPersistFiles.mockRejectedValue(serverError)
1056
-
1057
- await expect(
1058
- fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
1059
- ).rejects.toThrow(serverError)
1060
-
1061
- await expect(
1062
- fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
1063
- ).rejects.not.toThrow(InvalidComponentStateError)
1064
- })
1065
-
1066
- it('should re-throw non-Boom errors without wrapping', async () => {
1067
- const genericError = new Error('Something went wrong')
1068
- mockPersistFiles.mockRejectedValue(genericError)
1069
-
1070
- await expect(
1071
- fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
1072
- ).rejects.toThrow(genericError)
1073
-
1074
- await expect(
1075
- fileUploadField.onSubmit(mockRequest, mockMetadata, mockContext)
1076
- ).rejects.not.toThrow(InvalidComponentStateError)
1077
- })
1078
- })
1079
- })