@defra/forms-engine-plugin 5.0.0-alpha.3 → 5.0.0-alpha.30

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 (406) hide show
  1. package/.public/37c964ca545c240f010a.mjs +2 -0
  2. package/.public/37c964ca545c240f010a.mjs.LICENSE.txt +4 -0
  3. package/.public/assets-manifest.json +3 -0
  4. package/.public/javascripts/application.min.js +1 -1
  5. package/.public/javascripts/application.min.js.LICENSE.txt +7 -0
  6. package/.public/javascripts/application.min.js.map +1 -1
  7. package/.public/javascripts/shared.min.js +1 -1
  8. package/.public/javascripts/shared.min.js.LICENSE.txt +9 -0
  9. package/.public/javascripts/shared.min.js.map +1 -1
  10. package/.public/javascripts/vendor/@defra.min.js +1 -1
  11. package/.public/javascripts/vendor/@defra.min.js.map +1 -1
  12. package/.public/javascripts/vendor/maplibre-gl.min.js +1 -1
  13. package/.public/javascripts/vendor/maplibre-gl.min.js.LICENSE.txt +3 -3
  14. package/.public/javascripts/vendor/maplibre-gl.min.js.map +1 -1
  15. package/.public/stylesheets/application.min.css +1 -1
  16. package/.public/stylesheets/application.min.css.map +1 -1
  17. package/.server/client/javascripts/file-upload.js +6 -3
  18. package/.server/client/javascripts/file-upload.js.map +1 -1
  19. package/.server/client/javascripts/geospatial-map.d.ts +159 -5
  20. package/.server/client/javascripts/geospatial-map.js +161 -81
  21. package/.server/client/javascripts/geospatial-map.js.map +1 -1
  22. package/.server/client/javascripts/geospatial-map.test.js +152 -0
  23. package/.server/client/javascripts/geospatial-map.test.js.map +1 -0
  24. package/.server/client/javascripts/govuk.js +2 -1
  25. package/.server/client/javascripts/govuk.js.map +1 -1
  26. package/.server/client/javascripts/location-map.d.ts +44 -0
  27. package/.server/client/javascripts/location-map.js +55 -6
  28. package/.server/client/javascripts/location-map.js.map +1 -1
  29. package/.server/client/javascripts/map-constants.d.ts +3 -0
  30. package/.server/client/javascripts/map-constants.js +4 -0
  31. package/.server/client/javascripts/map-constants.js.map +1 -0
  32. package/.server/client/javascripts/map.d.ts +17 -4
  33. package/.server/client/javascripts/map.js +59 -6
  34. package/.server/client/javascripts/map.js.map +1 -1
  35. package/.server/client/javascripts/maps.d.ts +5 -0
  36. package/.server/client/javascripts/maps.js +6 -0
  37. package/.server/client/javascripts/maps.js.map +1 -0
  38. package/.server/client/javascripts/shared.d.ts +1 -4
  39. package/.server/client/javascripts/shared.js +1 -4
  40. package/.server/client/javascripts/shared.js.map +1 -1
  41. package/.server/client/javascripts/sssi-dataset.d.ts +18 -20
  42. package/.server/client/javascripts/sssi-dataset.js +37 -39
  43. package/.server/client/javascripts/sssi-dataset.js.map +1 -1
  44. package/.server/client/stylesheets/maps.scss +4 -0
  45. package/.server/client/stylesheets/shared.scss +1 -5
  46. package/.server/server/constants.d.ts +2 -0
  47. package/.server/server/constants.js +2 -0
  48. package/.server/server/constants.js.map +1 -1
  49. package/.server/server/forms/components.json +8 -0
  50. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +4 -0
  51. package/.server/server/plugins/engine/__stubs__/definitions.d.ts +29 -0
  52. package/.server/server/plugins/engine/__stubs__/definitions.js +125 -0
  53. package/.server/server/plugins/engine/__stubs__/definitions.js.map +1 -0
  54. package/.server/server/plugins/engine/components/AutocompleteField.d.ts +8 -3
  55. package/.server/server/plugins/engine/components/AutocompleteField.js +17 -0
  56. package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
  57. package/.server/server/plugins/engine/components/CheckboxesField.d.ts +23 -2
  58. package/.server/server/plugins/engine/components/CheckboxesField.js +30 -5
  59. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
  60. package/.server/server/plugins/engine/components/ComponentBase.d.ts +2 -1
  61. package/.server/server/plugins/engine/components/ComponentBase.js +2 -0
  62. package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -1
  63. package/.server/server/plugins/engine/components/ComponentCollection.js +12 -7
  64. package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
  65. package/.server/server/plugins/engine/components/DatePartsField.d.ts +6 -3
  66. package/.server/server/plugins/engine/components/DatePartsField.js +12 -7
  67. package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
  68. package/.server/server/plugins/engine/components/DeclarationField.d.ts +6 -3
  69. package/.server/server/plugins/engine/components/DeclarationField.js +6 -4
  70. package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
  71. package/.server/server/plugins/engine/components/Details.d.ts +1 -0
  72. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +33 -2
  73. package/.server/server/plugins/engine/components/EastingNorthingField.js +110 -54
  74. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
  75. package/.server/server/plugins/engine/components/EmailAddressField.d.ts +4 -1
  76. package/.server/server/plugins/engine/components/EmailAddressField.js +2 -1
  77. package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -1
  78. package/.server/server/plugins/engine/components/FileUploadField.d.ts +23 -2
  79. package/.server/server/plugins/engine/components/FileUploadField.js +35 -3
  80. package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
  81. package/.server/server/plugins/engine/components/FormComponent.d.ts +5 -1
  82. package/.server/server/plugins/engine/components/FormComponent.js +5 -2
  83. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  84. package/.server/server/plugins/engine/components/GeospatialField.d.ts +23 -0
  85. package/.server/server/plugins/engine/components/GeospatialField.js +33 -9
  86. package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
  87. package/.server/server/plugins/engine/components/Html.d.ts +1 -0
  88. package/.server/server/plugins/engine/components/InsetText.d.ts +1 -0
  89. package/.server/server/plugins/engine/components/LatLongField.d.ts +32 -2
  90. package/.server/server/plugins/engine/components/LatLongField.js +85 -48
  91. package/.server/server/plugins/engine/components/LatLongField.js.map +1 -1
  92. package/.server/server/plugins/engine/components/List.d.ts +1 -0
  93. package/.server/server/plugins/engine/components/ListFormComponent.d.ts +3 -2
  94. package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -1
  95. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +8 -2
  96. package/.server/server/plugins/engine/components/LocationFieldBase.js +31 -7
  97. package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
  98. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +12 -3
  99. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +21 -13
  100. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
  101. package/.server/server/plugins/engine/components/Markdown.d.ts +1 -0
  102. package/.server/server/plugins/engine/components/Markdown.js +1 -1
  103. package/.server/server/plugins/engine/components/Markdown.js.map +1 -1
  104. package/.server/server/plugins/engine/components/MonthYearField.d.ts +5 -2
  105. package/.server/server/plugins/engine/components/MonthYearField.js +13 -9
  106. package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
  107. package/.server/server/plugins/engine/components/MultilineTextField.d.ts +1 -0
  108. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +2 -1
  109. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js +4 -3
  110. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js.map +1 -1
  111. package/.server/server/plugins/engine/components/NotificationBanner.d.ts +1 -0
  112. package/.server/server/plugins/engine/components/NumberField.d.ts +5 -0
  113. package/.server/server/plugins/engine/components/NumberField.js +22 -0
  114. package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
  115. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +103 -1
  116. package/.server/server/plugins/engine/components/OsGridRefField.js +13 -3
  117. package/.server/server/plugins/engine/components/OsGridRefField.js.map +1 -1
  118. package/.server/server/plugins/engine/components/PaymentField.d.ts +2 -0
  119. package/.server/server/plugins/engine/components/PaymentField.js +9 -5
  120. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
  121. package/.server/server/plugins/engine/components/SelectField.d.ts +1 -0
  122. package/.server/server/plugins/engine/components/SelectionControlField.d.ts +1 -0
  123. package/.server/server/plugins/engine/components/TelephoneNumberField.d.ts +1 -0
  124. package/.server/server/plugins/engine/components/TrackingField.d.ts +21 -0
  125. package/.server/server/plugins/engine/components/TrackingField.js +46 -0
  126. package/.server/server/plugins/engine/components/TrackingField.js.map +1 -0
  127. package/.server/server/plugins/engine/components/UkAddressField.d.ts +1 -0
  128. package/.server/server/plugins/engine/components/UkAddressField.js +23 -8
  129. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  130. package/.server/server/plugins/engine/components/YesNoField.d.ts +3 -2
  131. package/.server/server/plugins/engine/components/YesNoField.js +22 -8
  132. package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
  133. package/.server/server/plugins/engine/components/helpers/components.d.ts +1 -1
  134. package/.server/server/plugins/engine/components/helpers/components.js +6 -3
  135. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  136. package/.server/server/plugins/engine/components/helpers/geospatial.d.ts +8 -1
  137. package/.server/server/plugins/engine/components/helpers/geospatial.js +58 -17
  138. package/.server/server/plugins/engine/components/helpers/geospatial.js.map +1 -1
  139. package/.server/server/plugins/engine/components/helpers/index.d.ts +21 -1
  140. package/.server/server/plugins/engine/components/helpers/index.js +45 -1
  141. package/.server/server/plugins/engine/components/helpers/index.js.map +1 -1
  142. package/.server/server/plugins/engine/components/index.d.ts +1 -0
  143. package/.server/server/plugins/engine/components/index.js +1 -0
  144. package/.server/server/plugins/engine/components/index.js.map +1 -1
  145. package/.server/server/plugins/engine/components/types.d.ts +1 -0
  146. package/.server/server/plugins/engine/components/types.js.map +1 -1
  147. package/.server/server/plugins/engine/errors.d.ts +49 -0
  148. package/.server/server/plugins/engine/errors.js +75 -0
  149. package/.server/server/plugins/engine/errors.js.map +1 -0
  150. package/.server/server/plugins/engine/form-availability.d.ts +3 -2
  151. package/.server/server/plugins/engine/form-availability.js +3 -2
  152. package/.server/server/plugins/engine/form-availability.js.map +1 -1
  153. package/.server/server/plugins/engine/form-context.js +2 -2
  154. package/.server/server/plugins/engine/form-context.js.map +1 -1
  155. package/.server/server/plugins/engine/helpers.d.ts +23 -2
  156. package/.server/server/plugins/engine/helpers.js +44 -5
  157. package/.server/server/plugins/engine/helpers.js.map +1 -1
  158. package/.server/server/plugins/engine/i18n/buildValidationMessages.d.ts +4 -1
  159. package/.server/server/plugins/engine/i18n/buildValidationMessages.js +31 -7
  160. package/.server/server/plugins/engine/i18n/buildValidationMessages.js.map +1 -1
  161. package/.server/server/plugins/engine/i18n/createFormTranslator.d.ts +4 -4
  162. package/.server/server/plugins/engine/i18n/createFormTranslator.js +27 -5
  163. package/.server/server/plugins/engine/i18n/createFormTranslator.js.map +1 -1
  164. package/.server/server/plugins/engine/i18n/extractBaseTranslations.d.ts +1 -1
  165. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js +9 -0
  166. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js.map +1 -1
  167. package/.server/server/plugins/engine/i18n/form.d.ts +13 -0
  168. package/.server/server/plugins/engine/i18n/form.js +35 -0
  169. package/.server/server/plugins/engine/i18n/form.js.map +1 -0
  170. package/.server/server/plugins/engine/i18n/languages.d.ts +10 -0
  171. package/.server/server/plugins/engine/i18n/languages.js +19 -0
  172. package/.server/server/plugins/engine/i18n/languages.js.map +1 -0
  173. package/.server/server/plugins/engine/i18n/translations/cy.json +176 -7
  174. package/.server/server/plugins/engine/i18n/translations/en-GB.json +110 -6
  175. package/.server/server/plugins/engine/i18n/types.d.ts +2 -0
  176. package/.server/server/plugins/engine/i18n/types.js.map +1 -1
  177. package/.server/server/plugins/engine/index.d.ts +4 -0
  178. package/.server/server/plugins/engine/index.js +4 -0
  179. package/.server/server/plugins/engine/index.js.map +1 -1
  180. package/.server/server/plugins/engine/models/FormModel.d.ts +0 -4
  181. package/.server/server/plugins/engine/models/FormModel.js +35 -23
  182. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  183. package/.server/server/plugins/engine/models/SummaryViewModel.js +9 -4
  184. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  185. package/.server/server/plugins/engine/models/types.d.ts +28 -1
  186. package/.server/server/plugins/engine/models/types.js.map +1 -1
  187. package/.server/server/plugins/engine/models/unavailable-view-model.d.ts +11 -2
  188. package/.server/server/plugins/engine/models/unavailable-view-model.js +23 -4
  189. package/.server/server/plugins/engine/models/unavailable-view-model.js.map +1 -1
  190. package/.server/server/plugins/engine/options.js +2 -1
  191. package/.server/server/plugins/engine/options.js.map +1 -1
  192. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js +14 -6
  193. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js.map +1 -1
  194. package/.server/server/plugins/engine/outputFormatters/human/v1.js +2 -1
  195. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
  196. package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +2 -0
  197. package/.server/server/plugins/engine/outputFormatters/machine/v2.js +2 -0
  198. package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
  199. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +7 -1
  200. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +56 -10
  201. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
  202. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +1 -1
  203. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +2 -2
  204. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  205. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +3 -4
  206. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -1
  207. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +10 -4
  208. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  209. package/.server/server/plugins/engine/pageControllers/helpers/pages.js +2 -1
  210. package/.server/server/plugins/engine/pageControllers/helpers/pages.js.map +1 -1
  211. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +35 -2
  212. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +100 -3
  213. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
  214. package/.server/server/plugins/engine/pageControllers/validationOptions.d.ts +1 -1
  215. package/.server/server/plugins/engine/pageControllers/validationOptions.js +24 -3
  216. package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
  217. package/.server/server/plugins/engine/plugin.js +3 -0
  218. package/.server/server/plugins/engine/plugin.js.map +1 -1
  219. package/.server/server/plugins/engine/referenceNumbers.d.ts +1 -0
  220. package/.server/server/plugins/engine/referenceNumbers.js +1 -0
  221. package/.server/server/plugins/engine/referenceNumbers.js.map +1 -1
  222. package/.server/server/plugins/engine/routes/index.js +9 -4
  223. package/.server/server/plugins/engine/routes/index.js.map +1 -1
  224. package/.server/server/plugins/engine/types/enums.d.ts +3 -3
  225. package/.server/server/plugins/engine/types/enums.js +5 -4
  226. package/.server/server/plugins/engine/types/enums.js.map +1 -1
  227. package/.server/server/plugins/engine/types/schema.js +15 -4
  228. package/.server/server/plugins/engine/types/schema.js.map +1 -1
  229. package/.server/server/plugins/engine/types.d.ts +24 -2
  230. package/.server/server/plugins/engine/types.js.map +1 -1
  231. package/.server/server/plugins/engine/unavailable-response.js +5 -2
  232. package/.server/server/plugins/engine/unavailable-response.js.map +1 -1
  233. package/.server/server/plugins/engine/views/components/_location-field-base.html +4 -2
  234. package/.server/server/plugins/engine/views/components/fileuploadfield.html +1 -1
  235. package/.server/server/plugins/engine/views/components/geospatialfield.html +1 -0
  236. package/.server/server/plugins/engine/views/components/osgridreffield.html +4 -1
  237. package/.server/server/plugins/engine/views/components/trackingfield.html +3 -0
  238. package/.server/server/plugins/engine/views/components/ukaddressfield.html +1 -1
  239. package/.server/server/plugins/engine/views/file-upload.html +1 -1
  240. package/.server/server/plugins/engine/views/summary.html +1 -0
  241. package/.server/server/plugins/engine/views/unavailable.html +14 -11
  242. package/.server/server/plugins/map/routes/index.d.ts +4 -0
  243. package/.server/server/plugins/map/routes/index.js +12 -4
  244. package/.server/server/plugins/map/routes/index.js.map +1 -1
  245. package/.server/server/plugins/map/routes/index.test.js +7 -0
  246. package/.server/server/plugins/map/routes/index.test.js.map +1 -0
  247. package/.server/server/plugins/map/routes/vts/README.md +38 -0
  248. package/.server/server/plugins/map/routes/vts/countries-5dp.geojson +4 -0
  249. package/.server/server/plugins/map/routes/vts/countries.geojson +10 -39283
  250. package/.server/server/plugins/map/types.d.ts +24 -2
  251. package/.server/server/plugins/map/types.js +9 -2
  252. package/.server/server/plugins/map/types.js.map +1 -1
  253. package/.server/server/plugins/nunjucks/enviroment.test.js +11 -4
  254. package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -1
  255. package/.server/server/plugins/nunjucks/filters/applyUrlParam.d.ts +9 -0
  256. package/.server/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
  257. package/.server/server/plugins/nunjucks/filters/applyUrlParam.js.map +1 -0
  258. package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js +17 -0
  259. package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js.map +1 -0
  260. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  261. package/.server/server/plugins/nunjucks/filters/index.d.ts +1 -0
  262. package/.server/server/plugins/nunjucks/filters/index.js +1 -0
  263. package/.server/server/plugins/nunjucks/filters/index.js.map +1 -1
  264. package/.server/server/plugins/payment/helper.d.ts +11 -1
  265. package/.server/server/plugins/payment/helper.js +18 -2
  266. package/.server/server/plugins/payment/helper.js.map +1 -1
  267. package/.server/server/plugins/payment/helper.test.js +2 -1
  268. package/.server/server/plugins/payment/helper.test.js.map +1 -1
  269. package/.server/server/plugins/payment/service.d.ts +2 -1
  270. package/.server/server/plugins/payment/service.js +5 -2
  271. package/.server/server/plugins/payment/service.js.map +1 -1
  272. package/.server/server/plugins/payment/service.test.js +7 -3
  273. package/.server/server/plugins/payment/service.test.js.map +1 -1
  274. package/.server/server/plugins/payment/types.d.ts +4 -0
  275. package/.server/server/plugins/payment/types.js +1 -0
  276. package/.server/server/plugins/payment/types.js.map +1 -1
  277. package/.server/server/plugins/postcode-lookup/models/index.d.ts +249 -3
  278. package/.server/server/plugins/postcode-lookup/models/index.js +103 -36
  279. package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
  280. package/.server/server/plugins/postcode-lookup/routes/index.d.ts +15 -1
  281. package/.server/server/plugins/postcode-lookup/routes/index.js +64 -18
  282. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  283. package/.server/server/plugins/postcode-lookup/routes/index.test.js +84 -0
  284. package/.server/server/plugins/postcode-lookup/routes/index.test.js.map +1 -0
  285. package/.server/server/plugins/postcode-lookup/types.d.ts +12 -0
  286. package/.server/server/plugins/postcode-lookup/types.js +6 -1
  287. package/.server/server/plugins/postcode-lookup/types.js.map +1 -1
  288. package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  289. package/.server/server/utils/type-utils.d.ts +1 -2
  290. package/.server/server/utils/type-utils.js +0 -3
  291. package/.server/server/utils/type-utils.js.map +1 -1
  292. package/.server/server/utils/utils.d.ts +6 -0
  293. package/.server/server/utils/utils.js +18 -1
  294. package/.server/server/utils/utils.js.map +1 -1
  295. package/.server/server/utils/utils.test.js +21 -1
  296. package/.server/server/utils/utils.test.js.map +1 -1
  297. package/.server/typings/geodesy/index.d.js +2 -0
  298. package/.server/typings/geodesy/index.d.js.map +1 -0
  299. package/.server/typings/hapi/index.d.js.map +1 -1
  300. package/package.json +24 -9
  301. package/src/client/javascripts/file-upload.js +11 -3
  302. package/src/client/javascripts/geospatial-map.js +181 -86
  303. package/src/client/javascripts/govuk.js +2 -0
  304. package/src/client/javascripts/location-map.js +62 -6
  305. package/src/client/javascripts/map-constants.js +3 -0
  306. package/src/client/javascripts/map.js +66 -9
  307. package/src/client/javascripts/maps.js +5 -0
  308. package/src/client/javascripts/shared.js +1 -4
  309. package/src/client/javascripts/sssi-dataset.js +39 -41
  310. package/src/client/stylesheets/maps.scss +4 -0
  311. package/src/client/stylesheets/shared.scss +1 -5
  312. package/src/server/constants.js +2 -0
  313. package/src/server/forms/components.json +8 -0
  314. package/src/server/forms/register-as-a-unicorn-breeder.yaml +4 -0
  315. package/src/server/plugins/engine/__stubs__/definitions.ts +155 -0
  316. package/src/server/plugins/engine/components/AutocompleteField.ts +20 -0
  317. package/src/server/plugins/engine/components/CheckboxesField.ts +41 -8
  318. package/src/server/plugins/engine/components/ComponentBase.ts +6 -4
  319. package/src/server/plugins/engine/components/ComponentCollection.ts +17 -15
  320. package/src/server/plugins/engine/components/DatePartsField.ts +20 -9
  321. package/src/server/plugins/engine/components/DeclarationField.ts +10 -10
  322. package/src/server/plugins/engine/components/EastingNorthingField.ts +185 -89
  323. package/src/server/plugins/engine/components/EmailAddressField.ts +2 -1
  324. package/src/server/plugins/engine/components/FileUploadField.ts +46 -5
  325. package/src/server/plugins/engine/components/FormComponent.ts +6 -5
  326. package/src/server/plugins/engine/components/GeospatialField.ts +47 -9
  327. package/src/server/plugins/engine/components/LatLongField.ts +128 -58
  328. package/src/server/plugins/engine/components/ListFormComponent.ts +4 -4
  329. package/src/server/plugins/engine/components/LocationFieldBase.ts +41 -8
  330. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +28 -14
  331. package/src/server/plugins/engine/components/Markdown.ts +2 -3
  332. package/src/server/plugins/engine/components/MonthYearField.ts +20 -15
  333. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +9 -3
  334. package/src/server/plugins/engine/components/NumberField.ts +24 -0
  335. package/src/server/plugins/engine/components/OsGridRefField.ts +22 -3
  336. package/src/server/plugins/engine/components/PaymentField.ts +9 -4
  337. package/src/server/plugins/engine/components/TrackingField.ts +64 -0
  338. package/src/server/plugins/engine/components/UkAddressField.ts +30 -7
  339. package/src/server/plugins/engine/components/YesNoField.ts +27 -9
  340. package/src/server/plugins/engine/components/helpers/components.ts +8 -3
  341. package/src/server/plugins/engine/components/helpers/geospatial.ts +87 -24
  342. package/src/server/plugins/engine/components/helpers/index.ts +64 -1
  343. package/src/server/plugins/engine/components/index.ts +1 -0
  344. package/src/server/plugins/engine/components/types.ts +1 -0
  345. package/src/server/plugins/engine/errors.ts +78 -0
  346. package/src/server/plugins/engine/form-availability.ts +8 -2
  347. package/src/server/plugins/engine/form-context.ts +4 -2
  348. package/src/server/plugins/engine/helpers.ts +52 -5
  349. package/src/server/plugins/engine/i18n/buildValidationMessages.ts +16 -8
  350. package/src/server/plugins/engine/i18n/createFormTranslator.ts +43 -12
  351. package/src/server/plugins/engine/i18n/extractBaseTranslations.ts +7 -1
  352. package/src/server/plugins/engine/i18n/form.ts +54 -0
  353. package/src/server/plugins/engine/i18n/languages.ts +19 -0
  354. package/src/server/plugins/engine/i18n/translations/cy.json +176 -7
  355. package/src/server/plugins/engine/i18n/translations/en-GB.json +110 -6
  356. package/src/server/plugins/engine/i18n/types.ts +2 -0
  357. package/src/server/plugins/engine/index.ts +7 -0
  358. package/src/server/plugins/engine/models/FormModel.ts +46 -23
  359. package/src/server/plugins/engine/models/SummaryViewModel.ts +6 -5
  360. package/src/server/plugins/engine/models/types.ts +31 -0
  361. package/src/server/plugins/engine/models/unavailable-view-model.ts +26 -5
  362. package/src/server/plugins/engine/options.js +2 -1
  363. package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +18 -7
  364. package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -1
  365. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +3 -0
  366. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +60 -9
  367. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +2 -2
  368. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +2 -2
  369. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +15 -4
  370. package/src/server/plugins/engine/pageControllers/helpers/pages.ts +2 -1
  371. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +143 -4
  372. package/src/server/plugins/engine/pageControllers/validationOptions.ts +29 -4
  373. package/src/server/plugins/engine/plugin.ts +6 -0
  374. package/src/server/plugins/engine/referenceNumbers.ts +2 -0
  375. package/src/server/plugins/engine/routes/index.ts +9 -3
  376. package/src/server/plugins/engine/types/enums.ts +4 -3
  377. package/src/server/plugins/engine/types/schema.ts +22 -5
  378. package/src/server/plugins/engine/types.ts +28 -1
  379. package/src/server/plugins/engine/unavailable-response.ts +6 -2
  380. package/src/server/plugins/engine/views/components/_location-field-base.html +4 -2
  381. package/src/server/plugins/engine/views/components/fileuploadfield.html +1 -1
  382. package/src/server/plugins/engine/views/components/geospatialfield.html +1 -0
  383. package/src/server/plugins/engine/views/components/osgridreffield.html +4 -1
  384. package/src/server/plugins/engine/views/components/trackingfield.html +3 -0
  385. package/src/server/plugins/engine/views/components/ukaddressfield.html +1 -1
  386. package/src/server/plugins/engine/views/file-upload.html +1 -1
  387. package/src/server/plugins/engine/views/summary.html +1 -0
  388. package/src/server/plugins/engine/views/unavailable.html +14 -11
  389. package/src/server/plugins/map/routes/index.js +29 -4
  390. package/src/server/plugins/map/routes/vts/README.md +38 -0
  391. package/src/server/plugins/map/routes/vts/countries-5dp.geojson +4 -0
  392. package/src/server/plugins/map/routes/vts/countries.geojson +10 -39283
  393. package/src/server/plugins/map/types.js +9 -2
  394. package/src/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
  395. package/src/server/plugins/nunjucks/filters/index.js +1 -0
  396. package/src/server/plugins/payment/helper.js +22 -2
  397. package/src/server/plugins/payment/service.js +6 -2
  398. package/src/server/plugins/payment/types.js +1 -0
  399. package/src/server/plugins/postcode-lookup/models/index.js +91 -46
  400. package/src/server/plugins/postcode-lookup/routes/index.js +96 -24
  401. package/src/server/plugins/postcode-lookup/types.js +6 -1
  402. package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  403. package/src/server/utils/type-utils.ts +1 -11
  404. package/src/server/utils/utils.js +19 -1
  405. package/src/typings/geodesy/index.d.ts +18 -0
  406. package/src/typings/hapi/index.d.ts +2 -0
@@ -1,3 +1,25 @@
1
+ /**
2
+ * @typedef {{
3
+ * ordnanceSurveyApiKey: string
4
+ * ordnanceSurveyApiSecret: string
5
+ * }} MapConfiguration
6
+ */
7
+ /**
8
+ * Map proxy query params
9
+ * @typedef {object} MapProxyQuery
10
+ * @property {string} url - the proxied url
11
+ */
12
+ /**
13
+ * Map geocode query params
14
+ * @typedef {object} MapGeocodeQuery
15
+ * @property {string} query - name query
16
+ */
17
+ export const CountryMap: {
18
+ england: number;
19
+ 'northern-ireland': number;
20
+ scotland: number;
21
+ wales: number;
22
+ };
1
23
  export type MapConfiguration = {
2
24
  ordnanceSurveyApiKey: string;
3
25
  ordnanceSurveyApiSecret: string;
@@ -27,11 +49,11 @@ export type GeospatialCountriesQuery = {
27
49
  /**
28
50
  * - the country to omit
29
51
  */
30
- omit: string;
52
+ omit?: "england" | "wales" | "northern-ireland" | "scotland" | undefined;
31
53
  /**
32
54
  * - the country to include
33
55
  */
34
- only: string;
56
+ only?: "england" | "wales" | "northern-ireland" | "scotland" | undefined;
35
57
  };
36
58
  /**
37
59
  * Map geocode get request
@@ -21,11 +21,18 @@
21
21
  * @property {string} query - name query
22
22
  */
23
23
 
24
+ export const CountryMap = {
25
+ england: 1,
26
+ 'northern-ireland': 3,
27
+ scotland: 2,
28
+ wales: 4
29
+ };
30
+
24
31
  /**
25
32
  * Geospatial countries query params
26
33
  * @typedef {object} GeospatialCountriesQuery
27
- * @property {string} omit - the country to omit
28
- * @property {string} only - the country to include
34
+ * @property {keyof typeof CountryMap} [omit] - the country to omit
35
+ * @property {keyof typeof CountryMap} [only] - the country to include
29
36
  */
30
37
 
31
38
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../../../src/server/plugins/map/types.js"],"sourcesContent":["/**\n * @typedef {{\n * ordnanceSurveyApiKey: string\n * ordnanceSurveyApiSecret: string\n * }} MapConfiguration\n */\n\n//\n// Route types\n//\n\n/**\n * Map proxy query params\n * @typedef {object} MapProxyQuery\n * @property {string} url - the proxied url\n */\n\n/**\n * Map geocode query params\n * @typedef {object} MapGeocodeQuery\n * @property {string} query - name query\n */\n\n/**\n * Geospatial countries query params\n * @typedef {object} GeospatialCountriesQuery\n * @property {string} omit - the country to omit\n * @property {string} only - the country to include\n */\n\n/**\n * Map geocode get request\n * @typedef {object} MapProxyGetRequestRefs\n * @property {MapProxyQuery} Query - Request query\n */\n\n/**\n * Map geocode get request\n * @typedef {object} MapGeocodeGetRequestRefs\n * @property {MapGeocodeQuery} Query - Request query\n */\n\n/**\n * Map countries geojson get request\n * @typedef {object} GeospatialCountriesGetRequestRefs\n * @property {GeospatialCountriesQuery} Query - Request query\n */\n\n/**\n * @typedef {MapProxyGetRequestRefs} MapProxyRequestRefs\n * @typedef {MapGeocodeGetRequestRefs} MapGeocodeRequestRefs\n * @typedef {Request<MapGeocodeGetRequestRefs>} MapProxyGetRequest\n * @typedef {Request<MapGeocodeGetRequestRefs>} MapGeocodeGetRequest\n * @typedef {MapProxyGetRequest | MapGeocodeGetRequest } MapRequest\n */\n\n//\n// Service types\n//\n\n/**\n * @typedef {object} OsNamesFindResponse\n * @property {OsNamesFindHeader} header - Metadata about the search request and results.\n * @property {OsNamesFindResult[]} results - An array of matched place records from the search.\n */\n\n/**\n * @typedef {object} OsNamesFindHeader\n * @property {string} uri - The query URI (usually same as search text).\n * @property {string} query - The original text query string passed to the API.\n * @property {string} format - The response format returned (e.g., \"JSON\").\n * @property {number} maxresults - The maximum number of results requested.\n * @property {number} offset - The offset used in the search results.\n * @property {number} totalresults - The total number of results that matched the query.\n * @property {string} filter - The original filter string passed to the API.\n */\n\n/**\n * @typedef {object} OsNamesFindGazetteerEntry\n * @property {string} ID - Unique identifier for the place/feature.\n * @property {string} NAMES_URI - A URI (identifier) for this named feature.\n * @property {string} NAME1 - Primary name of the feature.\n * @property {string} TYPE - General type classification of the feature.\n * @property {string} LOCAL_TYPE - Local or more specific type classification.\n * @property {number} GEOMETRY_X - Easting coordinate (British National Grid).\n * @property {number} GEOMETRY_Y - Northing coordinate (British National Grid).\n * @property {number} MOST_DETAIL_VIEW_RES - Most detailed resolution available.\n * @property {number} LEAST_DETAIL_VIEW_RES - Least detailed resolution available.\n * @property {number} [MBR_XMIN] - Minimum bounding box X (easting).\n * @property {number} [MBR_YMIN] - Minimum bounding box Y (northing).\n * @property {number} [MBR_XMAX] - Maximum bounding box X (easting).\n * @property {number} [MBR_YMAX] - Maximum bounding box Y (northing).\n * @property {string} [DISTRICT_BOROUGH] - (Optional) District borough.\n * @property {string} [DISTRICT_BOROUGH_URI] - (Optional) URI for the district borough.\n * @property {string} [DISTRICT_BOROUGH_TYPE] - (Optional) Type of the district borough.\n * @property {string} [POSTCODE_DISTRICT] - (Optional) Postcode district.\n * @property {string} [POSTCODE_DISTRICT_URI] - (Optional) URI for the postcode district.\n * @property {string} [POPULATED_PLACE] - (Optional) Name of associated populated place.\n * @property {string} [POPULATED_PLACE_URI] - (Optional) URI of populated place.\n * @property {string} [POPULATED_PLACE_TYPE] - (Optional) Type of populated place.\n * @property {string} [COUNTY_UNITARY] - (Optional) County or unitary authority name.\n * @property {string} [COUNTY_UNITARY_URI] - (Optional) URI for county/unitary authority.\n * @property {string} [COUNTY_UNITARY_TYPE] - (Optional) Classification of county/unitary authority.\n * @property {string} [REGION] - (Optional) Region name.\n * @property {string} [REGION_URI] - (Optional) URI for region.\n * @property {string} [COUNTRY] - (Optional) Country name.\n * @property {string} [COUNTRY_URI] - (Optional) URI for country.\n */\n\n/**\n * OS names GAZETTEER_ENTRY response\n * @typedef {object} OsNamesFindResult\n * @property {OsNamesFindGazetteerEntry} GAZETTEER_ENTRY - Gazetteer entry\n */\n\n/**\n * @import { Request } from '@hapi/hapi'\n */\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA","ignoreList":[]}
1
+ {"version":3,"file":"types.js","names":["CountryMap","england","scotland","wales"],"sources":["../../../../src/server/plugins/map/types.js"],"sourcesContent":["/**\n * @typedef {{\n * ordnanceSurveyApiKey: string\n * ordnanceSurveyApiSecret: string\n * }} MapConfiguration\n */\n\n//\n// Route types\n//\n\n/**\n * Map proxy query params\n * @typedef {object} MapProxyQuery\n * @property {string} url - the proxied url\n */\n\n/**\n * Map geocode query params\n * @typedef {object} MapGeocodeQuery\n * @property {string} query - name query\n */\n\nexport const CountryMap = {\n england: 1,\n 'northern-ireland': 3,\n scotland: 2,\n wales: 4\n}\n\n/**\n * Geospatial countries query params\n * @typedef {object} GeospatialCountriesQuery\n * @property {keyof typeof CountryMap} [omit] - the country to omit\n * @property {keyof typeof CountryMap} [only] - the country to include\n */\n\n/**\n * Map geocode get request\n * @typedef {object} MapProxyGetRequestRefs\n * @property {MapProxyQuery} Query - Request query\n */\n\n/**\n * Map geocode get request\n * @typedef {object} MapGeocodeGetRequestRefs\n * @property {MapGeocodeQuery} Query - Request query\n */\n\n/**\n * Map countries geojson get request\n * @typedef {object} GeospatialCountriesGetRequestRefs\n * @property {GeospatialCountriesQuery} Query - Request query\n */\n\n/**\n * @typedef {MapProxyGetRequestRefs} MapProxyRequestRefs\n * @typedef {MapGeocodeGetRequestRefs} MapGeocodeRequestRefs\n * @typedef {Request<MapGeocodeGetRequestRefs>} MapProxyGetRequest\n * @typedef {Request<MapGeocodeGetRequestRefs>} MapGeocodeGetRequest\n * @typedef {MapProxyGetRequest | MapGeocodeGetRequest } MapRequest\n */\n\n//\n// Service types\n//\n\n/**\n * @typedef {object} OsNamesFindResponse\n * @property {OsNamesFindHeader} header - Metadata about the search request and results.\n * @property {OsNamesFindResult[]} results - An array of matched place records from the search.\n */\n\n/**\n * @typedef {object} OsNamesFindHeader\n * @property {string} uri - The query URI (usually same as search text).\n * @property {string} query - The original text query string passed to the API.\n * @property {string} format - The response format returned (e.g., \"JSON\").\n * @property {number} maxresults - The maximum number of results requested.\n * @property {number} offset - The offset used in the search results.\n * @property {number} totalresults - The total number of results that matched the query.\n * @property {string} filter - The original filter string passed to the API.\n */\n\n/**\n * @typedef {object} OsNamesFindGazetteerEntry\n * @property {string} ID - Unique identifier for the place/feature.\n * @property {string} NAMES_URI - A URI (identifier) for this named feature.\n * @property {string} NAME1 - Primary name of the feature.\n * @property {string} TYPE - General type classification of the feature.\n * @property {string} LOCAL_TYPE - Local or more specific type classification.\n * @property {number} GEOMETRY_X - Easting coordinate (British National Grid).\n * @property {number} GEOMETRY_Y - Northing coordinate (British National Grid).\n * @property {number} MOST_DETAIL_VIEW_RES - Most detailed resolution available.\n * @property {number} LEAST_DETAIL_VIEW_RES - Least detailed resolution available.\n * @property {number} [MBR_XMIN] - Minimum bounding box X (easting).\n * @property {number} [MBR_YMIN] - Minimum bounding box Y (northing).\n * @property {number} [MBR_XMAX] - Maximum bounding box X (easting).\n * @property {number} [MBR_YMAX] - Maximum bounding box Y (northing).\n * @property {string} [DISTRICT_BOROUGH] - (Optional) District borough.\n * @property {string} [DISTRICT_BOROUGH_URI] - (Optional) URI for the district borough.\n * @property {string} [DISTRICT_BOROUGH_TYPE] - (Optional) Type of the district borough.\n * @property {string} [POSTCODE_DISTRICT] - (Optional) Postcode district.\n * @property {string} [POSTCODE_DISTRICT_URI] - (Optional) URI for the postcode district.\n * @property {string} [POPULATED_PLACE] - (Optional) Name of associated populated place.\n * @property {string} [POPULATED_PLACE_URI] - (Optional) URI of populated place.\n * @property {string} [POPULATED_PLACE_TYPE] - (Optional) Type of populated place.\n * @property {string} [COUNTY_UNITARY] - (Optional) County or unitary authority name.\n * @property {string} [COUNTY_UNITARY_URI] - (Optional) URI for county/unitary authority.\n * @property {string} [COUNTY_UNITARY_TYPE] - (Optional) Classification of county/unitary authority.\n * @property {string} [REGION] - (Optional) Region name.\n * @property {string} [REGION_URI] - (Optional) URI for region.\n * @property {string} [COUNTRY] - (Optional) Country name.\n * @property {string} [COUNTRY_URI] - (Optional) URI for country.\n */\n\n/**\n * OS names GAZETTEER_ENTRY response\n * @typedef {object} OsNamesFindResult\n * @property {OsNamesFindGazetteerEntry} GAZETTEER_ENTRY - Gazetteer entry\n */\n\n/**\n * @import { Request } from '@hapi/hapi'\n */\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,OAAO,MAAMA,UAAU,GAAG;EACxBC,OAAO,EAAE,CAAC;EACV,kBAAkB,EAAE,CAAC;EACrBC,QAAQ,EAAE,CAAC;EACXC,KAAK,EAAE;AACT,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA","ignoreList":[]}
@@ -2,13 +2,16 @@ import * as helpers from "../engine/helpers.js";
2
2
  import { environment } from "./environment.js";
3
3
  describe('Nunjucks environment', () => {
4
4
  describe('t global function', () => {
5
+ /** @type {typeof tGlobal} */
6
+ let t;
7
+ beforeEach(() => {
8
+ t = environment.getGlobal('t');
9
+ });
5
10
  it('has t as a global function', () => {
6
- const globals = /** @type {any} */environment.globals;
7
- expect(typeof globals.t).toBe('function');
11
+ expect(typeof t).toBe('function');
8
12
  });
9
13
  it('t global returns the English string for a known key', () => {
10
- const globals = /** @type {any} */environment.globals;
11
- expect(globals.t('errors.title')).toBe('There is a problem');
14
+ expect(t('errors.title')).toBe('There is a problem');
12
15
  });
13
16
  });
14
17
  describe('checkErrorTemplates function', () => {
@@ -173,6 +176,10 @@ describe('Nunjucks environment', () => {
173
176
  });
174
177
  });
175
178
 
179
+ /**
180
+ * @import { tGlobal } from '../../../server/plugins/nunjucks/environment.js'
181
+ */
182
+
176
183
  /*
177
184
  * @import { ComponentViewModel } from '../../../server/plugins/engine/components/types.js'
178
185
  */
@@ -1 +1 @@
1
- {"version":3,"file":"enviroment.test.js","names":["helpers","environment","describe","it","globals","expect","t","toBe","checkErrorTemplates","beforeEach","getGlobal","jest","spyOn","mockImplementation","text","afterEach","restoreAllMocks","test","nunjucksCtx","ctx","errors","result","call","evaluateTemplate","not","toHaveBeenCalled","formContext","someData","context","toHaveBeenCalledTimes","toHaveBeenCalledWith","toEqual","checkComponentTemplates","component","type","isFormComponent","model","content","nonStringContent","some","label","evaluateFunc","template"],"sources":["../../../../src/server/plugins/nunjucks/enviroment.test.js"],"sourcesContent":["import * as helpers from '~/src/server/plugins/engine/helpers.js'\nimport { environment } from '~/src/server/plugins/nunjucks/environment.js'\n\ndescribe('Nunjucks environment', () => {\n describe('t global function', () => {\n it('has t as a global function', () => {\n const globals = /** @type {any} */ (environment).globals\n expect(typeof globals.t).toBe('function')\n })\n\n it('t global returns the English string for a known key', () => {\n const globals = /** @type {any} */ (environment).globals\n expect(globals.t('errors.title')).toBe('There is a problem')\n })\n })\n\n describe('checkErrorTemplates function', () => {\n /** @type {Function} */\n let checkErrorTemplates\n\n beforeEach(() => {\n checkErrorTemplates = environment.getGlobal('checkErrorTemplates')\n\n jest\n .spyOn(helpers, 'evaluateTemplate')\n .mockImplementation((text) => `evaluated-${text}`)\n })\n\n afterEach(() => {\n jest.restoreAllMocks()\n })\n\n test('returns errors unchanged when context is not present', () => {\n const nunjucksCtx = {\n ctx: {}\n }\n\n const errors = [{ text: 'Error 1' }, { text: 'Error 2' }]\n\n const result = checkErrorTemplates.call(nunjucksCtx, errors)\n\n expect(result).toBe(errors)\n expect(helpers.evaluateTemplate).not.toHaveBeenCalled()\n })\n\n test('evaluates error texts when context is present', () => {\n const formContext = { someData: 'some-text' }\n const nunjucksCtx = {\n ctx: { context: formContext }\n }\n\n const errors = [{ text: 'Error 1' }, { text: 'Error 2' }]\n\n const result = checkErrorTemplates.call(nunjucksCtx, errors)\n\n expect(helpers.evaluateTemplate).toHaveBeenCalledTimes(2)\n expect(helpers.evaluateTemplate).toHaveBeenCalledWith(\n 'Error 1',\n formContext\n )\n expect(helpers.evaluateTemplate).toHaveBeenCalledWith(\n 'Error 2',\n formContext\n )\n\n expect(result).toEqual([\n { text: 'evaluated-Error 1' },\n { text: 'evaluated-Error 2' }\n ])\n })\n })\n\n describe('checkComponentTemplates function', () => {\n /** @type {Function} */\n let checkComponentTemplates\n\n beforeEach(() => {\n checkComponentTemplates = environment.getGlobal('checkComponentTemplates')\n\n jest\n .spyOn(helpers, 'evaluateTemplate')\n .mockImplementation((text) => `evaluated-${text}`)\n })\n\n afterEach(() => {\n jest.restoreAllMocks()\n })\n\n test('evaluates string content for Html components', () => {\n const formContext = { someData: 'some-text' }\n const nunjucksCtx = {\n ctx: { context: formContext }\n }\n\n const component = {\n type: 'Html',\n isFormComponent: false,\n model: {\n content: 'Some {{ context.someData }} content'\n }\n }\n\n const result = /** @type {{ model: { content: string } }} */ (\n checkComponentTemplates.call(nunjucksCtx, component)\n )\n\n expect(helpers.evaluateTemplate).toHaveBeenCalledWith(\n 'Some {{ context.someData }} content',\n formContext\n )\n expect(result.model.content).toBe(\n 'evaluated-Some {{ context.someData }} content'\n )\n })\n\n test('does not evaluate non-string content for Html components', () => {\n const formContext = { someData: 'some-text' }\n const nunjucksCtx = {\n ctx: { context: formContext }\n }\n\n const nonStringContent = { some: 'object' }\n const component = {\n type: 'Html',\n isFormComponent: false,\n model: {\n content: nonStringContent\n }\n }\n\n const result = /** @type {{ model: { content: string } }} */ (\n checkComponentTemplates.call(nunjucksCtx, component)\n )\n\n expect(helpers.evaluateTemplate).not.toHaveBeenCalled()\n\n expect(result.model.content).toBe(nonStringContent)\n })\n\n test('evaluates label text for form components', () => {\n const formContext = { someData: 'some-text' }\n const nunjucksCtx = {\n ctx: { context: formContext }\n }\n\n const component = {\n isFormComponent: true,\n model: {\n label: {\n text: 'Label with {{ context.someData }}'\n }\n }\n }\n\n const result = /** @type {{ model: { label?: { text: string } } }} */ (\n checkComponentTemplates.call(nunjucksCtx, component)\n )\n\n expect(helpers.evaluateTemplate).toHaveBeenCalledWith(\n 'Label with {{ context.someData }}',\n formContext\n )\n\n expect(result.model.label?.text).toBe(\n 'evaluated-Label with {{ context.someData }}'\n )\n })\n })\n\n describe('evaluate function', () => {\n /** @type {Function} */\n let evaluateFunc\n\n beforeEach(() => {\n evaluateFunc = environment.getGlobal('evaluate')\n\n jest\n .spyOn(helpers, 'evaluateTemplate')\n .mockImplementation((text) => `evaluated-${text}`)\n })\n\n afterEach(() => {\n jest.restoreAllMocks()\n })\n\n test('evaluates template when context is present', () => {\n const formContext = { someData: 'some-text' }\n const nunjucksCtx = {\n ctx: { context: formContext }\n }\n\n const template = 'Template with {{ context.someData }}'\n const result = evaluateFunc.call(nunjucksCtx, template)\n\n expect(helpers.evaluateTemplate).toHaveBeenCalledWith(\n template,\n formContext\n )\n expect(result).toBe('evaluated-Template with {{ context.someData }}')\n })\n\n test('returns template unchanged when context is not present', () => {\n const nunjucksCtx = {\n ctx: {}\n }\n\n const template = 'Template with {{ context.someData }}'\n const result = evaluateFunc.call(nunjucksCtx, template)\n\n expect(helpers.evaluateTemplate).not.toHaveBeenCalled()\n\n expect(result).toBe(template)\n })\n })\n})\n\n/*\n * @import { ComponentViewModel } from '~/src/server/plugins/engine/components/types.js'\n */\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"enviroment.test.js","names":["helpers","environment","describe","t","beforeEach","getGlobal","it","expect","toBe","checkErrorTemplates","jest","spyOn","mockImplementation","text","afterEach","restoreAllMocks","test","nunjucksCtx","ctx","errors","result","call","evaluateTemplate","not","toHaveBeenCalled","formContext","someData","context","toHaveBeenCalledTimes","toHaveBeenCalledWith","toEqual","checkComponentTemplates","component","type","isFormComponent","model","content","nonStringContent","some","label","evaluateFunc","template"],"sources":["../../../../src/server/plugins/nunjucks/enviroment.test.js"],"sourcesContent":["import * as helpers from '~/src/server/plugins/engine/helpers.js'\nimport { environment } from '~/src/server/plugins/nunjucks/environment.js'\n\ndescribe('Nunjucks environment', () => {\n describe('t global function', () => {\n /** @type {typeof tGlobal} */\n let t\n\n beforeEach(() => {\n t = environment.getGlobal('t')\n })\n\n it('has t as a global function', () => {\n expect(typeof t).toBe('function')\n })\n\n it('t global returns the English string for a known key', () => {\n expect(t('errors.title')).toBe('There is a problem')\n })\n })\n\n describe('checkErrorTemplates function', () => {\n /** @type {Function} */\n let checkErrorTemplates\n\n beforeEach(() => {\n checkErrorTemplates = environment.getGlobal('checkErrorTemplates')\n\n jest\n .spyOn(helpers, 'evaluateTemplate')\n .mockImplementation((text) => `evaluated-${text}`)\n })\n\n afterEach(() => {\n jest.restoreAllMocks()\n })\n\n test('returns errors unchanged when context is not present', () => {\n const nunjucksCtx = {\n ctx: {}\n }\n\n const errors = [{ text: 'Error 1' }, { text: 'Error 2' }]\n\n const result = checkErrorTemplates.call(nunjucksCtx, errors)\n\n expect(result).toBe(errors)\n expect(helpers.evaluateTemplate).not.toHaveBeenCalled()\n })\n\n test('evaluates error texts when context is present', () => {\n const formContext = { someData: 'some-text' }\n const nunjucksCtx = {\n ctx: { context: formContext }\n }\n\n const errors = [{ text: 'Error 1' }, { text: 'Error 2' }]\n\n const result = checkErrorTemplates.call(nunjucksCtx, errors)\n\n expect(helpers.evaluateTemplate).toHaveBeenCalledTimes(2)\n expect(helpers.evaluateTemplate).toHaveBeenCalledWith(\n 'Error 1',\n formContext\n )\n expect(helpers.evaluateTemplate).toHaveBeenCalledWith(\n 'Error 2',\n formContext\n )\n\n expect(result).toEqual([\n { text: 'evaluated-Error 1' },\n { text: 'evaluated-Error 2' }\n ])\n })\n })\n\n describe('checkComponentTemplates function', () => {\n /** @type {Function} */\n let checkComponentTemplates\n\n beforeEach(() => {\n checkComponentTemplates = environment.getGlobal('checkComponentTemplates')\n\n jest\n .spyOn(helpers, 'evaluateTemplate')\n .mockImplementation((text) => `evaluated-${text}`)\n })\n\n afterEach(() => {\n jest.restoreAllMocks()\n })\n\n test('evaluates string content for Html components', () => {\n const formContext = { someData: 'some-text' }\n const nunjucksCtx = {\n ctx: { context: formContext }\n }\n\n const component = {\n type: 'Html',\n isFormComponent: false,\n model: {\n content: 'Some {{ context.someData }} content'\n }\n }\n\n const result = /** @type {{ model: { content: string } }} */ (\n checkComponentTemplates.call(nunjucksCtx, component)\n )\n\n expect(helpers.evaluateTemplate).toHaveBeenCalledWith(\n 'Some {{ context.someData }} content',\n formContext\n )\n expect(result.model.content).toBe(\n 'evaluated-Some {{ context.someData }} content'\n )\n })\n\n test('does not evaluate non-string content for Html components', () => {\n const formContext = { someData: 'some-text' }\n const nunjucksCtx = {\n ctx: { context: formContext }\n }\n\n const nonStringContent = { some: 'object' }\n const component = {\n type: 'Html',\n isFormComponent: false,\n model: {\n content: nonStringContent\n }\n }\n\n const result = /** @type {{ model: { content: string } }} */ (\n checkComponentTemplates.call(nunjucksCtx, component)\n )\n\n expect(helpers.evaluateTemplate).not.toHaveBeenCalled()\n\n expect(result.model.content).toBe(nonStringContent)\n })\n\n test('evaluates label text for form components', () => {\n const formContext = { someData: 'some-text' }\n const nunjucksCtx = {\n ctx: { context: formContext }\n }\n\n const component = {\n isFormComponent: true,\n model: {\n label: {\n text: 'Label with {{ context.someData }}'\n }\n }\n }\n\n const result = /** @type {{ model: { label?: { text: string } } }} */ (\n checkComponentTemplates.call(nunjucksCtx, component)\n )\n\n expect(helpers.evaluateTemplate).toHaveBeenCalledWith(\n 'Label with {{ context.someData }}',\n formContext\n )\n\n expect(result.model.label?.text).toBe(\n 'evaluated-Label with {{ context.someData }}'\n )\n })\n })\n\n describe('evaluate function', () => {\n /** @type {Function} */\n let evaluateFunc\n\n beforeEach(() => {\n evaluateFunc = environment.getGlobal('evaluate')\n\n jest\n .spyOn(helpers, 'evaluateTemplate')\n .mockImplementation((text) => `evaluated-${text}`)\n })\n\n afterEach(() => {\n jest.restoreAllMocks()\n })\n\n test('evaluates template when context is present', () => {\n const formContext = { someData: 'some-text' }\n const nunjucksCtx = {\n ctx: { context: formContext }\n }\n\n const template = 'Template with {{ context.someData }}'\n const result = evaluateFunc.call(nunjucksCtx, template)\n\n expect(helpers.evaluateTemplate).toHaveBeenCalledWith(\n template,\n formContext\n )\n expect(result).toBe('evaluated-Template with {{ context.someData }}')\n })\n\n test('returns template unchanged when context is not present', () => {\n const nunjucksCtx = {\n ctx: {}\n }\n\n const template = 'Template with {{ context.someData }}'\n const result = evaluateFunc.call(nunjucksCtx, template)\n\n expect(helpers.evaluateTemplate).not.toHaveBeenCalled()\n\n expect(result).toBe(template)\n })\n })\n})\n\n/**\n * @import { tGlobal } from '~/src/server/plugins/nunjucks/environment.js'\n */\n\n/*\n * @import { ComponentViewModel } from '~/src/server/plugins/engine/components/types.js'\n */\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Nunjucks filter to add/replace a parameter on a query string of a url.
3
+ * Currently only used in forms-runner.
4
+ * @param {string} urlPath - existing relative url with query string
5
+ * @param {string} paramName - name of parameter
6
+ * @param {string} paramValue - value of parameter
7
+ * @returns {string}
8
+ */
9
+ export function applyUrlParam(urlPath: string, paramName: string, paramValue: string): string;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Nunjucks filter to add/replace a parameter on a query string of a url.
3
+ * Currently only used in forms-runner.
4
+ * @param {string} urlPath - existing relative url with query string
5
+ * @param {string} paramName - name of parameter
6
+ * @param {string} paramValue - value of parameter
7
+ * @returns {string}
8
+ */
9
+ export function applyUrlParam(urlPath, paramName, paramValue) {
10
+ if (typeof urlPath !== 'string') {
11
+ return '';
12
+ }
13
+ const url = new URL(urlPath, 'https://dummy');
14
+ url.searchParams.set(paramName, paramValue);
15
+ return url.pathname + url.search;
16
+ }
17
+ //# sourceMappingURL=applyUrlParam.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applyUrlParam.js","names":["applyUrlParam","urlPath","paramName","paramValue","url","URL","searchParams","set","pathname","search"],"sources":["../../../../../src/server/plugins/nunjucks/filters/applyUrlParam.js"],"sourcesContent":["/**\n * Nunjucks filter to add/replace a parameter on a query string of a url.\n * Currently only used in forms-runner.\n * @param {string} urlPath - existing relative url with query string\n * @param {string} paramName - name of parameter\n * @param {string} paramValue - value of parameter\n * @returns {string}\n */\nexport function applyUrlParam(urlPath, paramName, paramValue) {\n if (typeof urlPath !== 'string') {\n return ''\n }\n const url = new URL(urlPath, 'https://dummy')\n url.searchParams.set(paramName, paramValue)\n\n return url.pathname + url.search\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,aAAaA,CAACC,OAAO,EAAEC,SAAS,EAAEC,UAAU,EAAE;EAC5D,IAAI,OAAOF,OAAO,KAAK,QAAQ,EAAE;IAC/B,OAAO,EAAE;EACX;EACA,MAAMG,GAAG,GAAG,IAAIC,GAAG,CAACJ,OAAO,EAAE,eAAe,CAAC;EAC7CG,GAAG,CAACE,YAAY,CAACC,GAAG,CAACL,SAAS,EAAEC,UAAU,CAAC;EAE3C,OAAOC,GAAG,CAACI,QAAQ,GAAGJ,GAAG,CAACK,MAAM;AAClC","ignoreList":[]}
@@ -0,0 +1,17 @@
1
+ import { applyUrlParam } from "./applyUrlParam.js";
2
+ describe('applyUrlParam', () => {
3
+ test('should return blank string if not a string input', () => {
4
+ // @ts-expect-error - wrong datatype for test
5
+ expect(applyUrlParam({}, 'name', 'val')).toBe('');
6
+ });
7
+ test('should add param', () => {
8
+ expect(applyUrlParam('/my-path/my-form', 'language', 'cy')).toBe('/my-path/my-form?language=cy');
9
+ });
10
+ test('should concat param', () => {
11
+ expect(applyUrlParam('/my-path/my-form?otherParam=123', 'language', 'en-GB')).toBe('/my-path/my-form?otherParam=123&language=en-GB');
12
+ });
13
+ test('should replace param', () => {
14
+ expect(applyUrlParam('/my-path/my-form?language=cy', 'language', 'en-GB')).toBe('/my-path/my-form?language=en-GB');
15
+ });
16
+ });
17
+ //# sourceMappingURL=applyUrlParam.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applyUrlParam.test.js","names":["applyUrlParam","describe","test","expect","toBe"],"sources":["../../../../../src/server/plugins/nunjucks/filters/applyUrlParam.test.js"],"sourcesContent":["import { applyUrlParam } from '~/src/server/plugins/nunjucks/filters/applyUrlParam.js'\n\ndescribe('applyUrlParam', () => {\n test('should return blank string if not a string input', () => {\n // @ts-expect-error - wrong datatype for test\n expect(applyUrlParam({}, 'name', 'val')).toBe('')\n })\n\n test('should add param', () => {\n expect(applyUrlParam('/my-path/my-form', 'language', 'cy')).toBe(\n '/my-path/my-form?language=cy'\n )\n })\n\n test('should concat param', () => {\n expect(\n applyUrlParam('/my-path/my-form?otherParam=123', 'language', 'en-GB')\n ).toBe('/my-path/my-form?otherParam=123&language=en-GB')\n })\n\n test('should replace param', () => {\n expect(\n applyUrlParam('/my-path/my-form?language=cy', 'language', 'en-GB')\n ).toBe('/my-path/my-form?language=en-GB')\n })\n})\n"],"mappings":"AAAA,SAASA,aAAa;AAEtBC,QAAQ,CAAC,eAAe,EAAE,MAAM;EAC9BC,IAAI,CAAC,kDAAkD,EAAE,MAAM;IAC7D;IACAC,MAAM,CAACH,aAAa,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAACI,IAAI,CAAC,EAAE,CAAC;EACnD,CAAC,CAAC;EAEFF,IAAI,CAAC,kBAAkB,EAAE,MAAM;IAC7BC,MAAM,CAACH,aAAa,CAAC,kBAAkB,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAACI,IAAI,CAC9D,8BACF,CAAC;EACH,CAAC,CAAC;EAEFF,IAAI,CAAC,qBAAqB,EAAE,MAAM;IAChCC,MAAM,CACJH,aAAa,CAAC,iCAAiC,EAAE,UAAU,EAAE,OAAO,CACtE,CAAC,CAACI,IAAI,CAAC,gDAAgD,CAAC;EAC1D,CAAC,CAAC;EAEFF,IAAI,CAAC,sBAAsB,EAAE,MAAM;IACjCC,MAAM,CACJH,aAAa,CAAC,8BAA8B,EAAE,UAAU,EAAE,OAAO,CACnE,CAAC,CAACI,IAAI,CAAC,iCAAiC,CAAC;EAC3C,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
@@ -3,5 +3,5 @@
3
3
  * @this {NunjucksContext}
4
4
  * @param {string} name - The name of the component
5
5
  */
6
- export function field(this: NunjucksContext, name: string): import("../../engine/components/TextField.js").TextField | import("../../engine/components/PaymentField.js").PaymentField | import("../../engine/components/SelectField.js").SelectField | import("../../engine/components/RadiosField.js").RadiosField | import("../../engine/components/YesNoField.js").YesNoField | import("../../engine/components/CheckboxesField.js").CheckboxesField | import("../../engine/components/DatePartsField.js").DatePartsField | import("../../engine/components/DeclarationField.js").DeclarationField | import("../../engine/components/EastingNorthingField.js").EastingNorthingField | import("../../engine/components/EmailAddressField.js").EmailAddressField | import("../../engine/components/LatLongField.js").LatLongField | import("../../engine/components/MonthYearField.js").MonthYearField | import("../../engine/components/MultilineTextField.js").MultilineTextField | import("../../engine/components/NationalGridFieldNumberField.js").NationalGridFieldNumberField | import("../../engine/components/NumberField.js").NumberField | import("../../engine/components/OsGridRefField.js").OsGridRefField | import("../../engine/components/TelephoneNumberField.js").TelephoneNumberField | import("../../engine/components/UkAddressField.js").UkAddressField | import("../../engine/components/FileUploadField.js").FileUploadField | import("../../engine/components/HiddenField.js").HiddenField | import("../../engine/components/GeospatialField.js").GeospatialField | import("../../engine/components/Details.js").Details | import("../../engine/components/Html.js").Html | import("../../engine/components/InsetText.js").InsetText | import("../../engine/components/List.js").List | import("../../engine/components/Markdown.js").Markdown | import("../../engine/components/NotificationBanner.js").NotificationBanner | undefined;
6
+ export function field(this: NunjucksContext, name: string): import("../../engine/components/TextField.js").TextField | import("../../engine/components/SelectField.js").SelectField | import("../../engine/components/RadiosField.js").RadiosField | import("../../engine/components/YesNoField.js").YesNoField | import("../../engine/components/CheckboxesField.js").CheckboxesField | import("../../engine/components/DatePartsField.js").DatePartsField | import("../../engine/components/DeclarationField.js").DeclarationField | import("../../engine/components/EastingNorthingField.js").EastingNorthingField | import("../../engine/components/EmailAddressField.js").EmailAddressField | import("../../engine/components/LatLongField.js").LatLongField | import("../../engine/components/MonthYearField.js").MonthYearField | import("../../engine/components/MultilineTextField.js").MultilineTextField | import("../../engine/components/NationalGridFieldNumberField.js").NationalGridFieldNumberField | import("../../engine/components/NumberField.js").NumberField | import("../../engine/components/OsGridRefField.js").OsGridRefField | import("../../engine/components/TelephoneNumberField.js").TelephoneNumberField | import("../../engine/components/UkAddressField.js").UkAddressField | import("../../engine/components/FileUploadField.js").FileUploadField | import("../../engine/components/HiddenField.js").HiddenField | import("../../engine/components/TrackingField.js").TrackingField | import("../../engine/components/PaymentField.js").PaymentField | import("../../engine/components/GeospatialField.js").GeospatialField | import("../../engine/components/Details.js").Details | import("../../engine/components/Html.js").Html | import("../../engine/components/InsetText.js").InsetText | import("../../engine/components/List.js").List | import("../../engine/components/Markdown.js").Markdown | import("../../engine/components/NotificationBanner.js").NotificationBanner | undefined;
7
7
  import type { NunjucksContext } from '../../../../server/plugins/nunjucks/types.js';
@@ -6,3 +6,4 @@ export { href } from "../../../../server/plugins/nunjucks/filters/href.js";
6
6
  export { field } from "../../../../server/plugins/nunjucks/filters/field.js";
7
7
  export { page } from "../../../../server/plugins/nunjucks/filters/page.js";
8
8
  export { merge } from "../../../../server/plugins/nunjucks/filters/merge.js";
9
+ export { applyUrlParam } from "../../../../server/plugins/nunjucks/filters/applyUrlParam.js";
@@ -6,4 +6,5 @@ export { href } from "./href.js";
6
6
  export { field } from "./field.js";
7
7
  export { page } from "./page.js";
8
8
  export { merge } from "./merge.js";
9
+ export { applyUrlParam } from "./applyUrlParam.js";
9
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["highlight","inspect","evaluate","answer","href","field","page","merge"],"sources":["../../../../../src/server/plugins/nunjucks/filters/index.js"],"sourcesContent":["export { highlight } from '~/src/server/plugins/nunjucks/filters/highlight.js'\nexport { inspect } from '~/src/server/plugins/nunjucks/filters/inspect.js'\nexport { evaluate } from '~/src/server/plugins/nunjucks/filters/evaluate.js'\nexport { answer } from '~/src/server/plugins/nunjucks/filters/answer.js'\nexport { href } from '~/src/server/plugins/nunjucks/filters/href.js'\nexport { field } from '~/src/server/plugins/nunjucks/filters/field.js'\nexport { page } from '~/src/server/plugins/nunjucks/filters/page.js'\nexport { merge } from '~/src/server/plugins/nunjucks/filters/merge.js'\n"],"mappings":"AAAA,SAASA,SAAS;AAClB,SAASC,OAAO;AAChB,SAASC,QAAQ;AACjB,SAASC,MAAM;AACf,SAASC,IAAI;AACb,SAASC,KAAK;AACd,SAASC,IAAI;AACb,SAASC,KAAK","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["highlight","inspect","evaluate","answer","href","field","page","merge","applyUrlParam"],"sources":["../../../../../src/server/plugins/nunjucks/filters/index.js"],"sourcesContent":["export { highlight } from '~/src/server/plugins/nunjucks/filters/highlight.js'\nexport { inspect } from '~/src/server/plugins/nunjucks/filters/inspect.js'\nexport { evaluate } from '~/src/server/plugins/nunjucks/filters/evaluate.js'\nexport { answer } from '~/src/server/plugins/nunjucks/filters/answer.js'\nexport { href } from '~/src/server/plugins/nunjucks/filters/href.js'\nexport { field } from '~/src/server/plugins/nunjucks/filters/field.js'\nexport { page } from '~/src/server/plugins/nunjucks/filters/page.js'\nexport { merge } from '~/src/server/plugins/nunjucks/filters/merge.js'\nexport { applyUrlParam } from '~/src/server/plugins/nunjucks/filters/applyUrlParam.js'\n"],"mappings":"AAAA,SAASA,SAAS;AAClB,SAASC,OAAO;AAChB,SAASC,QAAQ;AACjB,SAASC,MAAM;AACf,SAASC,IAAI;AACb,SAASC,KAAK;AACd,SAASC,IAAI;AACb,SAASC,KAAK;AACd,SAASC,aAAa","ignoreList":[]}
@@ -9,9 +9,19 @@ export function createPaymentService(isLivePayment: boolean, formId: string, for
9
9
  /**
10
10
  * Formats a payment date for display
11
11
  * @param {string} isoString - ISO date string
12
+ * @param {string} language - the target language
12
13
  * @returns {string} Formatted date string (e.g., "26 January 2026 5:01pm")
13
14
  */
14
- export function formatPaymentDate(isoString: string): string;
15
+ export function formatPaymentDate(isoString: string, language: string): string;
16
+ /**
17
+ * Formats a date for display in a specific language.
18
+ * To use additional languages, the appropriate module must be imported from 'date-fns/locale'
19
+ * @param { Date | string } date - the date
20
+ * @param {string} formatMask - the format mask
21
+ * @param {string} language - the target language
22
+ * @returns {string} Formatted date string (e.g., "26 January 2026 5:01pm")
23
+ */
24
+ export function formatDateForLanguage(date: Date | string, formatMask: string, language: string): string;
15
25
  /**
16
26
  * Formats a currency amount with thousand separators and two decimal places
17
27
  * @param {number} amount - amount in pounds
@@ -1,4 +1,5 @@
1
1
  import { format } from 'date-fns';
2
+ import { toLanguageLocale } from "../engine/helpers.js";
2
3
  import { PaymentService } from "./service.js";
3
4
  export const DEFAULT_PAYMENT_HELP_URL = 'https://www.gov.uk/government/organisations/department-for-environment-food-rural-affairs';
4
5
  const PAYMENT_TEST_API_KEY = 'payment-test-api-key';
@@ -20,10 +21,25 @@ export async function createPaymentService(isLivePayment, formId, formsService)
20
21
  /**
21
22
  * Formats a payment date for display
22
23
  * @param {string} isoString - ISO date string
24
+ * @param {string} language - the target language
23
25
  * @returns {string} Formatted date string (e.g., "26 January 2026 5:01pm")
24
26
  */
25
- export function formatPaymentDate(isoString) {
26
- return format(new Date(isoString), 'd MMMM yyyy h:mmaaa');
27
+ export function formatPaymentDate(isoString, language) {
28
+ return formatDateForLanguage(new Date(isoString), 'd MMMM yyyy h:mmaaa', language);
29
+ }
30
+
31
+ /**
32
+ * Formats a date for display in a specific language.
33
+ * To use additional languages, the appropriate module must be imported from 'date-fns/locale'
34
+ * @param { Date | string } date - the date
35
+ * @param {string} formatMask - the format mask
36
+ * @param {string} language - the target language
37
+ * @returns {string} Formatted date string (e.g., "26 January 2026 5:01pm")
38
+ */
39
+ export function formatDateForLanguage(date, formatMask, language) {
40
+ return format(date, formatMask, {
41
+ locale: toLanguageLocale(language)
42
+ });
27
43
  }
28
44
 
29
45
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"helper.js","names":["format","PaymentService","DEFAULT_PAYMENT_HELP_URL","PAYMENT_TEST_API_KEY","PAYMENT_LIVE_API_KEY","createPaymentService","isLivePayment","formId","formsService","secretName","apiKey","getFormSecret","formatPaymentDate","isoString","Date","formatCurrency","amount","locale","currency","formatter","Intl","NumberFormat","style"],"sources":["../../../../src/server/plugins/payment/helper.js"],"sourcesContent":["import { format } from 'date-fns'\n\nimport { PaymentService } from '~/src/server/plugins/payment/service.js'\n\nexport const DEFAULT_PAYMENT_HELP_URL =\n 'https://www.gov.uk/government/organisations/department-for-environment-food-rural-affairs'\n\nconst PAYMENT_TEST_API_KEY = 'payment-test-api-key'\nconst PAYMENT_LIVE_API_KEY = 'payment-live-api-key'\n\n/**\n * Creates a PaymentService instance with the appropriate API key\n * @param {boolean} isLivePayment - true if this is a live payment\n * @param {string} formId - id of the form\n * @param {FormsService} formsService - service to handle form data operations\n * @returns {Promise<PaymentService>}\n */\nexport async function createPaymentService(\n isLivePayment,\n formId,\n formsService\n) {\n const secretName = isLivePayment ? PAYMENT_LIVE_API_KEY : PAYMENT_TEST_API_KEY\n const apiKey = await formsService.getFormSecret(formId, secretName)\n return new PaymentService(apiKey)\n}\n\n/**\n * Formats a payment date for display\n * @param {string} isoString - ISO date string\n * @returns {string} Formatted date string (e.g., \"26 January 2026 5:01pm\")\n */\nexport function formatPaymentDate(isoString) {\n return format(new Date(isoString), 'd MMMM yyyy h:mmaaa')\n}\n\n/**\n * Formats a currency amount with thousand separators and two decimal places\n * @param {number} amount - amount in pounds\n * @param {'en-GB'} [locale] - locale for formatting\n * @param {'GBP'} [currency] - currency code\n * @returns {string} Formatted amount (e.g., \"£1,234.56\")\n */\nexport function formatCurrency(amount, locale = 'en-GB', currency = 'GBP') {\n const formatter = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency\n })\n\n return formatter.format(amount)\n}\n\n/**\n * @import { FormsService } from '~/src/server/types.js'\n */\n"],"mappings":"AAAA,SAASA,MAAM,QAAQ,UAAU;AAEjC,SAASC,cAAc;AAEvB,OAAO,MAAMC,wBAAwB,GACnC,2FAA2F;AAE7F,MAAMC,oBAAoB,GAAG,sBAAsB;AACnD,MAAMC,oBAAoB,GAAG,sBAAsB;;AAEnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,oBAAoBA,CACxCC,aAAa,EACbC,MAAM,EACNC,YAAY,EACZ;EACA,MAAMC,UAAU,GAAGH,aAAa,GAAGF,oBAAoB,GAAGD,oBAAoB;EAC9E,MAAMO,MAAM,GAAG,MAAMF,YAAY,CAACG,aAAa,CAACJ,MAAM,EAAEE,UAAU,CAAC;EACnE,OAAO,IAAIR,cAAc,CAACS,MAAM,CAAC;AACnC;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,iBAAiBA,CAACC,SAAS,EAAE;EAC3C,OAAOb,MAAM,CAAC,IAAIc,IAAI,CAACD,SAAS,CAAC,EAAE,qBAAqB,CAAC;AAC3D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,cAAcA,CAACC,MAAM,EAAEC,MAAM,GAAG,OAAO,EAAEC,QAAQ,GAAG,KAAK,EAAE;EACzE,MAAMC,SAAS,GAAG,IAAIC,IAAI,CAACC,YAAY,CAACJ,MAAM,EAAE;IAC9CK,KAAK,EAAE,UAAU;IACjBJ;EACF,CAAC,CAAC;EAEF,OAAOC,SAAS,CAACnB,MAAM,CAACgB,MAAM,CAAC;AACjC;;AAEA;AACA;AACA","ignoreList":[]}
1
+ {"version":3,"file":"helper.js","names":["format","toLanguageLocale","PaymentService","DEFAULT_PAYMENT_HELP_URL","PAYMENT_TEST_API_KEY","PAYMENT_LIVE_API_KEY","createPaymentService","isLivePayment","formId","formsService","secretName","apiKey","getFormSecret","formatPaymentDate","isoString","language","formatDateForLanguage","Date","date","formatMask","locale","formatCurrency","amount","currency","formatter","Intl","NumberFormat","style"],"sources":["../../../../src/server/plugins/payment/helper.js"],"sourcesContent":["import { format } from 'date-fns'\n\nimport { toLanguageLocale } from '~/src/server/plugins/engine/helpers.js'\nimport { PaymentService } from '~/src/server/plugins/payment/service.js'\n\nexport const DEFAULT_PAYMENT_HELP_URL =\n 'https://www.gov.uk/government/organisations/department-for-environment-food-rural-affairs'\n\nconst PAYMENT_TEST_API_KEY = 'payment-test-api-key'\nconst PAYMENT_LIVE_API_KEY = 'payment-live-api-key'\n\n/**\n * Creates a PaymentService instance with the appropriate API key\n * @param {boolean} isLivePayment - true if this is a live payment\n * @param {string} formId - id of the form\n * @param {FormsService} formsService - service to handle form data operations\n * @returns {Promise<PaymentService>}\n */\nexport async function createPaymentService(\n isLivePayment,\n formId,\n formsService\n) {\n const secretName = isLivePayment ? PAYMENT_LIVE_API_KEY : PAYMENT_TEST_API_KEY\n const apiKey = await formsService.getFormSecret(formId, secretName)\n return new PaymentService(apiKey)\n}\n\n/**\n * Formats a payment date for display\n * @param {string} isoString - ISO date string\n * @param {string} language - the target language\n * @returns {string} Formatted date string (e.g., \"26 January 2026 5:01pm\")\n */\nexport function formatPaymentDate(isoString, language) {\n return formatDateForLanguage(\n new Date(isoString),\n 'd MMMM yyyy h:mmaaa',\n language\n )\n}\n\n/**\n * Formats a date for display in a specific language.\n * To use additional languages, the appropriate module must be imported from 'date-fns/locale'\n * @param { Date | string } date - the date\n * @param {string} formatMask - the format mask\n * @param {string} language - the target language\n * @returns {string} Formatted date string (e.g., \"26 January 2026 5:01pm\")\n */\nexport function formatDateForLanguage(date, formatMask, language) {\n return format(date, formatMask, {\n locale: toLanguageLocale(language)\n })\n}\n\n/**\n * Formats a currency amount with thousand separators and two decimal places\n * @param {number} amount - amount in pounds\n * @param {'en-GB'} [locale] - locale for formatting\n * @param {'GBP'} [currency] - currency code\n * @returns {string} Formatted amount (e.g., \"£1,234.56\")\n */\nexport function formatCurrency(amount, locale = 'en-GB', currency = 'GBP') {\n const formatter = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency\n })\n\n return formatter.format(amount)\n}\n\n/**\n * @import { FormsService } from '~/src/server/types.js'\n */\n"],"mappings":"AAAA,SAASA,MAAM,QAAQ,UAAU;AAEjC,SAASC,gBAAgB;AACzB,SAASC,cAAc;AAEvB,OAAO,MAAMC,wBAAwB,GACnC,2FAA2F;AAE7F,MAAMC,oBAAoB,GAAG,sBAAsB;AACnD,MAAMC,oBAAoB,GAAG,sBAAsB;;AAEnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,oBAAoBA,CACxCC,aAAa,EACbC,MAAM,EACNC,YAAY,EACZ;EACA,MAAMC,UAAU,GAAGH,aAAa,GAAGF,oBAAoB,GAAGD,oBAAoB;EAC9E,MAAMO,MAAM,GAAG,MAAMF,YAAY,CAACG,aAAa,CAACJ,MAAM,EAAEE,UAAU,CAAC;EACnE,OAAO,IAAIR,cAAc,CAACS,MAAM,CAAC;AACnC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,iBAAiBA,CAACC,SAAS,EAAEC,QAAQ,EAAE;EACrD,OAAOC,qBAAqB,CAC1B,IAAIC,IAAI,CAACH,SAAS,CAAC,EACnB,qBAAqB,EACrBC,QACF,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,qBAAqBA,CAACE,IAAI,EAAEC,UAAU,EAAEJ,QAAQ,EAAE;EAChE,OAAOf,MAAM,CAACkB,IAAI,EAAEC,UAAU,EAAE;IAC9BC,MAAM,EAAEnB,gBAAgB,CAACc,QAAQ;EACnC,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASM,cAAcA,CAACC,MAAM,EAAEF,MAAM,GAAG,OAAO,EAAEG,QAAQ,GAAG,KAAK,EAAE;EACzE,MAAMC,SAAS,GAAG,IAAIC,IAAI,CAACC,YAAY,CAACN,MAAM,EAAE;IAC9CO,KAAK,EAAE,UAAU;IACjBJ;EACF,CAAC,CAAC;EAEF,OAAOC,SAAS,CAACxB,MAAM,CAACsB,MAAM,CAAC;AACjC;;AAEA;AACA;AACA","ignoreList":[]}
@@ -1,7 +1,8 @@
1
+ import { EN_GB } from "../../constants.js";
1
2
  import { formatCurrency, formatPaymentDate } from "./helper.js";
2
3
  describe('formatPaymentDate', () => {
3
4
  it('should format ISO date string to en-GB format', () => {
4
- const result = formatPaymentDate('2025-11-10T17:01:29.000Z');
5
+ const result = formatPaymentDate('2025-11-10T17:01:29.000Z', EN_GB);
5
6
  expect(result).toBe('10 November 2025 5:01pm');
6
7
  });
7
8
  });
@@ -1 +1 @@
1
- {"version":3,"file":"helper.test.js","names":["formatCurrency","formatPaymentDate","describe","it","result","expect","toBe"],"sources":["../../../../src/server/plugins/payment/helper.test.js"],"sourcesContent":["import {\n formatCurrency,\n formatPaymentDate\n} from '~/src/server/plugins/payment/helper.js'\n\ndescribe('formatPaymentDate', () => {\n it('should format ISO date string to en-GB format', () => {\n const result = formatPaymentDate('2025-11-10T17:01:29.000Z')\n expect(result).toBe('10 November 2025 5:01pm')\n })\n})\n\ndescribe('formatCurrency', () => {\n it('should format whole number with currency symbol', () => {\n expect(formatCurrency(10)).toBe('£10.00')\n })\n\n it('should format decimal amount with currency symbol', () => {\n expect(formatCurrency(99.5)).toBe('£99.50')\n })\n\n it('should format large amounts with thousand separators', () => {\n expect(formatCurrency(1234.56)).toBe('£1,234.56')\n })\n\n it('should format very large amounts with thousand separators', () => {\n expect(formatCurrency(20000)).toBe('£20,000.00')\n })\n})\n"],"mappings":"AAAA,SACEA,cAAc,EACdC,iBAAiB;AAGnBC,QAAQ,CAAC,mBAAmB,EAAE,MAAM;EAClCC,EAAE,CAAC,+CAA+C,EAAE,MAAM;IACxD,MAAMC,MAAM,GAAGH,iBAAiB,CAAC,0BAA0B,CAAC;IAC5DI,MAAM,CAACD,MAAM,CAAC,CAACE,IAAI,CAAC,yBAAyB,CAAC;EAChD,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFJ,QAAQ,CAAC,gBAAgB,EAAE,MAAM;EAC/BC,EAAE,CAAC,iDAAiD,EAAE,MAAM;IAC1DE,MAAM,CAACL,cAAc,CAAC,EAAE,CAAC,CAAC,CAACM,IAAI,CAAC,QAAQ,CAAC;EAC3C,CAAC,CAAC;EAEFH,EAAE,CAAC,mDAAmD,EAAE,MAAM;IAC5DE,MAAM,CAACL,cAAc,CAAC,IAAI,CAAC,CAAC,CAACM,IAAI,CAAC,QAAQ,CAAC;EAC7C,CAAC,CAAC;EAEFH,EAAE,CAAC,sDAAsD,EAAE,MAAM;IAC/DE,MAAM,CAACL,cAAc,CAAC,OAAO,CAAC,CAAC,CAACM,IAAI,CAAC,WAAW,CAAC;EACnD,CAAC,CAAC;EAEFH,EAAE,CAAC,2DAA2D,EAAE,MAAM;IACpEE,MAAM,CAACL,cAAc,CAAC,KAAK,CAAC,CAAC,CAACM,IAAI,CAAC,YAAY,CAAC;EAClD,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"helper.test.js","names":["EN_GB","formatCurrency","formatPaymentDate","describe","it","result","expect","toBe"],"sources":["../../../../src/server/plugins/payment/helper.test.js"],"sourcesContent":["import { EN_GB } from '~/src/server/constants.js'\nimport {\n formatCurrency,\n formatPaymentDate\n} from '~/src/server/plugins/payment/helper.js'\n\ndescribe('formatPaymentDate', () => {\n it('should format ISO date string to en-GB format', () => {\n const result = formatPaymentDate('2025-11-10T17:01:29.000Z', EN_GB)\n expect(result).toBe('10 November 2025 5:01pm')\n })\n})\n\ndescribe('formatCurrency', () => {\n it('should format whole number with currency symbol', () => {\n expect(formatCurrency(10)).toBe('£10.00')\n })\n\n it('should format decimal amount with currency symbol', () => {\n expect(formatCurrency(99.5)).toBe('£99.50')\n })\n\n it('should format large amounts with thousand separators', () => {\n expect(formatCurrency(1234.56)).toBe('£1,234.56')\n })\n\n it('should format very large amounts with thousand separators', () => {\n expect(formatCurrency(20000)).toBe('£20,000.00')\n })\n})\n"],"mappings":"AAAA,SAASA,KAAK;AACd,SACEC,cAAc,EACdC,iBAAiB;AAGnBC,QAAQ,CAAC,mBAAmB,EAAE,MAAM;EAClCC,EAAE,CAAC,+CAA+C,EAAE,MAAM;IACxD,MAAMC,MAAM,GAAGH,iBAAiB,CAAC,0BAA0B,EAAEF,KAAK,CAAC;IACnEM,MAAM,CAACD,MAAM,CAAC,CAACE,IAAI,CAAC,yBAAyB,CAAC;EAChD,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFJ,QAAQ,CAAC,gBAAgB,EAAE,MAAM;EAC/BC,EAAE,CAAC,iDAAiD,EAAE,MAAM;IAC1DE,MAAM,CAACL,cAAc,CAAC,EAAE,CAAC,CAAC,CAACM,IAAI,CAAC,QAAQ,CAAC;EAC3C,CAAC,CAAC;EAEFH,EAAE,CAAC,mDAAmD,EAAE,MAAM;IAC5DE,MAAM,CAACL,cAAc,CAAC,IAAI,CAAC,CAAC,CAACM,IAAI,CAAC,QAAQ,CAAC;EAC7C,CAAC,CAAC;EAEFH,EAAE,CAAC,sDAAsD,EAAE,MAAM;IAC/DE,MAAM,CAACL,cAAc,CAAC,OAAO,CAAC,CAAC,CAACM,IAAI,CAAC,WAAW,CAAC;EACnD,CAAC,CAAC;EAEFH,EAAE,CAAC,2DAA2D,EAAE,MAAM;IACpEE,MAAM,CAACL,cAAc,CAAC,KAAK,CAAC,CAAC,CAACM,IAAI,CAAC,YAAY,CAAC;EAClD,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
@@ -10,12 +10,13 @@ export class PaymentService {
10
10
  * @param {string} returnUrl
11
11
  * @param {string} reference
12
12
  * @param {boolean} isLivePayment
13
- * @param {{ formId: string, slug: string } | undefined } metadata
13
+ * @param {{ formId: string, slug: string, language: string } | undefined } metadata
14
14
  * @param {string} [email] - optional email to prepopulate on GOV.UK Pay
15
15
  */
16
16
  createPayment(amount: number, description: string, returnUrl: string, reference: string, isLivePayment: boolean, metadata: {
17
17
  formId: string;
18
18
  slug: string;
19
+ language: string;
19
20
  } | undefined, email?: string): Promise<{
20
21
  paymentId: string;
21
22
  paymentUrl: string;
@@ -1,5 +1,6 @@
1
1
  import { StatusCodes } from 'http-status-codes';
2
2
  import { logger } from "../../common/helpers/logging/logger.js";
3
+ import { toPayLanguageCode } from "../engine/helpers.js";
3
4
  import { buildPaymentInfo, convertPenceToPounds } from "../engine/routes/payment-helper.js";
4
5
  import { get, post, postJson } from "../../services/httpService.js";
5
6
  const PAYMENT_BASE_URL = 'https://publicapi.payments.service.gov.uk';
@@ -32,10 +33,11 @@ export class PaymentService {
32
33
  * @param {string} returnUrl
33
34
  * @param {string} reference
34
35
  * @param {boolean} isLivePayment
35
- * @param {{ formId: string, slug: string } | undefined } metadata
36
+ * @param {{ formId: string, slug: string, language: string } | undefined } metadata
36
37
  * @param {string} [email] - optional email to prepopulate on GOV.UK Pay
37
38
  */
38
39
  async createPayment(amount, description, returnUrl, reference, isLivePayment, metadata, email) {
40
+ const language = toPayLanguageCode(metadata?.language);
39
41
  try {
40
42
  /** @type {CreatePaymentRequest} */
41
43
  const payload = {
@@ -44,7 +46,8 @@ export class PaymentService {
44
46
  reference,
45
47
  metadata,
46
48
  return_url: returnUrl,
47
- delayed_capture: true
49
+ delayed_capture: true,
50
+ language
48
51
  };
49
52
 
50
53
  // Prepopulate email on GOV.UK Pay if provided
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","names":["StatusCodes","logger","buildPaymentInfo","convertPenceToPounds","get","post","postJson","PAYMENT_BASE_URL","PAYMENT_ENDPOINT","getAuthHeaders","apiKey","Authorization","PaymentService","constructor","createPayment","amount","description","returnUrl","reference","isLivePayment","metadata","email","payload","return_url","delayed_capture","response","postToPayProvider","info","payment_id","paymentId","paymentUrl","_links","next_url","href","err","error","output","message","undefined","getPaymentStatus","getByType","headers","json","errorMessage","Error","JSON","stringify","state","status","code","capturePayment","statusCode","res","OK","NO_CONTENT","event","category","action","outcome","reason","postJsonByType","includes"],"sources":["../../../../src/server/plugins/payment/service.js"],"sourcesContent":["import { StatusCodes } from 'http-status-codes'\n\nimport { logger } from '~/src/server/common/helpers/logging/logger.js'\nimport {\n buildPaymentInfo,\n convertPenceToPounds\n} from '~/src/server/plugins/engine/routes/payment-helper.js'\nimport { get, post, postJson } from '~/src/server/services/httpService.js'\n\nconst PAYMENT_BASE_URL = 'https://publicapi.payments.service.gov.uk'\nconst PAYMENT_ENDPOINT = '/v1/payments'\n\n/**\n * @param {string} apiKey\n * @returns {{ Authorization: string }}\n */\nfunction getAuthHeaders(apiKey) {\n return {\n Authorization: `Bearer ${apiKey}`\n }\n}\n\nexport class PaymentService {\n /** @type {string} */\n #apiKey\n\n /**\n * @param {string} apiKey - API key to use (global config for test value, per-form config for live value)\n */\n constructor(apiKey) {\n this.#apiKey = apiKey\n }\n\n /**\n * Creates a payment with delayed capture (pre-authorisation)\n * @param {number} amount - in pence\n * @param {string} description\n * @param {string} returnUrl\n * @param {string} reference\n * @param {boolean} isLivePayment\n * @param {{ formId: string, slug: string } | undefined } metadata\n * @param {string} [email] - optional email to prepopulate on GOV.UK Pay\n */\n async createPayment(\n amount,\n description,\n returnUrl,\n reference,\n isLivePayment,\n metadata,\n email\n ) {\n try {\n /** @type {CreatePaymentRequest} */\n const payload = {\n amount,\n description,\n reference,\n metadata,\n return_url: returnUrl,\n delayed_capture: true\n }\n\n // Prepopulate email on GOV.UK Pay if provided\n if (email) {\n payload.email = email\n }\n\n const response = await this.postToPayProvider(payload)\n\n logger.info(\n buildPaymentInfo(\n 'create-payment',\n 'success',\n `amount=${convertPenceToPounds(amount)}`,\n isLivePayment,\n response.payment_id\n ),\n `[payment] Created payment and user taken to enter pre-auth details for paymentId=${response.payment_id}`\n )\n\n return {\n paymentId: response.payment_id,\n paymentUrl: response._links.next_url.href\n }\n } catch (err) {\n const error =\n /** @type {{ output?: { payload?: any }, message?: any }} */ (err)\n if (isLivePayment) {\n logger.error(\n error.output?.payload ?? error.message,\n `[payment] Failed to create payment session for reference ${reference}`\n )\n }\n }\n return undefined\n }\n\n /**\n * @param {string} paymentId\n * @param {boolean} isLivePayment\n * @returns {Promise<GetPaymentResponse>}\n */\n async getPaymentStatus(paymentId, isLivePayment) {\n const getByType = /** @type {typeof get<GetPaymentApiResponse>} */ (get)\n\n try {\n const response = await getByType(\n `${PAYMENT_BASE_URL}${PAYMENT_ENDPOINT}/${paymentId}`,\n {\n headers: getAuthHeaders(this.#apiKey),\n json: true\n }\n )\n\n if (response.error) {\n const errorMessage =\n response.error instanceof Error\n ? response.error.message\n : JSON.stringify(response.error)\n throw new Error(`Failed to get payment status: ${errorMessage}`)\n }\n\n const state = response.payload.state\n logger.info(\n buildPaymentInfo(\n 'get-payment-status',\n state.status === 'capturable' || state.status === 'success'\n ? 'success'\n : 'failure',\n `status:${state.status} code:${state.code ?? 'N/A'} message:${state.message ?? 'N/A'}`,\n isLivePayment,\n paymentId\n ),\n `[payment] Got payment status for paymentId=${paymentId}: status=${state.status}`\n )\n\n return {\n state,\n _links: response.payload._links,\n email: response.payload.email,\n paymentId: response.payload.payment_id,\n amount: response.payload.amount\n }\n } catch (err) {\n const error = /** @type {Error} */ (err)\n logger.error(\n error,\n `[payment] Error getting payment status for paymentId=${paymentId}: ${error.message}`\n )\n throw err\n }\n }\n\n /**\n * Captures a payment that is in 'capturable' status\n * @param {string} paymentId\n * @param {number} amount\n * @returns {Promise<boolean>}\n */\n async capturePayment(paymentId, amount) {\n try {\n const response = await post(\n `${PAYMENT_BASE_URL}${PAYMENT_ENDPOINT}/${paymentId}/capture`,\n {\n headers: getAuthHeaders(this.#apiKey)\n }\n )\n\n const statusCode = response.res.statusCode\n\n if (\n statusCode === StatusCodes.OK ||\n statusCode === StatusCodes.NO_CONTENT\n ) {\n logger.info(\n {\n event: {\n category: 'payment',\n action: 'capture-payment',\n outcome: 'success',\n reason: `amount=${convertPenceToPounds(amount)}`,\n reference: paymentId\n }\n },\n `[payment] Successfully captured payment for paymentId=${paymentId}`\n )\n return true\n }\n\n logger.error(\n `[payment] Capture failed for paymentId=${paymentId}: HTTP ${statusCode}`\n )\n return false\n } catch (err) {\n const error = /** @type {Error} */ (err)\n logger.error(\n error,\n `[payment] Error capturing payment for paymentId=${paymentId}: ${error.message}`\n )\n throw err\n }\n }\n\n /**\n * @param {CreatePaymentRequest} payload\n */\n async postToPayProvider(payload) {\n const postJsonByType =\n /** @type {typeof postJson<CreatePaymentResponse>} */ (postJson)\n\n try {\n const response = await postJsonByType(\n `${PAYMENT_BASE_URL}${PAYMENT_ENDPOINT}`,\n {\n payload,\n headers: getAuthHeaders(this.#apiKey)\n }\n )\n\n if (response.payload?.state.status !== 'created') {\n throw new Error(\n `Failed to create payment for reference=${payload.reference}`\n )\n }\n\n return response.payload\n } catch (err) {\n const error = /** @type {Error} */ (err)\n if (!error.message.includes('401 Unauthorized')) {\n logger.error(\n error,\n `[payment] Error creating payment for reference=${payload.reference}: ${error.message}`\n )\n }\n throw err\n }\n }\n}\n\n/**\n * @import { CreatePaymentRequest, CreatePaymentResponse, GetPaymentApiResponse, GetPaymentResponse } from '~/src/server/plugins/payment/types.js'\n */\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"service.js","names":["StatusCodes","logger","toPayLanguageCode","buildPaymentInfo","convertPenceToPounds","get","post","postJson","PAYMENT_BASE_URL","PAYMENT_ENDPOINT","getAuthHeaders","apiKey","Authorization","PaymentService","constructor","createPayment","amount","description","returnUrl","reference","isLivePayment","metadata","email","language","payload","return_url","delayed_capture","response","postToPayProvider","info","payment_id","paymentId","paymentUrl","_links","next_url","href","err","error","output","message","undefined","getPaymentStatus","getByType","headers","json","errorMessage","Error","JSON","stringify","state","status","code","capturePayment","statusCode","res","OK","NO_CONTENT","event","category","action","outcome","reason","postJsonByType","includes"],"sources":["../../../../src/server/plugins/payment/service.js"],"sourcesContent":["import { StatusCodes } from 'http-status-codes'\n\nimport { logger } from '~/src/server/common/helpers/logging/logger.js'\nimport { toPayLanguageCode } from '~/src/server/plugins/engine/helpers.js'\nimport {\n buildPaymentInfo,\n convertPenceToPounds\n} from '~/src/server/plugins/engine/routes/payment-helper.js'\nimport { get, post, postJson } from '~/src/server/services/httpService.js'\n\nconst PAYMENT_BASE_URL = 'https://publicapi.payments.service.gov.uk'\nconst PAYMENT_ENDPOINT = '/v1/payments'\n\n/**\n * @param {string} apiKey\n * @returns {{ Authorization: string }}\n */\nfunction getAuthHeaders(apiKey) {\n return {\n Authorization: `Bearer ${apiKey}`\n }\n}\n\nexport class PaymentService {\n /** @type {string} */\n #apiKey\n\n /**\n * @param {string} apiKey - API key to use (global config for test value, per-form config for live value)\n */\n constructor(apiKey) {\n this.#apiKey = apiKey\n }\n\n /**\n * Creates a payment with delayed capture (pre-authorisation)\n * @param {number} amount - in pence\n * @param {string} description\n * @param {string} returnUrl\n * @param {string} reference\n * @param {boolean} isLivePayment\n * @param {{ formId: string, slug: string, language: string } | undefined } metadata\n * @param {string} [email] - optional email to prepopulate on GOV.UK Pay\n */\n async createPayment(\n amount,\n description,\n returnUrl,\n reference,\n isLivePayment,\n metadata,\n email\n ) {\n const language = toPayLanguageCode(metadata?.language)\n\n try {\n /** @type {CreatePaymentRequest} */\n const payload = {\n amount,\n description,\n reference,\n metadata,\n return_url: returnUrl,\n delayed_capture: true,\n language\n }\n\n // Prepopulate email on GOV.UK Pay if provided\n if (email) {\n payload.email = email\n }\n\n const response = await this.postToPayProvider(payload)\n\n logger.info(\n buildPaymentInfo(\n 'create-payment',\n 'success',\n `amount=${convertPenceToPounds(amount)}`,\n isLivePayment,\n response.payment_id\n ),\n `[payment] Created payment and user taken to enter pre-auth details for paymentId=${response.payment_id}`\n )\n\n return {\n paymentId: response.payment_id,\n paymentUrl: response._links.next_url.href\n }\n } catch (err) {\n const error =\n /** @type {{ output?: { payload?: any }, message?: any }} */ (err)\n if (isLivePayment) {\n logger.error(\n error.output?.payload ?? error.message,\n `[payment] Failed to create payment session for reference ${reference}`\n )\n }\n }\n return undefined\n }\n\n /**\n * @param {string} paymentId\n * @param {boolean} isLivePayment\n * @returns {Promise<GetPaymentResponse>}\n */\n async getPaymentStatus(paymentId, isLivePayment) {\n const getByType = /** @type {typeof get<GetPaymentApiResponse>} */ (get)\n\n try {\n const response = await getByType(\n `${PAYMENT_BASE_URL}${PAYMENT_ENDPOINT}/${paymentId}`,\n {\n headers: getAuthHeaders(this.#apiKey),\n json: true\n }\n )\n\n if (response.error) {\n const errorMessage =\n response.error instanceof Error\n ? response.error.message\n : JSON.stringify(response.error)\n throw new Error(`Failed to get payment status: ${errorMessage}`)\n }\n\n const state = response.payload.state\n logger.info(\n buildPaymentInfo(\n 'get-payment-status',\n state.status === 'capturable' || state.status === 'success'\n ? 'success'\n : 'failure',\n `status:${state.status} code:${state.code ?? 'N/A'} message:${state.message ?? 'N/A'}`,\n isLivePayment,\n paymentId\n ),\n `[payment] Got payment status for paymentId=${paymentId}: status=${state.status}`\n )\n\n return {\n state,\n _links: response.payload._links,\n email: response.payload.email,\n paymentId: response.payload.payment_id,\n amount: response.payload.amount\n }\n } catch (err) {\n const error = /** @type {Error} */ (err)\n logger.error(\n error,\n `[payment] Error getting payment status for paymentId=${paymentId}: ${error.message}`\n )\n throw err\n }\n }\n\n /**\n * Captures a payment that is in 'capturable' status\n * @param {string} paymentId\n * @param {number} amount\n * @returns {Promise<boolean>}\n */\n async capturePayment(paymentId, amount) {\n try {\n const response = await post(\n `${PAYMENT_BASE_URL}${PAYMENT_ENDPOINT}/${paymentId}/capture`,\n {\n headers: getAuthHeaders(this.#apiKey)\n }\n )\n\n const statusCode = response.res.statusCode\n\n if (\n statusCode === StatusCodes.OK ||\n statusCode === StatusCodes.NO_CONTENT\n ) {\n logger.info(\n {\n event: {\n category: 'payment',\n action: 'capture-payment',\n outcome: 'success',\n reason: `amount=${convertPenceToPounds(amount)}`,\n reference: paymentId\n }\n },\n `[payment] Successfully captured payment for paymentId=${paymentId}`\n )\n return true\n }\n\n logger.error(\n `[payment] Capture failed for paymentId=${paymentId}: HTTP ${statusCode}`\n )\n return false\n } catch (err) {\n const error = /** @type {Error} */ (err)\n logger.error(\n error,\n `[payment] Error capturing payment for paymentId=${paymentId}: ${error.message}`\n )\n throw err\n }\n }\n\n /**\n * @param {CreatePaymentRequest} payload\n */\n async postToPayProvider(payload) {\n const postJsonByType =\n /** @type {typeof postJson<CreatePaymentResponse>} */ (postJson)\n\n try {\n const response = await postJsonByType(\n `${PAYMENT_BASE_URL}${PAYMENT_ENDPOINT}`,\n {\n payload,\n headers: getAuthHeaders(this.#apiKey)\n }\n )\n\n if (response.payload?.state.status !== 'created') {\n throw new Error(\n `Failed to create payment for reference=${payload.reference}`\n )\n }\n\n return response.payload\n } catch (err) {\n const error = /** @type {Error} */ (err)\n if (!error.message.includes('401 Unauthorized')) {\n logger.error(\n error,\n `[payment] Error creating payment for reference=${payload.reference}: ${error.message}`\n )\n }\n throw err\n }\n }\n}\n\n/**\n * @import { CreatePaymentRequest, CreatePaymentResponse, GetPaymentApiResponse, GetPaymentResponse } from '~/src/server/plugins/payment/types.js'\n */\n"],"mappings":"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","ignoreList":[]}
@@ -1,3 +1,4 @@
1
+ import { EN_GB } from "../../constants.js";
1
2
  import { PaymentService } from "./service.js";
2
3
  import { get, post, postJson } from "../../services/httpService.js";
3
4
  jest.mock("../../services/httpService.ts");
@@ -33,7 +34,8 @@ describe('payment service', () => {
33
34
  const returnUrl = 'http://localhost:3009/payment-callback-handler';
34
35
  const metadata = {
35
36
  formId: 'form-id',
36
- slug: 'my-form-slug'
37
+ slug: 'my-form-slug',
38
+ language: EN_GB
37
39
  };
38
40
  const payment = await service.createPayment(100, 'Payment description', returnUrl, referenceNumber, false, metadata);
39
41
  expect(payment?.paymentId).toBe('payment-id-12345');
@@ -45,7 +47,8 @@ describe('payment service', () => {
45
47
  const returnUrl = 'http://localhost:3009/payment-callback-handler';
46
48
  const metadata = {
47
49
  formId: 'form-id',
48
- slug: 'my-form-slug'
50
+ slug: 'my-form-slug',
51
+ language: EN_GB
49
52
  };
50
53
  const res = await service.createPayment(100, 'Payment description', returnUrl, referenceNumber, false, metadata);
51
54
  expect(res).toBeUndefined();
@@ -68,7 +71,8 @@ describe('payment service', () => {
68
71
  const returnUrl = 'http://localhost:3009/payment-callback-handler';
69
72
  const metadata = {
70
73
  formId: 'form-id',
71
- slug: 'my-form-slug'
74
+ slug: 'my-form-slug',
75
+ language: 'cy'
72
76
  };
73
77
  const res = await service.createPayment(100, 'Payment description', returnUrl, referenceNumber, false, metadata);
74
78
  expect(res).toBeUndefined();
@@ -1 +1 @@
1
- {"version":3,"file":"service.test.js","names":["PaymentService","get","post","postJson","jest","mock","describe","service","it","expect","toBeDefined","createPaymentResult","payment_id","_links","next_url","href","state","status","mocked","mockResolvedValueOnce","res","statusCode","headers","payload","error","undefined","referenceNumber","returnUrl","metadata","formId","slug","payment","createPayment","paymentId","toBe","paymentUrl","mockRejectedValueOnce","Error","toBeUndefined","getPaymentStatusResult","paymentStatus","getPaymentStatus","rejects","toThrow","capturePaymentResult","captureResult","capturePayment"],"sources":["../../../../src/server/plugins/payment/service.test.js"],"sourcesContent":["import { PaymentService } from '~/src/server/plugins/payment/service.js'\nimport { get, post, postJson } from '~/src/server/services/httpService.js'\n\njest.mock('~/src/server/services/httpService.ts')\n\ndescribe('payment service', () => {\n const service = new PaymentService('my-api-key')\n describe('constructor', () => {\n it('should create instance', () => {\n expect(service).toBeDefined()\n })\n })\n\n describe('createPayment', () => {\n it('should create a payment', async () => {\n const createPaymentResult = {\n payment_id: 'payment-id-12345',\n _links: {\n next_url: {\n href: 'http://next-url-href/payment'\n }\n },\n state: {\n status: 'created'\n }\n }\n jest.mocked(postJson).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 200,\n headers: {}\n }),\n payload: createPaymentResult,\n error: undefined\n })\n\n const referenceNumber = 'ABC-DEF-123'\n const returnUrl = 'http://localhost:3009/payment-callback-handler'\n const metadata = { formId: 'form-id', slug: 'my-form-slug' }\n const payment = await service.createPayment(\n 100,\n 'Payment description',\n returnUrl,\n referenceNumber,\n false,\n metadata\n )\n expect(payment?.paymentId).toBe('payment-id-12345')\n expect(payment?.paymentUrl).toBe('http://next-url-href/payment')\n })\n\n it('should return undefined if fails to create a payment - failed API call', async () => {\n jest\n .mocked(postJson)\n .mockRejectedValueOnce(new Error('internal creation error'))\n\n const referenceNumber = 'ABC-DEF-123'\n const returnUrl = 'http://localhost:3009/payment-callback-handler'\n const metadata = { formId: 'form-id', slug: 'my-form-slug' }\n const res = await service.createPayment(\n 100,\n 'Payment description',\n returnUrl,\n referenceNumber,\n false,\n metadata\n )\n expect(res).toBeUndefined()\n })\n\n it('should return undefined if fails to create a payment - bad result from API call', async () => {\n const createPaymentResult = {\n state: {\n status: 'failed'\n }\n }\n jest.mocked(postJson).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 200,\n headers: {}\n }),\n payload: createPaymentResult,\n error: undefined\n })\n\n const referenceNumber = 'ABC-DEF-123'\n const returnUrl = 'http://localhost:3009/payment-callback-handler'\n const metadata = { formId: 'form-id', slug: 'my-form-slug' }\n const res = await service.createPayment(\n 100,\n 'Payment description',\n returnUrl,\n referenceNumber,\n false,\n metadata\n )\n expect(res).toBeUndefined()\n })\n })\n\n describe('getPaymentStatus', () => {\n it('should get payment status if exists', async () => {\n const getPaymentStatusResult = {\n payment_id: 'payment-id-12345',\n _links: {\n next_url: {\n href: 'http://next-url-href/payment'\n }\n },\n state: {\n status: 'created'\n }\n }\n\n jest.mocked(get).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 200,\n headers: {}\n }),\n payload: getPaymentStatusResult,\n error: undefined\n })\n\n const paymentStatus = await service.getPaymentStatus(\n 'payment-id-12345',\n false\n )\n expect(paymentStatus.paymentId).toBe('payment-id-12345')\n expect(paymentStatus._links.next_url?.href).toBe(\n 'http://next-url-href/payment'\n )\n })\n\n it('should handle payment status error', async () => {\n jest.mocked(get).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 200,\n headers: {}\n }),\n payload: undefined,\n error: new Error('some-error')\n })\n\n await expect(() =>\n service.getPaymentStatus('payment-id-12345', false)\n ).rejects.toThrow('Failed to get payment status: some-error')\n })\n })\n\n describe('capturePayment', () => {\n it('should return true when successful capture with statusCode 200', async () => {\n const capturePaymentResult = {}\n jest.mocked(post).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 200,\n headers: {}\n }),\n payload: capturePaymentResult,\n error: undefined\n })\n\n const captureResult = await service.capturePayment(\n 'payment-id-12345',\n 100\n )\n expect(captureResult).toBe(true)\n })\n\n it('should return true when successful capture with statusCode 204', async () => {\n const capturePaymentResult = {}\n jest.mocked(post).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 204,\n headers: {}\n }),\n payload: capturePaymentResult,\n error: undefined\n })\n\n const captureResult = await service.capturePayment(\n 'payment-id-12345',\n 100\n )\n expect(captureResult).toBe(true)\n })\n\n it('should return false when status code not 200 or 204', async () => {\n const capturePaymentResult = {}\n jest.mocked(post).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 500,\n headers: {}\n }),\n payload: capturePaymentResult,\n error: undefined\n })\n\n const captureResult = await service.capturePayment(\n 'payment-id-12345',\n 100\n )\n expect(captureResult).toBe(false)\n })\n\n it('should throw when internal error', async () => {\n jest\n .mocked(post)\n .mockRejectedValueOnce(new Error('internal capture error'))\n\n await expect(() =>\n service.capturePayment('payment-id-12345', 100)\n ).rejects.toThrow('internal capture error')\n })\n })\n})\n\n/**\n * @import { IncomingMessage } from 'node:http'\n */\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"service.test.js","names":["EN_GB","PaymentService","get","post","postJson","jest","mock","describe","service","it","expect","toBeDefined","createPaymentResult","payment_id","_links","next_url","href","state","status","mocked","mockResolvedValueOnce","res","statusCode","headers","payload","error","undefined","referenceNumber","returnUrl","metadata","formId","slug","language","payment","createPayment","paymentId","toBe","paymentUrl","mockRejectedValueOnce","Error","toBeUndefined","getPaymentStatusResult","paymentStatus","getPaymentStatus","rejects","toThrow","capturePaymentResult","captureResult","capturePayment"],"sources":["../../../../src/server/plugins/payment/service.test.js"],"sourcesContent":["import { EN_GB } from '~/src/server/constants.js'\nimport { PaymentService } from '~/src/server/plugins/payment/service.js'\nimport { get, post, postJson } from '~/src/server/services/httpService.js'\n\njest.mock('~/src/server/services/httpService.ts')\n\ndescribe('payment service', () => {\n const service = new PaymentService('my-api-key')\n describe('constructor', () => {\n it('should create instance', () => {\n expect(service).toBeDefined()\n })\n })\n\n describe('createPayment', () => {\n it('should create a payment', async () => {\n const createPaymentResult = {\n payment_id: 'payment-id-12345',\n _links: {\n next_url: {\n href: 'http://next-url-href/payment'\n }\n },\n state: {\n status: 'created'\n }\n }\n jest.mocked(postJson).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 200,\n headers: {}\n }),\n payload: createPaymentResult,\n error: undefined\n })\n\n const referenceNumber = 'ABC-DEF-123'\n const returnUrl = 'http://localhost:3009/payment-callback-handler'\n const metadata = {\n formId: 'form-id',\n slug: 'my-form-slug',\n language: EN_GB\n }\n const payment = await service.createPayment(\n 100,\n 'Payment description',\n returnUrl,\n referenceNumber,\n false,\n metadata\n )\n expect(payment?.paymentId).toBe('payment-id-12345')\n expect(payment?.paymentUrl).toBe('http://next-url-href/payment')\n })\n\n it('should return undefined if fails to create a payment - failed API call', async () => {\n jest\n .mocked(postJson)\n .mockRejectedValueOnce(new Error('internal creation error'))\n\n const referenceNumber = 'ABC-DEF-123'\n const returnUrl = 'http://localhost:3009/payment-callback-handler'\n const metadata = {\n formId: 'form-id',\n slug: 'my-form-slug',\n language: EN_GB\n }\n const res = await service.createPayment(\n 100,\n 'Payment description',\n returnUrl,\n referenceNumber,\n false,\n metadata\n )\n expect(res).toBeUndefined()\n })\n\n it('should return undefined if fails to create a payment - bad result from API call', async () => {\n const createPaymentResult = {\n state: {\n status: 'failed'\n }\n }\n jest.mocked(postJson).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 200,\n headers: {}\n }),\n payload: createPaymentResult,\n error: undefined\n })\n\n const referenceNumber = 'ABC-DEF-123'\n const returnUrl = 'http://localhost:3009/payment-callback-handler'\n const metadata = {\n formId: 'form-id',\n slug: 'my-form-slug',\n language: 'cy'\n }\n const res = await service.createPayment(\n 100,\n 'Payment description',\n returnUrl,\n referenceNumber,\n false,\n metadata\n )\n expect(res).toBeUndefined()\n })\n })\n\n describe('getPaymentStatus', () => {\n it('should get payment status if exists', async () => {\n const getPaymentStatusResult = {\n payment_id: 'payment-id-12345',\n _links: {\n next_url: {\n href: 'http://next-url-href/payment'\n }\n },\n state: {\n status: 'created'\n }\n }\n\n jest.mocked(get).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 200,\n headers: {}\n }),\n payload: getPaymentStatusResult,\n error: undefined\n })\n\n const paymentStatus = await service.getPaymentStatus(\n 'payment-id-12345',\n false\n )\n expect(paymentStatus.paymentId).toBe('payment-id-12345')\n expect(paymentStatus._links.next_url?.href).toBe(\n 'http://next-url-href/payment'\n )\n })\n\n it('should handle payment status error', async () => {\n jest.mocked(get).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 200,\n headers: {}\n }),\n payload: undefined,\n error: new Error('some-error')\n })\n\n await expect(() =>\n service.getPaymentStatus('payment-id-12345', false)\n ).rejects.toThrow('Failed to get payment status: some-error')\n })\n })\n\n describe('capturePayment', () => {\n it('should return true when successful capture with statusCode 200', async () => {\n const capturePaymentResult = {}\n jest.mocked(post).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 200,\n headers: {}\n }),\n payload: capturePaymentResult,\n error: undefined\n })\n\n const captureResult = await service.capturePayment(\n 'payment-id-12345',\n 100\n )\n expect(captureResult).toBe(true)\n })\n\n it('should return true when successful capture with statusCode 204', async () => {\n const capturePaymentResult = {}\n jest.mocked(post).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 204,\n headers: {}\n }),\n payload: capturePaymentResult,\n error: undefined\n })\n\n const captureResult = await service.capturePayment(\n 'payment-id-12345',\n 100\n )\n expect(captureResult).toBe(true)\n })\n\n it('should return false when status code not 200 or 204', async () => {\n const capturePaymentResult = {}\n jest.mocked(post).mockResolvedValueOnce({\n res: /** @type {IncomingMessage} */ ({\n statusCode: 500,\n headers: {}\n }),\n payload: capturePaymentResult,\n error: undefined\n })\n\n const captureResult = await service.capturePayment(\n 'payment-id-12345',\n 100\n )\n expect(captureResult).toBe(false)\n })\n\n it('should throw when internal error', async () => {\n jest\n .mocked(post)\n .mockRejectedValueOnce(new Error('internal capture error'))\n\n await expect(() =>\n service.capturePayment('payment-id-12345', 100)\n ).rejects.toThrow('internal capture error')\n })\n })\n})\n\n/**\n * @import { IncomingMessage } from 'node:http'\n */\n"],"mappings":"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","ignoreList":[]}