@defra/forms-engine-plugin 4.7.2-alpha → 4.7.3

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 (402) hide show
  1. package/.server/client/javascripts/geospatial-map.d.ts +6 -6
  2. package/.server/client/javascripts/geospatial-map.js +3 -3
  3. package/.server/client/javascripts/location-map.d.ts +1 -1
  4. package/.server/client/javascripts/location-map.js +1 -1
  5. package/.server/client/javascripts/map.d.ts +1 -1
  6. package/.server/client/javascripts/map.js +1 -1
  7. package/.server/client/javascripts/shared.d.ts +7 -7
  8. package/.server/server/index.d.ts +1 -1
  9. package/.server/server/plugins/crumb.d.ts +1 -1
  10. package/.server/server/plugins/engine/beta/form-context.d.ts +6 -6
  11. package/.server/server/plugins/engine/components/AutocompleteField.d.ts +4 -4
  12. package/.server/server/plugins/engine/components/CheckboxesField.d.ts +2 -2
  13. package/.server/server/plugins/engine/components/CheckboxesField.js +2 -2
  14. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
  15. package/.server/server/plugins/engine/components/ComponentBase.d.ts +5 -5
  16. package/.server/server/plugins/engine/components/ComponentCollection.d.ts +8 -8
  17. package/.server/server/plugins/engine/components/DatePartsField.d.ts +11 -11
  18. package/.server/server/plugins/engine/components/DeclarationField.d.ts +3 -3
  19. package/.server/server/plugins/engine/components/Details.d.ts +1 -1
  20. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +22 -22
  21. package/.server/server/plugins/engine/components/EmailAddressField.d.ts +4 -4
  22. package/.server/server/plugins/engine/components/FileUploadField.d.ts +3 -3
  23. package/.server/server/plugins/engine/components/FormComponent.d.ts +10 -10
  24. package/.server/server/plugins/engine/components/GeospatialField.d.ts +6 -6
  25. package/.server/server/plugins/engine/components/HiddenField.d.ts +2 -2
  26. package/.server/server/plugins/engine/components/Html.d.ts +1 -1
  27. package/.server/server/plugins/engine/components/InsetText.d.ts +1 -1
  28. package/.server/server/plugins/engine/components/LatLongField.d.ts +22 -22
  29. package/.server/server/plugins/engine/components/List.d.ts +8 -8
  30. package/.server/server/plugins/engine/components/ListFormComponent.d.ts +10 -10
  31. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +6 -6
  32. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +14 -14
  33. package/.server/server/plugins/engine/components/Markdown.d.ts +1 -1
  34. package/.server/server/plugins/engine/components/MonthYearField.d.ts +11 -11
  35. package/.server/server/plugins/engine/components/MultilineTextField.d.ts +5 -5
  36. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +1 -1
  37. package/.server/server/plugins/engine/components/NumberField.d.ts +3 -3
  38. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +1 -1
  39. package/.server/server/plugins/engine/components/PaymentField.d.ts +12 -12
  40. package/.server/server/plugins/engine/components/RadiosField.d.ts +1 -1
  41. package/.server/server/plugins/engine/components/SelectField.d.ts +4 -4
  42. package/.server/server/plugins/engine/components/SelectionControlField.d.ts +10 -10
  43. package/.server/server/plugins/engine/components/TelephoneNumberField.d.ts +4 -4
  44. package/.server/server/plugins/engine/components/TextField.d.ts +2 -2
  45. package/.server/server/plugins/engine/components/UkAddressField.d.ts +11 -11
  46. package/.server/server/plugins/engine/components/YesNoField.d.ts +2 -2
  47. package/.server/server/plugins/engine/components/helpers/__stubs__/geospatial.d.ts +1 -1
  48. package/.server/server/plugins/engine/components/helpers/components.d.ts +5 -5
  49. package/.server/server/plugins/engine/components/helpers/geospatial.d.ts +1 -1
  50. package/.server/server/plugins/engine/components/index.d.ts +27 -27
  51. package/.server/server/plugins/engine/components/types.d.ts +1 -1
  52. package/.server/server/plugins/engine/configureEnginePlugin.d.ts +4 -4
  53. package/.server/server/plugins/engine/date-helper.d.ts +1 -1
  54. package/.server/server/plugins/engine/helpers.d.ts +8 -8
  55. package/.server/server/plugins/engine/index.d.ts +5 -5
  56. package/.server/server/plugins/engine/models/FormModel.d.ts +6 -6
  57. package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +6 -6
  58. package/.server/server/plugins/engine/models/index.d.ts +2 -2
  59. package/.server/server/plugins/engine/models/types.d.ts +4 -4
  60. package/.server/server/plugins/engine/options.d.ts +1 -1
  61. package/.server/server/plugins/engine/options.js +1 -1
  62. package/.server/server/plugins/engine/options.test.js +1 -1
  63. package/.server/server/plugins/engine/outputFormatters/adapter/v1.d.ts +4 -4
  64. package/.server/server/plugins/engine/outputFormatters/human/v1.d.ts +4 -4
  65. package/.server/server/plugins/engine/outputFormatters/index.d.ts +5 -5
  66. package/.server/server/plugins/engine/outputFormatters/machine/v1.d.ts +4 -4
  67. package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +4 -4
  68. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +8 -8
  69. package/.server/server/plugins/engine/pageControllers/PageController.d.ts +6 -6
  70. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +8 -8
  71. package/.server/server/plugins/engine/pageControllers/RepeatPageController.d.ts +5 -5
  72. package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +4 -4
  73. package/.server/server/plugins/engine/pageControllers/StatusPageController.d.ts +4 -4
  74. package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +5 -5
  75. package/.server/server/plugins/engine/pageControllers/TerminalPageController.d.ts +3 -3
  76. package/.server/server/plugins/engine/pageControllers/__stubs__/request.d.ts +2 -2
  77. package/.server/server/plugins/engine/pageControllers/errors.d.ts +1 -1
  78. package/.server/server/plugins/engine/pageControllers/helpers/pages.d.ts +2 -2
  79. package/.server/server/plugins/engine/pageControllers/helpers/state.d.ts +5 -5
  80. package/.server/server/plugins/engine/pageControllers/helpers/state.js +1 -1
  81. package/.server/server/plugins/engine/pageControllers/helpers/state.js.map +1 -1
  82. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +1 -1
  83. package/.server/server/plugins/engine/pageControllers/index.d.ts +7 -7
  84. package/.server/server/plugins/engine/plugin.d.ts +1 -1
  85. package/.server/server/plugins/engine/routes/file-upload.d.ts +1 -1
  86. package/.server/server/plugins/engine/routes/index.d.ts +3 -3
  87. package/.server/server/plugins/engine/routes/payment-helper.d.ts +3 -3
  88. package/.server/server/plugins/engine/routes/payment-helper.js +2 -2
  89. package/.server/server/plugins/engine/routes/payment.js +5 -5
  90. package/.server/server/plugins/engine/routes/payment.test.js +1 -1
  91. package/.server/server/plugins/engine/routes/questions.d.ts +2 -2
  92. package/.server/server/plugins/engine/routes/repeaters/item-delete.d.ts +2 -2
  93. package/.server/server/plugins/engine/routes/repeaters/summary.d.ts +2 -2
  94. package/.server/server/plugins/engine/services/index.d.ts +3 -3
  95. package/.server/server/plugins/engine/services/notifyService.d.ts +4 -4
  96. package/.server/server/plugins/engine/services/uploadService.d.ts +2 -2
  97. package/.server/server/plugins/engine/services/uploadService.js +1 -1
  98. package/.server/server/plugins/engine/types/index.d.ts +10 -10
  99. package/.server/server/plugins/engine/types/schema.d.ts +1 -1
  100. package/.server/server/plugins/engine/types.d.ts +25 -16
  101. package/.server/server/plugins/engine/types.js.map +1 -1
  102. package/.server/server/plugins/engine/validationHelpers.d.ts +2 -2
  103. package/.server/server/plugins/engine/vision.d.ts +1 -1
  104. package/.server/server/plugins/map/index.d.ts +1 -1
  105. package/.server/server/plugins/map/index.js +1 -1
  106. package/.server/server/plugins/map/routes/get-os-token.d.ts +11 -1
  107. package/.server/server/plugins/map/routes/get-os-token.js +12 -2
  108. package/.server/server/plugins/map/routes/get-os-token.js.map +1 -1
  109. package/.server/server/plugins/map/routes/index.d.ts +4 -4
  110. package/.server/server/plugins/map/routes/index.js +3 -2
  111. package/.server/server/plugins/map/routes/index.js.map +1 -1
  112. package/.server/server/plugins/map/service.d.ts +1 -1
  113. package/.server/server/plugins/map/service.js +5 -2
  114. package/.server/server/plugins/map/service.js.map +1 -1
  115. package/.server/server/plugins/map/test/__stubs__/find.d.ts +1 -1
  116. package/.server/server/plugins/map/test/__stubs__/find.js +1 -1
  117. package/.server/server/plugins/nunjucks/context.d.ts +2 -2
  118. package/.server/server/plugins/nunjucks/context.js +2 -2
  119. package/.server/server/plugins/nunjucks/context.test.js +1 -1
  120. package/.server/server/plugins/nunjucks/enviroment.test.js +1 -1
  121. package/.server/server/plugins/nunjucks/environment.d.ts +3 -3
  122. package/.server/server/plugins/nunjucks/environment.js +3 -3
  123. package/.server/server/plugins/nunjucks/filters/answer.d.ts +1 -1
  124. package/.server/server/plugins/nunjucks/filters/answer.js +2 -2
  125. package/.server/server/plugins/nunjucks/filters/answer.test.js +1 -1
  126. package/.server/server/plugins/nunjucks/filters/evaluate.d.ts +1 -1
  127. package/.server/server/plugins/nunjucks/filters/evaluate.js +1 -1
  128. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  129. package/.server/server/plugins/nunjucks/filters/field.js +1 -1
  130. package/.server/server/plugins/nunjucks/filters/field.test.js +1 -1
  131. package/.server/server/plugins/nunjucks/filters/href.d.ts +1 -1
  132. package/.server/server/plugins/nunjucks/filters/href.js +1 -1
  133. package/.server/server/plugins/nunjucks/filters/href.test.js +1 -1
  134. package/.server/server/plugins/nunjucks/filters/index.d.ts +8 -8
  135. package/.server/server/plugins/nunjucks/filters/page.d.ts +1 -1
  136. package/.server/server/plugins/nunjucks/filters/page.js +1 -1
  137. package/.server/server/plugins/nunjucks/filters/page.test.js +1 -1
  138. package/.server/server/plugins/nunjucks/index.d.ts +3 -3
  139. package/.server/server/plugins/nunjucks/render.d.ts +2 -2
  140. package/.server/server/plugins/nunjucks/render.js +1 -1
  141. package/.server/server/plugins/nunjucks/types.d.ts +1 -1
  142. package/.server/server/plugins/nunjucks/types.js +1 -1
  143. package/.server/server/plugins/payment/helper.d.ts +2 -2
  144. package/.server/server/plugins/payment/helper.js +1 -1
  145. package/.server/server/plugins/payment/service.d.ts +3 -3
  146. package/.server/server/plugins/payment/service.js +1 -1
  147. package/.server/server/plugins/postcode-lookup/index.d.ts +1 -1
  148. package/.server/server/plugins/postcode-lookup/index.js +1 -1
  149. package/.server/server/plugins/postcode-lookup/models/index.d.ts +6 -6
  150. package/.server/server/plugins/postcode-lookup/models/index.js +1 -1
  151. package/.server/server/plugins/postcode-lookup/routes/index.d.ts +6 -6
  152. package/.server/server/plugins/postcode-lookup/routes/index.js +15 -15
  153. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  154. package/.server/server/plugins/postcode-lookup/service.d.ts +1 -1
  155. package/.server/server/plugins/postcode-lookup/service.js +5 -2
  156. package/.server/server/plugins/postcode-lookup/service.js.map +1 -1
  157. package/.server/server/plugins/postcode-lookup/types.js +1 -1
  158. package/.server/server/routes/index.d.ts +2 -2
  159. package/.server/server/routes/types.d.ts +1 -1
  160. package/.server/server/schemas/index.d.ts +2 -2
  161. package/.server/server/services/cacheService.d.ts +8 -8
  162. package/.server/server/services/cacheService.js +2 -5
  163. package/.server/server/services/cacheService.js.map +1 -1
  164. package/.server/server/services/httpService.test.js +1 -1
  165. package/.server/server/services/index.d.ts +1 -1
  166. package/.server/server/types.d.ts +7 -7
  167. package/.server/server/utils/file-form-service.d.ts +2 -2
  168. package/.server/server/utils/file-form-service.js +1 -1
  169. package/package.json +8 -4
  170. package/src/client/javascripts/application.js +1 -1
  171. package/src/client/javascripts/geospatial-map.js +4 -4
  172. package/src/client/javascripts/location-map.js +2 -2
  173. package/src/client/javascripts/map.js +3 -3
  174. package/src/client/javascripts/shared.js +7 -7
  175. package/src/index.ts +3 -3
  176. package/src/server/common/helpers/logging/logger-options.ts +1 -1
  177. package/src/server/common/helpers/logging/logger.ts +1 -1
  178. package/src/server/common/helpers/logging/request-logger.ts +1 -1
  179. package/src/server/common/helpers/logging/request-tracing.js +1 -1
  180. package/src/server/common/helpers/redis-client.js +2 -2
  181. package/src/server/index.ts +13 -13
  182. package/src/server/plugins/crumb.ts +2 -2
  183. package/src/server/plugins/engine/beta/form-context.ts +9 -9
  184. package/src/server/plugins/engine/components/AutocompleteField.ts +3 -3
  185. package/src/server/plugins/engine/components/CheckboxesField.ts +7 -8
  186. package/src/server/plugins/engine/components/ComponentBase.ts +5 -5
  187. package/src/server/plugins/engine/components/ComponentCollection.ts +9 -9
  188. package/src/server/plugins/engine/components/DatePartsField.ts +8 -8
  189. package/src/server/plugins/engine/components/DeclarationField.ts +3 -3
  190. package/src/server/plugins/engine/components/Details.ts +1 -1
  191. package/src/server/plugins/engine/components/EastingNorthingField.ts +9 -9
  192. package/src/server/plugins/engine/components/EmailAddressField.ts +3 -3
  193. package/src/server/plugins/engine/components/FileUploadField.ts +6 -6
  194. package/src/server/plugins/engine/components/FormComponent.ts +4 -4
  195. package/src/server/plugins/engine/components/GeospatialField.ts +5 -5
  196. package/src/server/plugins/engine/components/HiddenField.ts +4 -4
  197. package/src/server/plugins/engine/components/Html.ts +1 -1
  198. package/src/server/plugins/engine/components/InsetText.ts +1 -1
  199. package/src/server/plugins/engine/components/LatLongField.ts +9 -9
  200. package/src/server/plugins/engine/components/List.ts +2 -2
  201. package/src/server/plugins/engine/components/ListFormComponent.ts +4 -4
  202. package/src/server/plugins/engine/components/LocationFieldBase.ts +5 -5
  203. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +5 -5
  204. package/src/server/plugins/engine/components/Markdown.ts +1 -1
  205. package/src/server/plugins/engine/components/MonthYearField.ts +8 -8
  206. package/src/server/plugins/engine/components/MultilineTextField.ts +4 -4
  207. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +2 -2
  208. package/src/server/plugins/engine/components/NumberField.ts +3 -3
  209. package/src/server/plugins/engine/components/OsGridRefField.ts +2 -2
  210. package/src/server/plugins/engine/components/PaymentField.ts +8 -8
  211. package/src/server/plugins/engine/components/RadiosField.ts +1 -1
  212. package/src/server/plugins/engine/components/SelectField.ts +2 -2
  213. package/src/server/plugins/engine/components/SelectionControlField.ts +4 -4
  214. package/src/server/plugins/engine/components/TelephoneNumberField.ts +4 -4
  215. package/src/server/plugins/engine/components/TextField.ts +3 -3
  216. package/src/server/plugins/engine/components/UkAddressField.ts +7 -7
  217. package/src/server/plugins/engine/components/YesNoField.ts +5 -5
  218. package/src/server/plugins/engine/components/helpers/__stubs__/geospatial.ts +1 -1
  219. package/src/server/plugins/engine/components/helpers/components.ts +8 -8
  220. package/src/server/plugins/engine/components/helpers/geospatial.ts +1 -1
  221. package/src/server/plugins/engine/components/index.ts +27 -27
  222. package/src/server/plugins/engine/components/types.ts +1 -1
  223. package/src/server/plugins/engine/configureEnginePlugin.ts +10 -10
  224. package/src/server/plugins/engine/date-helper.ts +1 -1
  225. package/src/server/plugins/engine/helpers.ts +8 -8
  226. package/src/server/plugins/engine/index.ts +8 -8
  227. package/src/server/plugins/engine/models/FormModel.ts +15 -15
  228. package/src/server/plugins/engine/models/SummaryViewModel.ts +10 -10
  229. package/src/server/plugins/engine/models/index.ts +2 -2
  230. package/src/server/plugins/engine/models/types.ts +4 -4
  231. package/src/server/plugins/engine/options.js +3 -3
  232. package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +6 -6
  233. package/src/server/plugins/engine/outputFormatters/human/v1.ts +9 -9
  234. package/src/server/plugins/engine/outputFormatters/index.ts +8 -8
  235. package/src/server/plugins/engine/outputFormatters/machine/v1.ts +7 -7
  236. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +6 -6
  237. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +9 -9
  238. package/src/server/plugins/engine/pageControllers/PageController.ts +7 -7
  239. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +13 -13
  240. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +6 -6
  241. package/src/server/plugins/engine/pageControllers/StartPageController.ts +3 -3
  242. package/src/server/plugins/engine/pageControllers/StatusPageController.ts +5 -5
  243. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +12 -12
  244. package/src/server/plugins/engine/pageControllers/TerminalPageController.ts +3 -3
  245. package/src/server/plugins/engine/pageControllers/__stubs__/request.ts +3 -3
  246. package/src/server/plugins/engine/pageControllers/__stubs__/server.ts +2 -2
  247. package/src/server/plugins/engine/pageControllers/errors.ts +1 -1
  248. package/src/server/plugins/engine/pageControllers/helpers/pages.ts +2 -2
  249. package/src/server/plugins/engine/pageControllers/helpers/state.ts +9 -9
  250. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +5 -5
  251. package/src/server/plugins/engine/pageControllers/index.ts +7 -7
  252. package/src/server/plugins/engine/pageControllers/validationOptions.ts +1 -1
  253. package/src/server/plugins/engine/plugin.ts +14 -14
  254. package/src/server/plugins/engine/routes/file-upload.ts +2 -2
  255. package/src/server/plugins/engine/routes/index.ts +10 -10
  256. package/src/server/plugins/engine/routes/payment-helper.js +4 -4
  257. package/src/server/plugins/engine/routes/payment.js +9 -9
  258. package/src/server/plugins/engine/routes/questions.ts +10 -10
  259. package/src/server/plugins/engine/routes/repeaters/item-delete.ts +6 -6
  260. package/src/server/plugins/engine/routes/repeaters/summary.ts +5 -5
  261. package/src/server/plugins/engine/services/formSubmissionService.js +2 -2
  262. package/src/server/plugins/engine/services/index.js +3 -3
  263. package/src/server/plugins/engine/services/localFormsService.js +2 -2
  264. package/src/server/plugins/engine/services/notifyService.ts +9 -9
  265. package/src/server/plugins/engine/services/uploadService.js +3 -3
  266. package/src/server/plugins/engine/types/index.ts +10 -10
  267. package/src/server/plugins/engine/types/schema.ts +2 -2
  268. package/src/server/plugins/engine/types.ts +22 -17
  269. package/src/server/plugins/engine/validationHelpers.ts +3 -3
  270. package/src/server/plugins/engine/vision.ts +3 -3
  271. package/src/server/plugins/map/index.js +2 -2
  272. package/src/server/plugins/map/routes/get-os-token.js +15 -3
  273. package/src/server/plugins/map/routes/index.js +7 -5
  274. package/src/server/plugins/map/service.js +7 -4
  275. package/src/server/plugins/map/test/__stubs__/find.js +1 -1
  276. package/src/server/plugins/nunjucks/context.js +5 -5
  277. package/src/server/plugins/nunjucks/environment.js +6 -6
  278. package/src/server/plugins/nunjucks/filters/answer.js +3 -3
  279. package/src/server/plugins/nunjucks/filters/evaluate.js +2 -2
  280. package/src/server/plugins/nunjucks/filters/field.js +1 -1
  281. package/src/server/plugins/nunjucks/filters/href.js +2 -2
  282. package/src/server/plugins/nunjucks/filters/index.js +8 -8
  283. package/src/server/plugins/nunjucks/filters/page.js +1 -1
  284. package/src/server/plugins/nunjucks/index.js +3 -3
  285. package/src/server/plugins/nunjucks/plugin.js +3 -3
  286. package/src/server/plugins/nunjucks/render.js +2 -2
  287. package/src/server/plugins/nunjucks/types.js +1 -1
  288. package/src/server/plugins/payment/helper.js +2 -2
  289. package/src/server/plugins/payment/service.js +4 -4
  290. package/src/server/plugins/postcode-lookup/index.js +2 -2
  291. package/src/server/plugins/postcode-lookup/models/index.js +3 -3
  292. package/src/server/plugins/postcode-lookup/routes/index.js +24 -14
  293. package/src/server/plugins/postcode-lookup/service.js +7 -4
  294. package/src/server/plugins/postcode-lookup/types.js +1 -1
  295. package/src/server/plugins/session.ts +1 -1
  296. package/src/server/routes/index.ts +2 -2
  297. package/src/server/routes/public.ts +1 -1
  298. package/src/server/routes/types.ts +1 -1
  299. package/src/server/schemas/index.ts +2 -2
  300. package/src/server/secure-context.js +1 -1
  301. package/src/server/services/cacheService.ts +13 -18
  302. package/src/server/services/httpService.ts +1 -1
  303. package/src/server/services/index.ts +1 -1
  304. package/src/server/types.ts +7 -7
  305. package/src/server/utils/notify.ts +2 -2
  306. package/src/server/utils/utils.js +1 -1
  307. package/src/typings/hapi/index.d.ts +4 -4
  308. package/src/typings/joi/index.d.ts +1 -1
  309. package/src/server/common/helpers/logging/logger-options.test.ts +0 -50
  310. package/src/server/index.test.ts +0 -644
  311. package/src/server/plugins/engine/beta/form-context.test.ts +0 -373
  312. package/src/server/plugins/engine/components/AutocompleteField.test.ts +0 -362
  313. package/src/server/plugins/engine/components/CheckboxesField.test.ts +0 -486
  314. package/src/server/plugins/engine/components/DatePartsField.test.ts +0 -927
  315. package/src/server/plugins/engine/components/DeclarationField.test.ts +0 -560
  316. package/src/server/plugins/engine/components/Details.test.ts +0 -49
  317. package/src/server/plugins/engine/components/EastingNorthingField.test.ts +0 -727
  318. package/src/server/plugins/engine/components/EmailAddressField.test.ts +0 -445
  319. package/src/server/plugins/engine/components/FileUploadField.test.ts +0 -1079
  320. package/src/server/plugins/engine/components/GeospatialField.test.ts +0 -380
  321. package/src/server/plugins/engine/components/HiddenField.test.ts +0 -188
  322. package/src/server/plugins/engine/components/Html.test.ts +0 -48
  323. package/src/server/plugins/engine/components/InsetText.test.ts +0 -48
  324. package/src/server/plugins/engine/components/LatLongField.test.ts +0 -898
  325. package/src/server/plugins/engine/components/List.test.ts +0 -79
  326. package/src/server/plugins/engine/components/LocationFieldBase.test.ts +0 -253
  327. package/src/server/plugins/engine/components/LocationFieldHelpers.test.ts +0 -743
  328. package/src/server/plugins/engine/components/Markdown.test.ts +0 -48
  329. package/src/server/plugins/engine/components/MonthYearField.test.ts +0 -617
  330. package/src/server/plugins/engine/components/MultilineTextField.test.ts +0 -647
  331. package/src/server/plugins/engine/components/NationalGridFieldNumberField.test.ts +0 -449
  332. package/src/server/plugins/engine/components/NumberField.test.ts +0 -723
  333. package/src/server/plugins/engine/components/OsGridRefField.test.ts +0 -460
  334. package/src/server/plugins/engine/components/PaymentField.test.ts +0 -745
  335. package/src/server/plugins/engine/components/RadiosField.test.ts +0 -297
  336. package/src/server/plugins/engine/components/SelectField.test.ts +0 -289
  337. package/src/server/plugins/engine/components/TelephoneNumberField.test.ts +0 -384
  338. package/src/server/plugins/engine/components/TextField.test.ts +0 -521
  339. package/src/server/plugins/engine/components/UkAddressField.test.ts +0 -806
  340. package/src/server/plugins/engine/components/YesNoField.test.ts +0 -256
  341. package/src/server/plugins/engine/components/helpers/components.test.ts +0 -399
  342. package/src/server/plugins/engine/components/helpers/geospatial.test.js +0 -55
  343. package/src/server/plugins/engine/components/helpers/helpers.test.ts +0 -219
  344. package/src/server/plugins/engine/date-helper.test.ts +0 -47
  345. package/src/server/plugins/engine/helpers.test.ts +0 -868
  346. package/src/server/plugins/engine/models/FormModel.test.ts +0 -725
  347. package/src/server/plugins/engine/models/SummaryViewModel.test.ts +0 -472
  348. package/src/server/plugins/engine/options.test.js +0 -63
  349. package/src/server/plugins/engine/outputFormatters/adapter/v1.location.test.ts +0 -356
  350. package/src/server/plugins/engine/outputFormatters/adapter/v1.test.ts +0 -871
  351. package/src/server/plugins/engine/outputFormatters/human/v1.payment.test.ts +0 -147
  352. package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +0 -145
  353. package/src/server/plugins/engine/outputFormatters/index.test.ts +0 -17
  354. package/src/server/plugins/engine/outputFormatters/machine/v1.test.ts +0 -268
  355. package/src/server/plugins/engine/outputFormatters/machine/v2.location.test.ts +0 -341
  356. package/src/server/plugins/engine/outputFormatters/machine/v2.payment.test.ts +0 -115
  357. package/src/server/plugins/engine/outputFormatters/machine/v2.test.ts +0 -311
  358. package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +0 -1372
  359. package/src/server/plugins/engine/pageControllers/PageController.test.ts +0 -246
  360. package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +0 -1686
  361. package/src/server/plugins/engine/pageControllers/RepeatPageController.test.ts +0 -279
  362. package/src/server/plugins/engine/pageControllers/StartPageController.test.ts +0 -32
  363. package/src/server/plugins/engine/pageControllers/StatusPageController.test.ts +0 -32
  364. package/src/server/plugins/engine/pageControllers/SummaryPageController.test.ts +0 -89
  365. package/src/server/plugins/engine/pageControllers/TerminalController.test.ts +0 -37
  366. package/src/server/plugins/engine/pageControllers/errors.test.ts +0 -78
  367. package/src/server/plugins/engine/pageControllers/helpers/helpers.test.ts +0 -182
  368. package/src/server/plugins/engine/pageControllers/helpers/state.test.ts +0 -359
  369. package/src/server/plugins/engine/pageControllers/helpers/submission.test.ts +0 -373
  370. package/src/server/plugins/engine/referenceNumbers.test.ts +0 -74
  371. package/src/server/plugins/engine/routes/index.test.ts +0 -332
  372. package/src/server/plugins/engine/routes/payment-helper.test.js +0 -136
  373. package/src/server/plugins/engine/routes/payment.test.js +0 -180
  374. package/src/server/plugins/engine/routes/questions.test.ts +0 -502
  375. package/src/server/plugins/engine/routes/repeaters/item-delete.test.ts +0 -83
  376. package/src/server/plugins/engine/routes/repeaters/summary.test.ts +0 -75
  377. package/src/server/plugins/engine/services/formsService.test.js +0 -26
  378. package/src/server/plugins/engine/services/notifyService.test.ts +0 -310
  379. package/src/server/plugins/engine/types/schema.test.ts +0 -234
  380. package/src/server/plugins/engine/views/components/service-banner/template.test.js +0 -43
  381. package/src/server/plugins/engine/views/components/tag-env/template.test.js +0 -28
  382. package/src/server/plugins/engine/views/partials/preview-banner.test.js +0 -122
  383. package/src/server/plugins/map/routes/get-os-token.test.js +0 -55
  384. package/src/server/plugins/map/service.test.js +0 -144
  385. package/src/server/plugins/nunjucks/context.test.js +0 -109
  386. package/src/server/plugins/nunjucks/enviroment.test.js +0 -207
  387. package/src/server/plugins/nunjucks/filters/answer.test.js +0 -92
  388. package/src/server/plugins/nunjucks/filters/field.test.js +0 -75
  389. package/src/server/plugins/nunjucks/filters/href.test.js +0 -80
  390. package/src/server/plugins/nunjucks/filters/merge.test.js +0 -15
  391. package/src/server/plugins/nunjucks/filters/page.test.js +0 -65
  392. package/src/server/plugins/payment/helper.test.js +0 -29
  393. package/src/server/plugins/payment/service.test.js +0 -218
  394. package/src/server/plugins/postcode-lookup/service.test.js +0 -177
  395. package/src/server/postcode-lookup.test.ts +0 -64
  396. package/src/server/routes/dummy-api.test.ts +0 -97
  397. package/src/server/services/cacheService.test.ts +0 -308
  398. package/src/server/services/httpService.test.js +0 -491
  399. package/src/server/utils/file-form-service.test.js +0 -127
  400. package/src/server/utils/notify.test.ts +0 -37
  401. package/src/server/utils/secure-context/get-trust-store-certs.test.js +0 -19
  402. package/src/server/utils/utils.test.js +0 -69
@@ -1,1372 +0,0 @@
1
- /* eslint-disable @typescript-eslint/dot-notation */
2
- import { ComponentType, type ComponentDef } from '@defra/forms-model'
3
- import Boom from '@hapi/boom'
4
- import { type ValidationErrorItem, type ValidationResult } from 'joi'
5
-
6
- import {
7
- FileUploadField,
8
- tempItemSchema
9
- } from '~/src/server/plugins/engine/components/FileUploadField.js'
10
- import { TextField } from '~/src/server/plugins/engine/components/TextField.js'
11
- import {
12
- getCacheService,
13
- getError
14
- } from '~/src/server/plugins/engine/helpers.js'
15
- import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
16
- import {
17
- FileUploadPageController,
18
- prepareStatus
19
- } from '~/src/server/plugins/engine/pageControllers/FileUploadPageController.js'
20
- import { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'
21
- import { serverWithSaveAndExit } from '~/src/server/plugins/engine/pageControllers/__stubs__/server.js'
22
- import * as pageHelpers from '~/src/server/plugins/engine/pageControllers/helpers/index.js'
23
- import { getFormMetadata } from '~/src/server/plugins/engine/services/formsService.js'
24
- import * as uploadService from '~/src/server/plugins/engine/services/uploadService.js'
25
- import {
26
- FileStatus,
27
- UploadStatus,
28
- type FeaturedFormPageViewModel,
29
- type FormContext,
30
- type FormContextRequest,
31
- type FormPayloadParams,
32
- type FormSubmissionState,
33
- type UploadStatusFileResponse,
34
- type UploadStatusResponse
35
- } from '~/src/server/plugins/engine/types.js'
36
- import {
37
- type FormRequest,
38
- type FormRequestPayload,
39
- type FormResponseToolkit
40
- } from '~/src/server/routes/types.js'
41
- import { type CacheService } from '~/src/server/services/index.js'
42
- import * as fixtures from '~/test/fixtures/index.js'
43
- import definition from '~/test/form/definitions/file-upload-basic.js'
44
-
45
- jest.mock('~/src/server/plugins/engine/services/formsService.js')
46
-
47
- type TestableFileUploadPageController = FileUploadPageController & {
48
- initiateAndStoreNewUpload(
49
- req: FormRequest,
50
- state: FormSubmissionState
51
- ): Promise<FormSubmissionState>
52
- mergeState(
53
- req: FormRequest,
54
- state: FormSubmissionState,
55
- merge: object
56
- ): Promise<FormSubmissionState>
57
- checkUploadStatus(
58
- request: FormRequest,
59
- state: FormSubmissionState,
60
- depth?: number
61
- ): Promise<FormSubmissionState>
62
- prepareStatus(status: UploadStatusFileResponse): UploadStatusFileResponse
63
- }
64
-
65
- describe('FileUploadPageController', () => {
66
- let model: FormModel
67
- let controller: FileUploadPageController
68
- let request: FormRequest
69
-
70
- beforeEach(() => {
71
- const { pages } = structuredClone(definition)
72
-
73
- model = new FormModel(definition, {
74
- basePath: 'test'
75
- })
76
-
77
- jest.mocked(getFormMetadata).mockResolvedValue(fixtures.form.metadata)
78
-
79
- controller = new FileUploadPageController(model, pages[0])
80
- request = {
81
- params: {
82
- slug: 'test-form'
83
- },
84
- logger: {
85
- info: jest.fn(),
86
- error: jest.fn(),
87
- fatal: jest.fn(),
88
- warn: jest.fn(),
89
- debug: jest.fn(),
90
- trace: jest.fn(),
91
- level: 'info'
92
- },
93
- server: {
94
- plugins: {
95
- 'forms-engine-plugin': {
96
- baseLayoutPath: '',
97
- cacheService: {
98
- setFlash: jest.fn(),
99
- setState: jest
100
- .fn()
101
- .mockImplementation((req, updated) => Promise.resolve(updated))
102
- } as unknown as CacheService
103
- }
104
- }
105
- },
106
- query: {}
107
- } as unknown as FormRequest
108
- })
109
-
110
- afterEach(() => {
111
- jest.restoreAllMocks()
112
- jest.clearAllMocks()
113
- })
114
-
115
- describe('Constructor', () => {
116
- const textComponent: ComponentDef = {
117
- name: 'fullName',
118
- title: 'Full name',
119
- type: ComponentType.TextField,
120
- options: {},
121
- schema: {}
122
- }
123
-
124
- it('throws unless there is exactly 1 file upload component', () => {
125
- const { pages } = structuredClone(definition)
126
-
127
- // @ts-expect-error - Allow invalid component for test
128
- pages[0].components = [textComponent]
129
-
130
- expect(() => new FileUploadPageController(model, pages[0])).toThrow(
131
- `Expected 1 FileUploadFieldComponent in FileUploadPageController '${pages[0].path}'`
132
- )
133
- })
134
-
135
- it('throws unless file upload component is the first in the form', () => {
136
- const { pages } = structuredClone(definition)
137
-
138
- // @ts-expect-error - Allow invalid component for test
139
- pages[0].components.unshift(textComponent)
140
-
141
- expect(() => new FileUploadPageController(model, pages[0])).toThrow(
142
- `Expected 'fileUpload' to be the first form component in FileUploadPageController '${pages[0].path}'`
143
- )
144
- })
145
- })
146
-
147
- describe('Form validation', () => {
148
- it('includes title text and error', () => {
149
- const result = controller.collection.validate()
150
-
151
- expect(result.errors).toEqual([
152
- {
153
- path: ['fileUpload'],
154
- href: '#fileUpload',
155
- name: 'fileUpload',
156
- text: 'Select upload something',
157
- context: {
158
- key: 'fileUpload',
159
- label: 'Upload something',
160
- title: 'Upload something'
161
- }
162
- }
163
- ])
164
- })
165
-
166
- it('includes all field errors', () => {
167
- const result = controller.collection.validate()
168
- expect(result.errors).toHaveLength(1)
169
- })
170
- })
171
-
172
- describe('checkUploadStatus', () => {
173
- describe('error handling', () => {
174
- it('throws error when getUploadStatus returns empty response', async () => {
175
- const state = {
176
- upload: {
177
- [controller.path]: {
178
- upload: {
179
- uploadId: 'some-id',
180
- uploadUrl: 'some-url',
181
- statusUrl: 'some-status-url'
182
- },
183
- files: []
184
- }
185
- }
186
- } as unknown as FormSubmissionState
187
-
188
- jest
189
- .spyOn(uploadService, 'getUploadStatus')
190
- .mockResolvedValue(undefined)
191
-
192
- await expect(
193
- controller['checkUploadStatus'](request, state, 1)
194
- ).rejects.toThrow(
195
- 'Unexpected empty response from getUploadStatus for some-id'
196
- )
197
- })
198
-
199
- it('initiates new upload when getUploadStatus throws a 404 error', async () => {
200
- const state = {
201
- upload: {
202
- [controller.path]: {
203
- upload: {
204
- uploadId: 'some-id',
205
- uploadUrl: 'some-url',
206
- statusUrl: 'some-status-url'
207
- },
208
- files: []
209
- }
210
- }
211
- } as unknown as FormSubmissionState
212
-
213
- const notFoundError = Boom.notFound('Upload not found')
214
-
215
- jest
216
- .spyOn(uploadService, 'getUploadStatus')
217
- .mockRejectedValue(notFoundError)
218
-
219
- const testController = controller as TestableFileUploadPageController
220
- const initiateSpy = jest.spyOn(
221
- testController,
222
- 'initiateAndStoreNewUpload'
223
- )
224
- initiateSpy.mockResolvedValue(state as never)
225
-
226
- const result = await controller['checkUploadStatus'](request, state, 1)
227
-
228
- expect(initiateSpy).toHaveBeenCalledWith(request, state)
229
- expect(result).toBe(state)
230
- })
231
-
232
- it('re-throws non-404 Boom errors from getUploadStatus', async () => {
233
- const state = {
234
- upload: {
235
- [controller.path]: {
236
- upload: {
237
- uploadId: 'some-id',
238
- uploadUrl: 'some-url',
239
- statusUrl: 'some-status-url'
240
- },
241
- files: []
242
- }
243
- }
244
- } as unknown as FormSubmissionState
245
-
246
- const serverError = Boom.internal('Server error')
247
-
248
- jest
249
- .spyOn(uploadService, 'getUploadStatus')
250
- .mockRejectedValue(serverError)
251
-
252
- await expect(
253
- controller['checkUploadStatus'](request, state, 1)
254
- ).rejects.toThrow('Server error')
255
- })
256
-
257
- it('re-throws non-Boom errors from getUploadStatus', async () => {
258
- const state = {
259
- upload: {
260
- [controller.path]: {
261
- upload: {
262
- uploadId: 'some-id',
263
- uploadUrl: 'some-url',
264
- statusUrl: 'some-status-url'
265
- },
266
- files: []
267
- }
268
- }
269
- } as unknown as FormSubmissionState
270
-
271
- const networkError = new Error('Network failure')
272
-
273
- jest
274
- .spyOn(uploadService, 'getUploadStatus')
275
- .mockRejectedValue(networkError)
276
-
277
- await expect(
278
- controller['checkUploadStatus'](request, state, 1)
279
- ).rejects.toThrow('Network failure')
280
- })
281
-
282
- it('handles pending upload with backoff and retries', async () => {
283
- const state = {
284
- upload: {
285
- [controller.path]: {
286
- upload: {
287
- uploadId: 'some-id',
288
- uploadUrl: 'some-url',
289
- statusUrl: 'some-status-url'
290
- },
291
- files: []
292
- }
293
- }
294
- } as unknown as FormSubmissionState
295
-
296
- const pendingStatus = {
297
- uploadStatus: UploadStatus.pending,
298
- form: { file: { fileStatus: FileStatus.complete } }
299
- }
300
-
301
- const getUploadStatusSpy = jest
302
- .spyOn(uploadService, 'getUploadStatus')
303
- .mockResolvedValueOnce(pendingStatus as UploadStatusResponse)
304
- .mockResolvedValueOnce({
305
- uploadStatus: UploadStatus.initiated
306
- } as UploadStatusResponse)
307
-
308
- await controller['checkUploadStatus'](request, state, 1)
309
-
310
- expect(getUploadStatusSpy).toHaveBeenCalledTimes(2)
311
- expect(request.logger.info).toHaveBeenCalled()
312
-
313
- /* eslint-disable-next-line @typescript-eslint/no-unsafe-member-access */
314
- const logMsg = (request.logger.info as jest.Mock).mock.calls[0][0]
315
- expect(logMsg).toEqual(expect.stringContaining('Waiting'))
316
- expect(logMsg).toEqual(expect.stringContaining('some-id'))
317
- }, 3000)
318
-
319
- it('throws gateway timeout when maximum retry depth is exceeded, logs an error, and re-initiates a new upload', async () => {
320
- const state = {
321
- upload: {
322
- [controller.path]: {
323
- upload: {
324
- uploadId: 'some-id',
325
- uploadUrl: 'some-url',
326
- statusUrl: 'some-status-url'
327
- },
328
- files: []
329
- }
330
- }
331
- } as unknown as FormSubmissionState
332
-
333
- const pendingStatus = {
334
- uploadStatus: UploadStatus.pending,
335
- form: { file: { fileStatus: FileStatus.pending } }
336
- }
337
-
338
- jest
339
- .spyOn(uploadService, 'getUploadStatus')
340
- .mockResolvedValue(pendingStatus as UploadStatusResponse)
341
-
342
- const initiateSpy = jest
343
- .spyOn(
344
- controller as TestableFileUploadPageController,
345
- 'initiateAndStoreNewUpload'
346
- )
347
- .mockResolvedValue(state as never)
348
-
349
- await expect(
350
- controller['checkUploadStatus'](request, state, 7)
351
- ).rejects.toThrow(
352
- 'Timed out waiting for some-id after cumulative retries exceeding 55 seconds'
353
- )
354
-
355
- expect(request.logger.error).toHaveBeenCalledWith(
356
- expect.any(Error),
357
- expect.stringContaining(
358
- '[uploadTimeout] Exceeded cumulative retry delay for uploadId: some-id at depth: 7 - re-initiating new upload'
359
- )
360
- )
361
-
362
- expect(initiateSpy).toHaveBeenCalledWith(request, state)
363
- })
364
-
365
- it('throws error when initiateUpload returns undefined', async () => {
366
- const state = {
367
- upload: {
368
- [controller.path]: {
369
- upload: {},
370
- files: []
371
- }
372
- }
373
- } as unknown as FormSubmissionState
374
-
375
- jest.spyOn(uploadService, 'initiateUpload').mockResolvedValue(undefined)
376
-
377
- await expect(
378
- controller['checkUploadStatus'](request, state, 1)
379
- ).rejects.toThrow('Unexpected empty response from initiateUpload')
380
- })
381
-
382
- it('handles pending file status with custom error message', async () => {
383
- const state = {
384
- upload: {
385
- [controller.path]: {
386
- upload: {
387
- uploadId: 'some-id',
388
- uploadUrl: 'some-url',
389
- statusUrl: 'some-status-url'
390
- },
391
- files: []
392
- }
393
- }
394
- } as unknown as FormSubmissionState
395
-
396
- const pendingStatus = {
397
- uploadStatus: UploadStatus.ready,
398
- form: {
399
- file: {
400
- fileStatus: FileStatus.pending,
401
- errorMessage: 'Custom error message'
402
- }
403
- }
404
- }
405
-
406
- jest
407
- .spyOn(uploadService, 'getUploadStatus')
408
- .mockResolvedValue(pendingStatus as UploadStatusResponse)
409
-
410
- jest.spyOn(tempItemSchema, 'validate').mockReturnValue({
411
- value: {
412
- uploadId: 'some-id',
413
- status: pendingStatus,
414
- type: 'object.unknown',
415
- path: ['fileUpload', 'errorMessage'],
416
- context: { value: 'Custom error message' }
417
- },
418
- error: undefined
419
- } as ValidationResult)
420
-
421
- const testController = controller as TestableFileUploadPageController
422
- const initiateSpy = jest.spyOn(
423
- testController,
424
- 'initiateAndStoreNewUpload'
425
- )
426
- initiateSpy.mockResolvedValue(state as never)
427
-
428
- const cacheService = getCacheService(request.server)
429
- await controller['checkUploadStatus'](request, state, 1)
430
-
431
- expect(cacheService.setFlash).toHaveBeenCalledWith(request, {
432
- errors: [
433
- {
434
- path: ['fileUpload'],
435
- href: '#fileUpload',
436
- name: 'fileUpload',
437
- text: 'Custom error message'
438
- }
439
- ]
440
- })
441
- })
442
- })
443
-
444
- describe('state management', () => {
445
- it('returns existing state when upload status is initiated', async () => {
446
- const state = {
447
- upload: {
448
- [controller.path]: {
449
- upload: {
450
- uploadId: 'some-id',
451
- uploadUrl: 'some-url',
452
- statusUrl: 'some-status-url'
453
- },
454
- files: []
455
- }
456
- }
457
- } as unknown as FormSubmissionState
458
-
459
- jest.spyOn(uploadService, 'getUploadStatus').mockResolvedValue({
460
- uploadStatus: UploadStatus.initiated
461
- } as UploadStatusResponse)
462
- const result = await controller['checkUploadStatus'](request, state, 1)
463
- expect(result).toBe(state)
464
- })
465
-
466
- it('returns early when all files are updated', async () => {
467
- const files = ['file1', 'file2']
468
- const filesUpdated = [...files]
469
- const state = {
470
- upload: {
471
- [controller.path]: {
472
- upload: {
473
- uploadId: 'some-id',
474
- uploadUrl: 'some-url',
475
- statusUrl: 'some-status-url'
476
- },
477
- files,
478
- filesUpdated
479
- }
480
- }
481
- } as unknown as FormSubmissionState
482
-
483
- const readyStatus = {
484
- uploadStatus: UploadStatus.ready,
485
- form: { file: { fileStatus: FileStatus.complete } }
486
- }
487
-
488
- jest
489
- .spyOn(uploadService, 'getUploadStatus')
490
- .mockResolvedValue(readyStatus as UploadStatusResponse)
491
-
492
- jest.spyOn(tempItemSchema, 'validate').mockReturnValue({
493
- value: { status: readyStatus },
494
- error: undefined
495
- } as ValidationResult)
496
-
497
- const testController = controller as TestableFileUploadPageController
498
- const initiateSpy = jest.spyOn(
499
- testController,
500
- 'initiateAndStoreNewUpload'
501
- ) as jest.SpyInstance<
502
- Promise<FormSubmissionState>,
503
- [FormRequest, FormSubmissionState]
504
- >
505
-
506
- initiateSpy.mockResolvedValue(state)
507
-
508
- const result = await controller['checkUploadStatus'](request, state, 1)
509
-
510
- expect(result).toBe(state)
511
- })
512
-
513
- it('initiates new upload when no upload exists', async () => {
514
- const state = {
515
- upload: {
516
- [controller.path]: {
517
- upload: {},
518
- files: []
519
- }
520
- }
521
- } as unknown as FormSubmissionState
522
-
523
- const testController = controller as TestableFileUploadPageController
524
-
525
- const initiateSpy = jest.spyOn(
526
- testController,
527
- 'initiateAndStoreNewUpload'
528
- ) as jest.SpyInstance<
529
- Promise<FormSubmissionState>,
530
- [FormRequest, FormSubmissionState]
531
- >
532
-
533
- initiateSpy.mockImplementation(
534
- (_req: FormRequest, s: FormSubmissionState) =>
535
- Promise.resolve(Object.assign({}, s, { initiated: true }))
536
- )
537
-
538
- const result = await controller['checkUploadStatus'](request, state, 1)
539
-
540
- expect(initiateSpy).toHaveBeenCalled()
541
- expect(result.initiated).toBe(true)
542
- })
543
-
544
- it('initiates new upload when file validation fails', async () => {
545
- const state = {
546
- upload: {
547
- [controller.path]: {
548
- upload: {
549
- uploadId: 'some-id',
550
- uploadUrl: 'some-url',
551
- statusUrl: 'some-status-url'
552
- },
553
- files: []
554
- }
555
- }
556
- } as unknown as FormSubmissionState
557
-
558
- jest.spyOn(uploadService, 'getUploadStatus').mockResolvedValue({
559
- uploadStatus: UploadStatus.ready,
560
- form: { file: { fileStatus: FileStatus.complete } }
561
- } as UploadStatusResponse)
562
-
563
- jest.spyOn(tempItemSchema, 'validate').mockReturnValue({
564
- value: {},
565
- error: new Error('Validation failed')
566
- } as ValidationResult)
567
-
568
- const testController = controller as TestableFileUploadPageController
569
-
570
- const initiateSpy = jest.spyOn(
571
- testController,
572
- 'initiateAndStoreNewUpload'
573
- ) as jest.SpyInstance<
574
- Promise<FormSubmissionState>,
575
- [FormRequest, FormSubmissionState]
576
- >
577
-
578
- initiateSpy.mockImplementation(
579
- (
580
- _req: FormRequest,
581
- s: FormSubmissionState
582
- ): Promise<FormSubmissionState> =>
583
- Promise.resolve(Object.assign({}, s, { newUpload: true }))
584
- )
585
- const result = await controller['checkUploadStatus'](request, state, 1)
586
-
587
- expect(initiateSpy).toHaveBeenCalled()
588
- expect(result.newUpload).toBe(true)
589
- })
590
-
591
- it('merges state when file upload is complete', async () => {
592
- const state = {
593
- upload: {
594
- [controller.path]: {
595
- upload: {
596
- uploadId: 'some-id',
597
- uploadUrl: 'some-url',
598
- statusUrl: 'some-status-url'
599
- },
600
- files: []
601
- }
602
- }
603
- } as unknown as FormSubmissionState
604
-
605
- const completeStatus = {
606
- uploadStatus: UploadStatus.ready,
607
- form: { file: { fileStatus: FileStatus.complete } }
608
- }
609
-
610
- jest
611
- .spyOn(uploadService, 'getUploadStatus')
612
- .mockResolvedValue(completeStatus as UploadStatusResponse)
613
-
614
- jest.spyOn(tempItemSchema, 'validate').mockReturnValue({
615
- value: {
616
- status: completeStatus,
617
- uploadId: 'some-id'
618
- },
619
- error: undefined
620
- } as ValidationResult)
621
-
622
- const testController = controller as TestableFileUploadPageController
623
-
624
- const mergeStateSpy = jest.spyOn(
625
- testController,
626
- 'mergeState'
627
- ) as jest.SpyInstance<
628
- Promise<FormSubmissionState>,
629
- [FormRequest, FormSubmissionState, object]
630
- >
631
-
632
- mergeStateSpy.mockImplementation(
633
- (
634
- _req: FormRequest,
635
- s: FormSubmissionState,
636
- _merge: object
637
- ): Promise<FormSubmissionState> =>
638
- Promise.resolve(Object.assign({}, s, { merged: true }))
639
- )
640
-
641
- const initiateSpy = jest.spyOn(
642
- testController,
643
- 'initiateAndStoreNewUpload'
644
- ) as jest.SpyInstance<
645
- Promise<FormSubmissionState>,
646
- [FormRequest, FormSubmissionState]
647
- >
648
-
649
- initiateSpy.mockImplementation(
650
- (
651
- _req: FormRequest,
652
- s: FormSubmissionState
653
- ): Promise<FormSubmissionState> =>
654
- Promise.resolve(Object.assign({}, s, { newUpload: true }))
655
- )
656
-
657
- const result = await controller['checkUploadStatus'](request, state, 1)
658
-
659
- expect(mergeStateSpy).toHaveBeenCalled()
660
- expect(result.newUpload).toBe(true)
661
- })
662
- })
663
-
664
- describe('error messaging', () => {
665
- describe('when file status is not complete', () => {
666
- it('sets flash error with provided message', async () => {
667
- const state = {
668
- upload: {
669
- [controller.path]: {
670
- upload: {
671
- uploadId: 'some-id',
672
- uploadUrl: 'some-url',
673
- statusUrl: 'some-status-url'
674
- },
675
- files: []
676
- }
677
- }
678
- } as unknown as FormSubmissionState
679
-
680
- const errorStatus = {
681
- uploadStatus: UploadStatus.ready,
682
- form: {
683
- file: {
684
- fileStatus: FileStatus.rejected,
685
- errorMessage: 'Test error'
686
- }
687
- }
688
- }
689
-
690
- jest
691
- .spyOn(uploadService, 'getUploadStatus')
692
- .mockResolvedValue(errorStatus as UploadStatusResponse)
693
-
694
- jest.spyOn(tempItemSchema, 'validate').mockReturnValue({
695
- value: {
696
- status: errorStatus,
697
- uploadId: 'some-id'
698
- },
699
- error: undefined
700
- } as ValidationResult)
701
-
702
- const testController = controller as TestableFileUploadPageController
703
-
704
- const initiateSpy = jest.spyOn(
705
- testController,
706
- 'initiateAndStoreNewUpload'
707
- ) as jest.SpyInstance<
708
- Promise<FormSubmissionState>,
709
- [FormRequest, FormSubmissionState]
710
- >
711
-
712
- initiateSpy.mockImplementation(
713
- (
714
- _req: FormRequest,
715
- s: FormSubmissionState
716
- ): Promise<FormSubmissionState> =>
717
- Promise.resolve(Object.assign({}, s, { newUpload: true }))
718
- )
719
-
720
- const cacheService = getCacheService(request.server)
721
-
722
- await controller['checkUploadStatus'](request, state, 1)
723
-
724
- expect(cacheService.setFlash).toHaveBeenCalledWith(request, {
725
- errors: [
726
- {
727
- path: ['fileUpload'],
728
- href: '#fileUpload',
729
- name: 'fileUpload',
730
- text: 'Test error'
731
- }
732
- ]
733
- })
734
- })
735
- })
736
-
737
- describe('when file has error status', () => {
738
- it('sets flash error with error message', async () => {
739
- const state = {
740
- upload: {
741
- [controller.path]: {
742
- upload: {
743
- uploadId: 'some-id',
744
- uploadUrl: 'some-url',
745
- statusUrl: 'some-status-url'
746
- },
747
- files: []
748
- }
749
- }
750
- } as unknown as FormSubmissionState
751
-
752
- const errorStatus = {
753
- uploadStatus: UploadStatus.ready,
754
- form: {
755
- file: {
756
- fileStatus: FileStatus.rejected,
757
- errorMessage: 'Test error message'
758
- }
759
- }
760
- }
761
-
762
- jest
763
- .spyOn(uploadService, 'getUploadStatus')
764
- .mockResolvedValue(errorStatus as UploadStatusResponse)
765
-
766
- jest.spyOn(tempItemSchema, 'validate').mockReturnValue({
767
- value: { status: errorStatus },
768
- error: undefined
769
- } as ValidationResult)
770
-
771
- const testController = controller as TestableFileUploadPageController
772
-
773
- const initiateSpy = jest.spyOn(
774
- testController,
775
- 'initiateAndStoreNewUpload'
776
- ) as jest.SpyInstance<
777
- Promise<FormSubmissionState>,
778
- [FormRequest, FormSubmissionState]
779
- >
780
-
781
- initiateSpy.mockResolvedValue(state)
782
-
783
- const cacheService = getCacheService(request.server)
784
- await controller['checkUploadStatus'](request, state, 1)
785
-
786
- expect(cacheService.setFlash).toHaveBeenCalledWith(request, {
787
- errors: [
788
- {
789
- path: ['fileUpload'],
790
- href: '#fileUpload',
791
- name: 'fileUpload',
792
- text: 'Test error message'
793
- }
794
- ]
795
- })
796
- })
797
-
798
- it('collects all file errors into a single flash when multiple files fail', async () => {
799
- const state = {
800
- upload: {
801
- [controller.path]: {
802
- upload: {
803
- uploadId: 'some-id',
804
- uploadUrl: 'some-url',
805
- statusUrl: 'some-status-url'
806
- },
807
- files: []
808
- }
809
- }
810
- } as unknown as FormSubmissionState
811
-
812
- const errorStatus = {
813
- uploadStatus: UploadStatus.ready,
814
- form: {
815
- file: [
816
- {
817
- fileStatus: FileStatus.rejected,
818
- errorMessage: 'File too large'
819
- },
820
- {
821
- fileStatus: FileStatus.rejected,
822
- errorMessage: 'Invalid file type'
823
- }
824
- ]
825
- }
826
- }
827
-
828
- jest
829
- .spyOn(uploadService, 'getUploadStatus')
830
- .mockResolvedValue(errorStatus as unknown as UploadStatusResponse)
831
-
832
- jest.spyOn(tempItemSchema, 'validate').mockReturnValue({
833
- value: {
834
- status: errorStatus,
835
- uploadId: 'some-id'
836
- },
837
- error: undefined
838
- } as ValidationResult)
839
-
840
- const testController = controller as TestableFileUploadPageController
841
-
842
- const initiateSpy = jest.spyOn(
843
- testController,
844
- 'initiateAndStoreNewUpload'
845
- ) as jest.SpyInstance<
846
- Promise<FormSubmissionState>,
847
- [FormRequest, FormSubmissionState]
848
- >
849
-
850
- initiateSpy.mockResolvedValue(state)
851
-
852
- const cacheService = getCacheService(request.server)
853
-
854
- await controller['checkUploadStatus'](request, state, 1)
855
-
856
- expect(cacheService.setFlash).toHaveBeenCalledTimes(1)
857
- expect(cacheService.setFlash).toHaveBeenCalledWith(request, {
858
- errors: [
859
- {
860
- path: ['fileUpload'],
861
- href: '#fileUpload',
862
- name: 'fileUpload',
863
- text: 'File too large'
864
- },
865
- {
866
- path: ['fileUpload'],
867
- href: '#fileUpload',
868
- name: 'fileUpload',
869
- text: 'Invalid file type'
870
- }
871
- ]
872
- })
873
- })
874
-
875
- it('sets default error message when none provided', async () => {
876
- const state = {
877
- upload: {
878
- [controller.path]: {
879
- upload: {
880
- uploadId: 'some-id',
881
- uploadUrl: 'some-url',
882
- statusUrl: 'some-status-url'
883
- },
884
- files: []
885
- }
886
- }
887
- } as unknown as FormSubmissionState
888
-
889
- const errorStatus = {
890
- uploadStatus: UploadStatus.ready,
891
- form: {
892
- file: {
893
- fileStatus: FileStatus.rejected
894
- }
895
- }
896
- }
897
-
898
- jest
899
- .spyOn(uploadService, 'getUploadStatus')
900
- .mockResolvedValue(errorStatus as UploadStatusResponse)
901
-
902
- jest.spyOn(tempItemSchema, 'validate').mockReturnValue({
903
- value: { status: errorStatus },
904
- error: undefined
905
- } as ValidationResult)
906
-
907
- const testController = controller as TestableFileUploadPageController
908
-
909
- const initiateSpy = jest.spyOn(
910
- testController,
911
- 'initiateAndStoreNewUpload'
912
- ) as jest.SpyInstance<
913
- Promise<FormSubmissionState>,
914
- [FormRequest, FormSubmissionState]
915
- >
916
-
917
- initiateSpy.mockResolvedValue(state)
918
-
919
- const cacheService = getCacheService(request.server)
920
-
921
- await controller['checkUploadStatus'](request, state, 1)
922
-
923
- expect(cacheService.setFlash).toHaveBeenCalledWith(request, {
924
- errors: [
925
- {
926
- path: ['fileUpload'],
927
- href: '#fileUpload',
928
- name: 'fileUpload',
929
- text: 'Unknown error'
930
- }
931
- ]
932
- })
933
- })
934
- })
935
- })
936
-
937
- describe('file removal', () => {
938
- it('returns early when no file is removed', async () => {
939
- const files = [
940
- {
941
- uploadId: 'upload1',
942
- status: { form: { file: { fileId: 'file1' } } }
943
- },
944
- {
945
- uploadId: 'upload2',
946
- status: { form: { file: { fileId: 'file2' } } }
947
- }
948
- ]
949
-
950
- Object.defineProperty(request, 'params', {
951
- value: { itemId: 'nonexistent-file' },
952
- writable: true,
953
- configurable: true
954
- })
955
-
956
- const state = {
957
- upload: {
958
- [controller.path]: {
959
- upload: {
960
- uploadId: 'upload-123',
961
- uploadUrl: 'some-url',
962
- statusUrl: 'some-status-url'
963
- },
964
- files
965
- }
966
- }
967
- } as unknown as FormSubmissionState
968
-
969
- const testController = controller as TestableFileUploadPageController
970
- const mergeStateSpy = jest.spyOn(testController, 'mergeState')
971
-
972
- await controller['checkRemovedFiles'](
973
- request as FormRequestPayload,
974
- state
975
- )
976
-
977
- expect(mergeStateSpy).not.toHaveBeenCalled()
978
- })
979
-
980
- it('merges state when file is removed', async () => {
981
- const files = [
982
- {
983
- uploadId: 'upload1',
984
- status: { form: { file: { fileId: 'file1' } } }
985
- },
986
- {
987
- uploadId: 'upload2',
988
- status: { form: { file: { fileId: 'file2' } } }
989
- }
990
- ]
991
-
992
- Object.defineProperty(request, 'params', {
993
- value: { itemId: 'file1' },
994
- writable: true,
995
- configurable: true
996
- })
997
-
998
- const state = {
999
- upload: {
1000
- [controller.path]: {
1001
- upload: {
1002
- uploadId: 'upload-123',
1003
- uploadUrl: 'some-url',
1004
- statusUrl: 'some-status-url'
1005
- },
1006
- files
1007
- }
1008
- }
1009
- } as unknown as FormSubmissionState
1010
-
1011
- const testController = controller as TestableFileUploadPageController
1012
- const mergeStateSpy = jest.spyOn(testController, 'mergeState')
1013
-
1014
- await controller['checkRemovedFiles'](
1015
- request as FormRequestPayload,
1016
- state
1017
- )
1018
-
1019
- expect(mergeStateSpy).toHaveBeenCalledWith(request, state, {
1020
- upload: {
1021
- [controller.path]: {
1022
- files: [
1023
- {
1024
- uploadId: 'upload2',
1025
- status: { form: { file: { fileId: 'file2' } } }
1026
- }
1027
- ],
1028
- upload: {
1029
- uploadId: 'upload-123',
1030
- uploadUrl: 'some-url',
1031
- statusUrl: 'some-status-url'
1032
- }
1033
- }
1034
- }
1035
- })
1036
- })
1037
- })
1038
- })
1039
-
1040
- describe('prepareStatus', () => {
1041
- describe('when file is pending', () => {
1042
- it('adds error message when no error message exists', () => {
1043
- const status = {
1044
- form: {
1045
- file: {
1046
- fileStatus: FileStatus.pending,
1047
- errorMessage: undefined
1048
- }
1049
- }
1050
- } as UploadStatusFileResponse
1051
-
1052
- const result = prepareStatus(status)
1053
-
1054
- expect(result.form.file.errorMessage).toBe(
1055
- 'The selected file has not fully uploaded'
1056
- )
1057
- })
1058
-
1059
- it('preserves existing error message', () => {
1060
- const existingError = 'Existing error message'
1061
- const status = {
1062
- form: {
1063
- file: {
1064
- fileStatus: FileStatus.pending,
1065
- errorMessage: existingError
1066
- }
1067
- }
1068
- } as UploadStatusFileResponse
1069
-
1070
- const result = prepareStatus(status)
1071
-
1072
- expect(result.form.file.errorMessage).toBe(existingError)
1073
- })
1074
- })
1075
-
1076
- describe('when file is not pending', () => {
1077
- it('does not add error message', () => {
1078
- const status = {
1079
- form: {
1080
- file: {
1081
- fileStatus: FileStatus.complete,
1082
- errorMessage: undefined
1083
- }
1084
- }
1085
- } as UploadStatusFileResponse
1086
-
1087
- const result = prepareStatus(status)
1088
-
1089
- expect(result.form.file.errorMessage).toBeUndefined()
1090
- })
1091
- })
1092
- })
1093
-
1094
- describe('getErrors', () => {
1095
- let controller: FileUploadPageController
1096
-
1097
- beforeEach(() => {
1098
- const { pages } = structuredClone(definition)
1099
- const model = new FormModel(definition, { basePath: 'test' })
1100
- controller = new FileUploadPageController(model, pages[0])
1101
- })
1102
-
1103
- describe('when no details provided', () => {
1104
- it('returns undefined', () => {
1105
- const errors = controller.getErrors()
1106
- expect(errors).toBeUndefined()
1107
- })
1108
- })
1109
-
1110
- describe('error handling', () => {
1111
- it('handles non-upload errors using getError helper', () => {
1112
- const errorDetail = {
1113
- message: 'some error',
1114
- path: ['otherField'],
1115
- type: 'any.required'
1116
- }
1117
- const errors = controller.getErrors([errorDetail])
1118
- expect(errors).toEqual([getError(errorDetail)])
1119
- })
1120
-
1121
- it('handles upload root errors using getError helper', () => {
1122
- const errorDetail = {
1123
- message: 'some error',
1124
- path: ['fileUpload'],
1125
- type: 'any.required'
1126
- }
1127
- const errors = controller.getErrors([errorDetail])
1128
- expect(errors).toEqual([getError(errorDetail)])
1129
- })
1130
- })
1131
-
1132
- describe('object.unknown type errors', () => {
1133
- it('pushes an error with errorMessage', () => {
1134
- const errorDetail = {
1135
- message: 'some error',
1136
- path: ['fileUpload', 'errorMessage'],
1137
- type: 'object.unknown',
1138
- context: { value: 'some error text' }
1139
- }
1140
- const errors = controller.getErrors([errorDetail])
1141
- expect(errors).toEqual([
1142
- {
1143
- path: ['fileUpload', 'errorMessage'],
1144
- href: '#fileUpload',
1145
- name: 'fileUpload',
1146
- text: 'some error text'
1147
- }
1148
- ])
1149
- })
1150
-
1151
- it('handles non-string error message values with default text', () => {
1152
- const errorDetail = {
1153
- message: 'some error',
1154
- path: ['fileUpload', 'errorMessage'],
1155
- type: 'object.unknown',
1156
- context: { value: { some: 'object' } }
1157
- }
1158
- const errors = controller.getErrors([errorDetail])
1159
- expect(errors).toEqual([
1160
- {
1161
- path: ['fileUpload', 'errorMessage'],
1162
- href: '#fileUpload',
1163
- name: 'fileUpload',
1164
- text: 'Unknown error'
1165
- }
1166
- ])
1167
- })
1168
-
1169
- it('handles object.unknown error type with errorMessage path', () => {
1170
- const details = [
1171
- {
1172
- type: 'object.unknown',
1173
- path: ['fileUpload', 'errorMessage'],
1174
- context: { value: 'Custom error message' }
1175
- }
1176
- ] as ValidationErrorItem[]
1177
-
1178
- const errors = controller.getErrors(details)
1179
-
1180
- expect(errors).toEqual([
1181
- {
1182
- path: ['fileUpload', 'errorMessage'],
1183
- href: '#fileUpload',
1184
- name: 'fileUpload',
1185
- text: 'Custom error message'
1186
- }
1187
- ])
1188
- })
1189
- })
1190
- })
1191
-
1192
- describe('initiateAndStoreNewUpload', () => {
1193
- it('throws error when initiateUpload returns undefined', async () => {
1194
- const state = {
1195
- upload: {
1196
- '/test/file-upload': {
1197
- upload: {},
1198
- files: []
1199
- }
1200
- }
1201
- } as unknown as FormSubmissionState
1202
-
1203
- jest.spyOn(uploadService, 'initiateUpload').mockResolvedValue(undefined)
1204
-
1205
- await expect(
1206
- (
1207
- controller['initiateAndStoreNewUpload'] as (
1208
- req: FormRequest,
1209
- state: FormSubmissionState
1210
- ) => Promise<FormSubmissionState>
1211
- )(request, state)
1212
- ).rejects.toThrow('Unexpected empty response from initiateUpload')
1213
- })
1214
- })
1215
-
1216
- describe('makeGetItemDeleteRouteHandler', () => {
1217
- it('throws notFound error when file to delete does not exist', () => {
1218
- const state = {
1219
- upload: {
1220
- [controller.path]: {
1221
- files: [
1222
- {
1223
- uploadId: 'file-1',
1224
- status: {
1225
- form: { file: { fileId: 'file-1', filename: 'file-1.pdf' } }
1226
- }
1227
- },
1228
- {
1229
- uploadId: 'file-2',
1230
- status: {
1231
- form: { file: { fileId: 'file-2', filename: 'file-2.pdf' } }
1232
- }
1233
- }
1234
- ]
1235
- }
1236
- }
1237
- }
1238
-
1239
- const request = {
1240
- params: { itemId: 'I do not exist' }
1241
- } as unknown as FormRequest
1242
-
1243
- const context = { state } as unknown as FormContext
1244
- const h = {} as unknown as FormResponseToolkit
1245
-
1246
- const handler = controller.makeGetItemDeleteRouteHandler()
1247
-
1248
- expect(() => handler(request, context, h)).toThrow(
1249
- 'File to delete not found'
1250
- )
1251
- })
1252
- })
1253
-
1254
- describe('makePostItemDeleteRouteHandler', () => {
1255
- it('proceeds without deleting when confirm is false', async () => {
1256
- const request = {
1257
- params: { itemId: 'file-1' }
1258
- } as unknown as FormRequestPayload
1259
-
1260
- const h = {
1261
- redirect: jest.fn()
1262
- } as unknown as FormResponseToolkit
1263
-
1264
- const context = {
1265
- state: {}
1266
- } as unknown as FormContext
1267
-
1268
- jest
1269
- .spyOn(controller, 'getFormParams')
1270
- .mockReturnValue({ confirm: false } as unknown as FormPayloadParams)
1271
-
1272
- const proceedSpy = jest
1273
- .spyOn(controller, 'proceed')
1274
- .mockResolvedValue({ statusCode: 302 } as never)
1275
-
1276
- const handler = controller.makePostItemDeleteRouteHandler()
1277
- await handler(request, context, h)
1278
-
1279
- expect(proceedSpy).toHaveBeenCalledWith(request, h)
1280
- })
1281
- })
1282
-
1283
- describe('getViewModel', () => {
1284
- it('includes uploadId and proxyUrl in the view model', () => {
1285
- const state = {
1286
- upload: {
1287
- [controller.path]: {
1288
- upload: {
1289
- uploadId: 'some-upload-id',
1290
- uploadUrl: 'https://cdp-upload-and-scan.com/upload',
1291
- statusUrl: 'https://cdp-upload-and-scan.com/status'
1292
- },
1293
- files: []
1294
- }
1295
- }
1296
- } as unknown as FormSubmissionState
1297
-
1298
- const context = { state } as FormContext
1299
-
1300
- jest
1301
- .spyOn(QuestionPageController.prototype, 'getViewModel')
1302
- .mockReturnValue({
1303
- components: [{ model: { id: 'fileUpload' } }]
1304
- } as unknown as FeaturedFormPageViewModel)
1305
-
1306
- jest
1307
- .spyOn(pageHelpers, 'getProxyUrlForLocalDevelopment')
1308
- .mockReturnValue('http://uploader.127.0.0.1.sslip.io:7300')
1309
-
1310
- const viewModel = controller.getViewModel(
1311
- request as FormContextRequest,
1312
- context
1313
- )
1314
-
1315
- expect(viewModel.uploadId).toBe('some-upload-id')
1316
- expect(viewModel.proxyUrl).toBe('http://uploader.127.0.0.1.sslip.io:7300')
1317
- expect(viewModel.formAction).toBe(
1318
- 'https://cdp-upload-and-scan.com/upload'
1319
- )
1320
- })
1321
- })
1322
-
1323
- describe('shouldShowSaveAndExit', () => {
1324
- it('should return true when save and exit is enabled', () => {
1325
- expect(controller.shouldShowSaveAndExit(serverWithSaveAndExit)).toBe(true)
1326
- })
1327
- })
1328
-
1329
- describe('getStateKeys', () => {
1330
- it('should return nested upload path for FileUploadField component', () => {
1331
- const component = controller.fileUpload
1332
- const stateKeys = controller.getStateKeys(component)
1333
-
1334
- expect(stateKeys).toEqual(["upload['/file-upload-component']"])
1335
- })
1336
-
1337
- it('should return empty array for non-FileUploadField components', () => {
1338
- const component = new TextField(
1339
- {
1340
- name: 'testField',
1341
- title: 'Test field',
1342
- type: ComponentType.TextField,
1343
- options: {},
1344
- schema: {}
1345
- },
1346
- { model, page: controller }
1347
- )
1348
-
1349
- const stateKeys = controller.getStateKeys(component)
1350
- expect(stateKeys).toEqual([])
1351
- })
1352
-
1353
- it('should return fallback upload key when component has no page', () => {
1354
- const componentDef: ComponentDef = {
1355
- name: 'fileUpload',
1356
- title: 'Upload something',
1357
- type: ComponentType.FileUploadField,
1358
- options: {},
1359
- schema: {}
1360
- }
1361
-
1362
- // Create a component without a page reference - should return ['upload']
1363
- const component = new FileUploadField(componentDef, {
1364
- model,
1365
- page: undefined
1366
- })
1367
-
1368
- const stateKeys = controller.getStateKeys(component)
1369
- expect(stateKeys).toEqual(['upload'])
1370
- })
1371
- })
1372
- })