@ons/design-system 70.0.7 → 70.0.9

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 (454) hide show
  1. package/README.md +11 -17
  2. package/components/access-code/_macro.njk +31 -25
  3. package/components/access-code/_macro.spec.js +145 -145
  4. package/components/access-code/access-code.dom.js +5 -5
  5. package/components/access-code/access-code.js +16 -16
  6. package/components/access-code/access-code.scss +22 -22
  7. package/components/access-code/access-code.spec.js +17 -17
  8. package/components/access-code/example-access-code-error.njk +49 -37
  9. package/components/access-code/example-access-code.njk +40 -30
  10. package/components/accordion/_macro.njk +7 -6
  11. package/components/accordion/_macro.spec.js +154 -154
  12. package/components/accordion/accordion.dom.js +10 -10
  13. package/components/accordion/accordion.js +50 -50
  14. package/components/accordion/accordion.spec.js +104 -104
  15. package/components/accordion/example-accordion-open.njk +0 -1
  16. package/components/address-input/_macro.njk +23 -11
  17. package/components/address-input/_macro.spec.js +420 -420
  18. package/components/address-input/autosuggest.address.dom.js +5 -5
  19. package/components/address-input/autosuggest.address.error.js +77 -77
  20. package/components/address-input/autosuggest.address.js +354 -359
  21. package/components/address-input/autosuggest.address.setter.js +95 -95
  22. package/components/address-input/autosuggest.address.spec.js +668 -651
  23. package/components/address-input/example-address-input-editable.njk +52 -50
  24. package/components/address-input/example-address-input-manual.njk +23 -21
  25. package/components/address-input/example-address-input.njk +40 -38
  26. package/components/address-output/_address-output.scss +3 -3
  27. package/components/address-output/_macro.njk +6 -6
  28. package/components/address-output/_macro.spec.js +84 -84
  29. package/components/autosuggest/_autosuggest.scss +114 -114
  30. package/components/autosuggest/_macro.njk +57 -37
  31. package/components/autosuggest/_macro.spec.js +255 -255
  32. package/components/autosuggest/autosuggest.dom.js +5 -5
  33. package/components/autosuggest/autosuggest.helpers.js +11 -11
  34. package/components/autosuggest/autosuggest.helpers.spec.js +73 -73
  35. package/components/autosuggest/autosuggest.js +20 -20
  36. package/components/autosuggest/autosuggest.spec.js +542 -536
  37. package/components/autosuggest/autosuggest.ui.js +478 -475
  38. package/components/autosuggest/example-autosuggest-country-multiple.njk +26 -26
  39. package/components/autosuggest/example-autosuggest-country.njk +24 -24
  40. package/components/autosuggest/fuse-config.js +17 -17
  41. package/components/back-to-top/_back-to-top.scss +27 -27
  42. package/components/back-to-top/_macro.spec.js +49 -49
  43. package/components/back-to-top/back-to-top.dom.js +5 -5
  44. package/components/back-to-top/back-to-top.js +52 -52
  45. package/components/back-to-top/back-to-top.spec.js +106 -106
  46. package/components/back-to-top/example-back-to-top.njk +183 -6
  47. package/components/back-to-top/example-full-page-back-to-top.njk +135 -123
  48. package/components/breadcrumbs/_breadcrumbs.scss +63 -65
  49. package/components/breadcrumbs/_macro.njk +12 -4
  50. package/components/breadcrumbs/_macro.spec.js +91 -91
  51. package/components/browser-banner/_browser-banner.scss +23 -23
  52. package/components/browser-banner/_macro.njk +6 -3
  53. package/components/browser-banner/_macro.spec.js +92 -92
  54. package/components/button/_button.scss +525 -491
  55. package/components/button/_macro.njk +63 -62
  56. package/components/button/_macro.spec.js +363 -363
  57. package/components/button/button.dom.js +15 -15
  58. package/components/button/button.js +53 -53
  59. package/components/button/button.spec.js +248 -240
  60. package/components/button/example-button-ghost.njk +1 -0
  61. package/components/call-to-action/_call-to-action.scss +5 -5
  62. package/components/call-to-action/_macro.njk +7 -5
  63. package/components/call-to-action/_macro.spec.js +28 -28
  64. package/components/call-to-action/example-call-to-action-default.njk +3 -2
  65. package/components/card/_card.scss +23 -23
  66. package/components/card/_macro.njk +26 -10
  67. package/components/card/_macro.spec.js +180 -180
  68. package/components/card/example-card-set-with-images.njk +31 -29
  69. package/components/card/example-card-set-with-lists.njk +58 -56
  70. package/components/card/example-card-set.njk +28 -26
  71. package/components/card/example-card.njk +9 -7
  72. package/components/char-check-limit/_macro.njk +1 -3
  73. package/components/char-check-limit/_macro.spec.js +48 -48
  74. package/components/char-check-limit/character-check.js +58 -58
  75. package/components/char-check-limit/character-check.spec.js +173 -173
  76. package/components/char-check-limit/character-limit.js +40 -40
  77. package/components/checkboxes/_checkbox-macro.njk +19 -15
  78. package/components/checkboxes/_checkbox-macro.spec.js +355 -355
  79. package/components/checkboxes/_checkbox.scss +180 -180
  80. package/components/checkboxes/_checkboxes.scss +37 -27
  81. package/components/checkboxes/_macro.njk +81 -72
  82. package/components/checkboxes/_macro.spec.js +261 -261
  83. package/components/checkboxes/checkbox-with-autoselect.js +32 -32
  84. package/components/checkboxes/checkbox-with-fieldset.js +21 -21
  85. package/components/checkboxes/checkboxes-with-reveal.js +10 -10
  86. package/components/checkboxes/checkboxes.dom.js +27 -27
  87. package/components/checkboxes/checkboxes.spec.js +183 -183
  88. package/components/checkboxes/example-checkboxes-disabled.njk +30 -30
  89. package/components/checkboxes/example-checkboxes-error.njk +0 -1
  90. package/components/checkboxes/example-checkboxes-with-descriptions.njk +7 -5
  91. package/components/checkboxes/example-checkboxes-with-hidden-label.njk +162 -170
  92. package/components/checkboxes/example-checkboxes-with-revealed-checkboxes-expanded.njk +81 -81
  93. package/components/checkboxes/example-checkboxes-with-revealed-checkboxes.njk +79 -79
  94. package/components/checkboxes/example-checkboxes-with-revealed-select-expanded.njk +7 -5
  95. package/components/checkboxes/example-checkboxes-with-revealed-select.njk +7 -5
  96. package/components/checkboxes/example-checkboxes-with-revealed-text-input-expanded.njk +7 -5
  97. package/components/checkboxes/example-checkboxes-with-revealed-text-input.njk +7 -5
  98. package/components/checkboxes/example-checkboxes-with-select-all-button.njk +7 -5
  99. package/components/checkboxes/example-checkboxes-with-visible-text-input.njk +7 -5
  100. package/components/checkboxes/example-checkboxes.njk +7 -5
  101. package/components/content-pagination/_content-pagination.scss +41 -41
  102. package/components/content-pagination/_macro.njk +34 -32
  103. package/components/content-pagination/_macro.spec.js +159 -159
  104. package/components/content-pagination/example-content-pagination.njk +17 -17
  105. package/components/cookies-banner/_cookies-banner.scss +22 -22
  106. package/components/cookies-banner/_macro.njk +19 -6
  107. package/components/cookies-banner/_macro.spec.js +177 -177
  108. package/components/cookies-banner/cookies-banner.dom.js +7 -7
  109. package/components/cookies-banner/cookies-banner.js +76 -76
  110. package/components/cookies-banner/cookies-banner.spec.js +72 -68
  111. package/components/cookies-banner/example-cookies-banner-cymraeg.njk +2 -1
  112. package/components/cookies-banner/example-cookies-banner.njk +3 -4
  113. package/components/date-input/_macro.njk +71 -63
  114. package/components/date-input/_macro.spec.js +338 -338
  115. package/components/date-input/example-date-input-error-for-single-field.njk +0 -1
  116. package/components/date-input/example-date-input-error.njk +0 -1
  117. package/components/description-list/_description-list.scss +23 -23
  118. package/components/description-list/_macro.njk +20 -11
  119. package/components/description-list/_macro.spec.js +144 -144
  120. package/components/details/_details.scss +109 -109
  121. package/components/details/_macro.njk +18 -11
  122. package/components/details/_macro.spec.js +132 -132
  123. package/components/details/details.dom.js +6 -6
  124. package/components/details/details.js +60 -60
  125. package/components/details/details.spec.js +106 -106
  126. package/components/details/example-details-with-warning.njk +15 -10
  127. package/components/document-list/_macro.njk +102 -93
  128. package/components/document-list/_macro.spec.js +444 -444
  129. package/components/document-list/document-list.scss +145 -149
  130. package/components/document-list/example-document-list-article-featured.njk +27 -25
  131. package/components/document-list/example-document-list-articles.njk +55 -53
  132. package/components/document-list/example-document-list-downloads.njk +49 -47
  133. package/components/document-list/example-document-list-search-result-featured.njk +19 -17
  134. package/components/document-list/example-document-list-search-results.njk +60 -58
  135. package/components/download-resources/_download-resources.scss +109 -108
  136. package/components/download-resources/download-resources.js +907 -900
  137. package/components/download-resources/download-resources.spec.js +461 -461
  138. package/components/duration/_macro.njk +61 -55
  139. package/components/duration/_macro.spec.js +291 -291
  140. package/components/duration/example-duration-error-for-single-field.njk +28 -26
  141. package/components/duration/example-duration-single-field.njk +23 -19
  142. package/components/duration/example-duration.njk +33 -29
  143. package/components/error/_macro.njk +8 -6
  144. package/components/error/_macro.spec.js +72 -72
  145. package/components/external-link/_external-link.scss +19 -19
  146. package/components/external-link/_macro.njk +7 -5
  147. package/components/external-link/_macro.spec.js +68 -68
  148. package/components/external-link/example-external-link.njk +9 -6
  149. package/components/feedback/_feedback.scss +31 -31
  150. package/components/feedback/_macro.njk +7 -5
  151. package/components/feedback/_macro.spec.js +72 -72
  152. package/components/field/_field-group.scss +10 -10
  153. package/components/field/_field.scss +16 -16
  154. package/components/field/_macro.njk +2 -2
  155. package/components/field/_macro.spec.js +80 -80
  156. package/components/fieldset/_fieldset.scss +27 -27
  157. package/components/fieldset/_macro.njk +23 -16
  158. package/components/fieldset/_macro.spec.js +161 -161
  159. package/components/footer/_footer.scss +45 -45
  160. package/components/footer/_macro.njk +28 -21
  161. package/components/footer/_macro.spec.js +452 -452
  162. package/components/footer/example-footer-cymraeg.njk +2 -1
  163. package/components/footer/example-footer-default.njk +3 -4
  164. package/components/footer/example-footer-transactional.njk +2 -1
  165. package/components/footer/example-footer-warning.njk +2 -1
  166. package/components/footer/example-footer-with-alternative-organisation.njk +2 -1
  167. package/components/footer/example-footer-with-coat-of-arms.njk +2 -1
  168. package/components/footer/example-footer-with-copyright.njk +2 -1
  169. package/components/footer/example-footer.njk +2 -1
  170. package/components/header/_header.scss +207 -202
  171. package/components/header/_macro.njk +183 -141
  172. package/components/header/_macro.spec.js +833 -829
  173. package/components/header/example-header-default.njk +2 -1
  174. package/components/header/example-header-external-for-survey-with-description.njk +2 -1
  175. package/components/header/example-header-external-for-surveys.njk +2 -1
  176. package/components/header/example-header-external-welsh.njk +7 -7
  177. package/components/header/example-header-external-with-navigation-and-search.njk +3 -2
  178. package/components/header/example-header-external-with-navigation.njk +2 -1
  179. package/components/header/example-header-external-with-service-links.njk +2 -1
  180. package/components/header/example-header-external-with-sub-navigation-removed.njk +2 -1
  181. package/components/header/example-header-external-with-sub-navigation.njk +3 -2
  182. package/components/header/example-header-internal.njk +2 -1
  183. package/components/header/example-header-multiple-logos.njk +2 -1
  184. package/components/header/{example-header-neutral-for-multicoloured-logo.njk → example-header-neutral.njk} +2 -1
  185. package/components/helpers/_grid.scss +4 -4
  186. package/components/helpers/grid.njk +17 -16
  187. package/components/hero/_hero.scss +48 -48
  188. package/components/hero/_macro.njk +6 -11
  189. package/components/hero/_macro.spec.js +59 -59
  190. package/components/hero/example-hero-dark.njk +2 -1
  191. package/components/hero/example-hero-default.njk +2 -1
  192. package/components/icon/_icon.scss +44 -44
  193. package/components/icon/_macro.njk +601 -168
  194. package/components/icon/_macro.spec.js +110 -110
  195. package/components/image/_image.scss +11 -11
  196. package/components/image/_macro.njk +7 -5
  197. package/components/image/_macro.spec.js +81 -81
  198. package/components/input/_input-type.scss +86 -89
  199. package/components/input/_input.scss +123 -124
  200. package/components/input/_macro.njk +114 -95
  201. package/components/input/_macro.spec.js +604 -604
  202. package/components/input/character-check.dom.js +5 -5
  203. package/components/input/example-input-search-with-character-check.njk +1 -1
  204. package/components/input/example-input-search-with-placeholder.njk +1 -1
  205. package/components/input/example-input-search.njk +1 -1
  206. package/components/input/input.dom.js +5 -5
  207. package/components/input/input.js +10 -10
  208. package/components/input/input.spec.js +18 -18
  209. package/components/label/_label.scss +24 -24
  210. package/components/label/_macro.njk +32 -26
  211. package/components/label/_macro.spec.js +173 -170
  212. package/components/language-selector/_macro.njk +11 -2
  213. package/components/language-selector/_macro.spec.js +97 -97
  214. package/components/language-selector/language.scss +7 -7
  215. package/components/list/_list.scss +110 -97
  216. package/components/list/_macro.njk +93 -73
  217. package/components/list/_macro.spec.js +583 -583
  218. package/components/message/_macro.njk +20 -7
  219. package/components/message/_macro.spec.js +74 -74
  220. package/components/message/_message.scss +39 -39
  221. package/components/message-list/_macro.njk +26 -20
  222. package/components/message-list/_macro.spec.js +86 -86
  223. package/components/message-list/_message-list.scss +16 -16
  224. package/components/modal/_macro.njk +11 -12
  225. package/components/modal/_macro.spec.js +69 -69
  226. package/components/modal/_modal.scss +36 -36
  227. package/components/modal/modal.dom.js +6 -6
  228. package/components/modal/modal.js +89 -89
  229. package/components/modal/modal.spec.js +50 -50
  230. package/components/multiple-input-fields/_macro.njk +30 -28
  231. package/components/mutually-exclusive/_macro.njk +20 -13
  232. package/components/mutually-exclusive/_macro.spec.js +140 -140
  233. package/components/mutually-exclusive/example-mutually-exclusive-checkboxes.njk +6 -4
  234. package/components/mutually-exclusive/example-mutually-exclusive-date.njk +7 -5
  235. package/components/mutually-exclusive/example-mutually-exclusive-duration.njk +44 -40
  236. package/components/mutually-exclusive/example-mutually-exclusive-email.njk +7 -5
  237. package/components/mutually-exclusive/example-mutually-exclusive-multiple-options.njk +6 -4
  238. package/components/mutually-exclusive/example-mutually-exclusive-number.njk +6 -4
  239. package/components/mutually-exclusive/example-mutually-exclusive-textarea.njk +6 -4
  240. package/components/mutually-exclusive/mutually-exclusive.checkboxes.spec.js +188 -188
  241. package/components/mutually-exclusive/mutually-exclusive.date.spec.js +211 -211
  242. package/components/mutually-exclusive/mutually-exclusive.dom.js +5 -5
  243. package/components/mutually-exclusive/mutually-exclusive.duration.spec.js +210 -210
  244. package/components/mutually-exclusive/mutually-exclusive.email.spec.js +90 -90
  245. package/components/mutually-exclusive/mutually-exclusive.js +137 -137
  246. package/components/mutually-exclusive/mutually-exclusive.multiple-options.checkboxes.spec.js +197 -197
  247. package/components/mutually-exclusive/mutually-exclusive.number.spec.js +96 -96
  248. package/components/mutually-exclusive/mutually-exclusive.textarea.spec.js +102 -102
  249. package/components/navigation/_macro.njk +133 -67
  250. package/components/navigation/_macro.spec.js +360 -354
  251. package/components/navigation/_navigation.scss +112 -122
  252. package/components/navigation/navigation.dom.js +35 -35
  253. package/components/navigation/navigation.js +49 -49
  254. package/components/navigation/navigation.spec.js +249 -249
  255. package/components/pagination/_macro.njk +42 -20
  256. package/components/pagination/_macro.spec.js +342 -335
  257. package/components/pagination/_pagination.scss +58 -58
  258. package/components/panel/_macro.njk +27 -16
  259. package/components/panel/_macro.spec.js +372 -372
  260. package/components/panel/_panel.scss +200 -199
  261. package/components/panel/example-panel-bare.njk +6 -4
  262. package/components/panel/example-panel-with-announcement.njk +7 -4
  263. package/components/panel/example-panel-with-error-summary.njk +6 -4
  264. package/components/panel/example-panel-with-warning.njk +5 -3
  265. package/components/password/_macro.njk +7 -5
  266. package/components/password/_macro.spec.js +95 -95
  267. package/components/password/password.dom.js +5 -5
  268. package/components/password/password.js +10 -10
  269. package/components/password/password.spec.js +26 -26
  270. package/components/phase-banner/_macro.njk +3 -3
  271. package/components/phase-banner/_macro.spec.js +86 -86
  272. package/components/phase-banner/_phase-banner.scss +16 -16
  273. package/components/phase-banner/example-phase-banner-alpha.njk +2 -1
  274. package/components/phase-banner/example-phase-banner-beta.njk +4 -3
  275. package/components/question/_macro.njk +62 -47
  276. package/components/question/_macro.spec.js +235 -235
  277. package/components/question/_question.scss +24 -24
  278. package/components/question/example-question-ccs.njk +40 -35
  279. package/components/question/example-question-fieldset.njk +84 -80
  280. package/components/question/example-question-interviewer-note.njk +27 -24
  281. package/components/question/example-question-no-fieldset.njk +39 -33
  282. package/components/quote/_macro.njk +3 -1
  283. package/components/quote/_macro.spec.js +52 -52
  284. package/components/quote/_quote.scss +24 -24
  285. package/components/radios/_macro.njk +54 -36
  286. package/components/radios/_macro.spec.js +545 -524
  287. package/components/radios/_radio.scss +49 -48
  288. package/components/radios/_radios.scss +14 -20
  289. package/components/radios/check-radios.js +21 -21
  290. package/components/radios/clear-radios.js +45 -45
  291. package/components/radios/example-radios-with-clear-button-expanded.njk +6 -4
  292. package/components/radios/example-radios-with-clear-button.njk +6 -4
  293. package/components/radios/example-radios-with-descriptions.njk +7 -5
  294. package/components/radios/example-radios-with-revealed-select-expanded.njk +6 -4
  295. package/components/radios/example-radios-with-revealed-select.njk +6 -4
  296. package/components/radios/example-radios-with-revealed-text-area-expanded.njk +7 -5
  297. package/components/radios/example-radios-with-revealed-text-area.njk +7 -5
  298. package/components/radios/example-radios-with-revealed-text-input-expanded.njk +7 -5
  299. package/components/radios/example-radios-with-revealed-text-input.njk +7 -5
  300. package/components/radios/example-radios-with-separator.njk +6 -4
  301. package/components/radios/example-radios-with-visible-text-input.njk +7 -5
  302. package/components/radios/example-radios-without-border.njk +0 -1
  303. package/components/radios/example-radios.njk +7 -5
  304. package/components/radios/radio-with-fieldset.js +22 -22
  305. package/components/radios/radios.dom.js +32 -32
  306. package/components/radios/radios.spec.js +251 -251
  307. package/components/related-content/_macro.njk +10 -11
  308. package/components/related-content/_macro.spec.js +109 -109
  309. package/components/related-content/_related-content.scss +12 -12
  310. package/components/related-content/_section-macro.njk +7 -7
  311. package/components/related-content/_section-macro.spec.js +20 -20
  312. package/components/related-content/example-related-content-general.njk +5 -3
  313. package/components/related-content/example-related-content-multiple-rows-of-links.njk +51 -49
  314. package/components/related-content/example-related-content-social-media.njk +40 -38
  315. package/components/relationships/_macro.njk +10 -8
  316. package/components/relationships/_macro.spec.js +94 -94
  317. package/components/relationships/_relationships.scss +9 -9
  318. package/components/relationships/example-relationships-error.njk +176 -168
  319. package/components/relationships/example-relationships-you.njk +169 -163
  320. package/components/relationships/example-relationships.njk +167 -161
  321. package/components/relationships/relationships.dom.js +5 -5
  322. package/components/relationships/relationships.js +18 -18
  323. package/components/relationships/relationships.spec.js +71 -71
  324. package/components/reply/_macro.spec.js +47 -47
  325. package/components/reply/reply-input.js +15 -15
  326. package/components/reply/reply.dom.js +5 -5
  327. package/components/reply/reply.spec.js +57 -57
  328. package/components/section-navigation/_macro.njk +34 -12
  329. package/components/section-navigation/_macro.spec.js +210 -210
  330. package/components/section-navigation/_section-navigation.scss +76 -76
  331. package/components/select/_macro.njk +21 -18
  332. package/components/select/_macro.spec.js +166 -166
  333. package/components/share-page/_macro.njk +10 -5
  334. package/components/share-page/_macro.spec.js +68 -68
  335. package/components/skip-to-content/_macro.njk +1 -1
  336. package/components/skip-to-content/_macro.spec.js +54 -54
  337. package/components/skip-to-content/_skip.scss +30 -30
  338. package/components/skip-to-content/example-skip-to-content.njk +1 -0
  339. package/components/skip-to-content/skip-to-content.dom.js +6 -6
  340. package/components/skip-to-content/skip-to-content.js +7 -7
  341. package/components/skip-to-content/skip-to-content.spec.js +21 -21
  342. package/components/status/_macro.njk +1 -1
  343. package/components/status/_macro.spec.js +53 -53
  344. package/components/status/_status.scss +32 -32
  345. package/components/summary/_macro.njk +53 -23
  346. package/components/summary/_macro.spec.js +551 -535
  347. package/components/summary/_summary.scss +191 -195
  348. package/components/summary/example-summary-household-no-rows.njk +18 -16
  349. package/components/summary/example-summary-household.njk +75 -73
  350. package/components/summary/example-summary-hub-minimal.njk +74 -72
  351. package/components/summary/example-summary-hub.njk +169 -167
  352. package/components/table/_macro.njk +72 -45
  353. package/components/table/_macro.spec.js +499 -499
  354. package/components/table/_table.scss +204 -201
  355. package/components/table/scrollable-table.dom.js +5 -5
  356. package/components/table/scrollable-table.js +60 -60
  357. package/components/table/sortable-table.dom.js +5 -5
  358. package/components/table/sortable-table.js +135 -135
  359. package/components/table/table.spec.js +144 -140
  360. package/components/table-of-contents/_macro.njk +34 -32
  361. package/components/table-of-contents/_macro.spec.js +125 -125
  362. package/components/table-of-contents/_toc.scss +9 -9
  363. package/components/table-of-contents/example-table-of-contents-grouped.njk +1 -1
  364. package/components/table-of-contents/example-table-of-contents-single.njk +1 -1
  365. package/components/table-of-contents/example-table-of-contents-sticky-full-page.njk +79 -38
  366. package/components/table-of-contents/example-table-of-contents-sticky.njk +50 -13
  367. package/components/table-of-contents/toc.dom.js +5 -5
  368. package/components/table-of-contents/toc.js +30 -30
  369. package/components/table-of-contents/toc.spec.js +88 -88
  370. package/components/tabs/_macro.njk +12 -6
  371. package/components/tabs/_macro.spec.js +92 -92
  372. package/components/tabs/_tabs.scss +120 -115
  373. package/components/tabs/example-tabs-details.njk +5 -6
  374. package/components/tabs/tabs.dom.js +5 -5
  375. package/components/tabs/tabs.js +266 -266
  376. package/components/tabs/tabs.spec.js +268 -268
  377. package/components/text-indent/_macro.njk +1 -3
  378. package/components/text-indent/_macro.spec.js +33 -33
  379. package/components/text-indent/_text-indent.scss +3 -3
  380. package/components/textarea/_macro.njk +49 -46
  381. package/components/textarea/_macro.spec.js +227 -238
  382. package/components/textarea/textarea.dom.js +5 -5
  383. package/components/textarea/textarea.spec.js +78 -74
  384. package/components/timeline/_macro.njk +4 -6
  385. package/components/timeline/_macro.spec.js +83 -83
  386. package/components/timeline/_timeline.scss +26 -26
  387. package/components/timeout-modal/_macro.njk +21 -19
  388. package/components/timeout-modal/_macro.spec.js +47 -47
  389. package/components/timeout-modal/example-timeout-modal.njk +16 -14
  390. package/components/timeout-modal/timeout-modal.dom.js +9 -9
  391. package/components/timeout-modal/timeout-modal.js +66 -66
  392. package/components/timeout-modal/timeout-modal.spec.js +157 -157
  393. package/components/timeout-panel/_macro.njk +19 -17
  394. package/components/timeout-panel/_macro.spec.js +41 -41
  395. package/components/timeout-panel/example-panel-with-timeout-warning.njk +13 -11
  396. package/components/timeout-panel/timeout-panel.dom.js +8 -8
  397. package/components/timeout-panel/timeout-panel.spec.js +118 -118
  398. package/components/upload/_macro.njk +20 -16
  399. package/components/upload/_macro.spec.js +52 -52
  400. package/components/upload/_upload.scss +28 -28
  401. package/components/video/_macro.njk +16 -2
  402. package/components/video/_macro.spec.js +42 -42
  403. package/components/video/_video.scss +16 -16
  404. package/components/video/example-video.njk +2 -2
  405. package/components/video/video.dom.js +5 -5
  406. package/components/video/video.js +32 -32
  407. package/components/video/video.spec.js +103 -97
  408. package/css/main.css +1 -1
  409. package/favicons/manifest.json +25 -25
  410. package/js/abortable-fetch.js +23 -23
  411. package/js/analytics.js +53 -53
  412. package/js/cookies-functions.js +135 -135
  413. package/js/cookies-settings.dom.js +7 -7
  414. package/js/cookies-settings.js +77 -77
  415. package/js/cookies-settings.spec.js +106 -106
  416. package/js/domready.js +8 -8
  417. package/js/fetch.js +14 -14
  418. package/js/inpagelink.dom.js +5 -5
  419. package/js/inpagelink.js +19 -19
  420. package/js/polyfills.js +0 -1
  421. package/js/print-button.js +6 -6
  422. package/js/timeout.js +211 -211
  423. package/layout/_dsTemplate.njk +22 -20
  424. package/layout/_template.njk +63 -51
  425. package/package.json +132 -128
  426. package/scripts/main.es5.js +1 -1
  427. package/scripts/main.js +1 -1
  428. package/scss/base/_forms.scss +10 -10
  429. package/scss/base/_global.scss +45 -44
  430. package/scss/base/_typography.scss +20 -20
  431. package/scss/helpers/_functions.scss +18 -15
  432. package/scss/helpers/_mixins.scss +59 -53
  433. package/scss/helpers/_mq.scss +62 -65
  434. package/scss/objects/_container.scss +20 -20
  435. package/scss/objects/_page.scss +33 -33
  436. package/scss/objects/_spacing.scss +10 -10
  437. package/scss/overrides/hcm.scss +237 -237
  438. package/scss/overrides/rtl.scss +95 -95
  439. package/scss/print.scss +47 -47
  440. package/scss/utilities/_border.scss +7 -7
  441. package/scss/utilities/_colors.scss +6 -6
  442. package/scss/utilities/_display.scss +8 -8
  443. package/scss/utilities/_float.scss +7 -7
  444. package/scss/utilities/_grid.scss +144 -144
  445. package/scss/utilities/_highlight.scss +4 -4
  446. package/scss/utilities/_margin.scss +17 -17
  447. package/scss/utilities/_pad.scss +15 -15
  448. package/scss/utilities/_typography.scss +35 -33
  449. package/scss/utilities/_utilities.scss +8 -8
  450. package/scss/utilities/_visibility.scss +25 -25
  451. package/scss/vars/_colors.scss +116 -116
  452. package/scss/vars/_forms.scss +22 -22
  453. package/scss/vars/_grid.scss +11 -9
  454. package/scss/vars/_typography.scss +54 -54
@@ -6,693 +6,693 @@ import axe from '../../tests/helpers/axe';
6
6
  import { renderComponent, templateFaker } from '../../tests/helpers/rendering';
7
7
 
8
8
  const EXAMPLE_INPUT_MINIMAL = {
9
- id: 'example-id',
10
- name: 'example-name',
9
+ id: 'example-id',
10
+ name: 'example-name',
11
11
  };
12
12
 
13
13
  const EXAMPLE_INPUT_WITH_LABEL = {
14
- ...EXAMPLE_INPUT_MINIMAL,
15
- label: {
16
- id: 'example-input-label',
17
- text: 'Example input label',
18
- classes: 'extra-label-class',
19
- description: 'Example input label description',
20
- attributes: { a: 42 },
21
- inline: false,
22
- },
23
- accessiblePlaceholder: true,
14
+ ...EXAMPLE_INPUT_MINIMAL,
15
+ label: {
16
+ id: 'example-input-label',
17
+ text: 'Example input label',
18
+ classes: 'extra-label-class',
19
+ description: 'Example input label description',
20
+ attributes: { a: 42 },
21
+ inline: false,
22
+ },
23
+ accessiblePlaceholder: true,
24
24
  };
25
25
 
26
26
  const EXAMPLE_INPUT_WITH_ERROR = {
27
- ...EXAMPLE_INPUT_WITH_LABEL,
28
- error: {
29
- id: 'feedback-error',
30
- text: 'Enter your feedback',
31
- },
27
+ ...EXAMPLE_INPUT_WITH_LABEL,
28
+ error: {
29
+ id: 'feedback-error',
30
+ text: 'Enter your feedback',
31
+ },
32
32
  };
33
33
 
34
34
  const EXAMPLE_WITH_SEARCH = {
35
- ...EXAMPLE_INPUT_MINIMAL,
36
- accessiblePlaceholder: true,
37
- searchButton: {
38
- type: 'button',
39
- text: 'Search for address',
40
- id: 'search-for-address',
41
- attributes: { a: 42 },
42
- classes: 'extra-search-button-class',
43
- iconType: 'search',
44
- visuallyHideButtonText: true,
45
- },
35
+ ...EXAMPLE_INPUT_MINIMAL,
36
+ accessiblePlaceholder: true,
37
+ searchButton: {
38
+ type: 'button',
39
+ text: 'Search for address',
40
+ id: 'search-for-address',
41
+ attributes: { a: 42 },
42
+ classes: 'extra-search-button-class',
43
+ iconType: 'search',
44
+ visuallyHideButtonText: true,
45
+ },
46
46
  };
47
47
 
48
48
  const EXAMPLE_INPUT_WITH_CHARACTER_LIMIT = {
49
- ...EXAMPLE_INPUT_MINIMAL,
50
- minLength: 10,
51
- maxLength: 200,
52
- charCheckLimit: {
53
- limit: 200,
54
- charCountSingular: 'You have {x} character remaining',
55
- charCountPlural: 'You have {x} characters remaining',
56
- charCountOverLimitSingular: '{x} character too many',
57
- charCountOverLimitPlural: '{x} characters too many',
58
- },
49
+ ...EXAMPLE_INPUT_MINIMAL,
50
+ minLength: 10,
51
+ maxLength: 200,
52
+ charCheckLimit: {
53
+ limit: 200,
54
+ charCountSingular: 'You have {x} character remaining',
55
+ charCountPlural: 'You have {x} characters remaining',
56
+ charCountOverLimitSingular: '{x} character too many',
57
+ charCountOverLimitPlural: '{x} characters too many',
58
+ },
59
59
  };
60
60
 
61
61
  const EXAMPLE_INPUT_WITH_MUTUALLY_EXCLUSIVE_WITH_ERROR = {
62
- ...EXAMPLE_INPUT_WITH_ERROR,
63
- dontWrap: true,
64
- mutuallyExclusive: {
65
- or: 'Or',
66
- deselectMessage: 'Selecting this will clear your feedback',
67
- deselectGroupAdjective: 'cleared',
68
- deselectExclusiveOptionAdjective: 'deselected',
69
- exclusiveOptions: [
70
- {
71
- id: 'feedback-exclusive-option',
72
- name: 'no-feedback',
73
- value: 'no-feedback',
74
- label: {
75
- text: 'I dont want to provide feedback',
76
- },
77
- },
78
- ],
79
- },
62
+ ...EXAMPLE_INPUT_WITH_ERROR,
63
+ dontWrap: true,
64
+ mutuallyExclusive: {
65
+ or: 'Or',
66
+ deselectMessage: 'Selecting this will clear your feedback',
67
+ deselectGroupAdjective: 'cleared',
68
+ deselectExclusiveOptionAdjective: 'deselected',
69
+ exclusiveOptions: [
70
+ {
71
+ id: 'feedback-exclusive-option',
72
+ name: 'no-feedback',
73
+ value: 'no-feedback',
74
+ label: {
75
+ text: 'I dont want to provide feedback',
76
+ },
77
+ },
78
+ ],
79
+ },
80
80
  };
81
81
 
82
82
  describe('macro: input', () => {
83
- it('passes jest-axe checks', async () => {
84
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_LABEL));
85
-
86
- const results = await axe($.html());
87
- expect(results).toHaveNoViolations();
88
- });
89
-
90
- it('has the provided `id` attribute', () => {
91
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
92
-
93
- expect($('.ons-input').attr('id')).toBe('example-id');
94
- });
95
-
96
- it('has the provided `name` attribute', () => {
97
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
98
-
99
- expect($('.ons-input').attr('name')).toBe('example-name');
100
- });
101
-
102
- it('has additionally provided `attributes`', () => {
103
- const $ = cheerio.load(
104
- renderComponent('input', {
105
- ...EXAMPLE_INPUT_MINIMAL,
106
- attributes: { a: '123', b: '456' },
107
- }),
108
- );
109
-
110
- expect($('.ons-input').attr('a')).toBe('123');
111
- expect($('.ons-input').attr('b')).toBe('456');
112
- });
113
-
114
- it('outputs number type in a way that works with more browsers', () => {
115
- const $ = cheerio.load(
116
- renderComponent('input', {
117
- ...EXAMPLE_INPUT_MINIMAL,
118
- type: 'number',
119
- }),
120
- );
121
-
122
- expect($('.ons-input').attr('type')).toBe('text');
123
- expect($('.ons-input').attr('pattern')).toBe('[0-9]*');
124
- expect($('.ons-input').attr('inputmode')).toBe('numeric');
125
- });
126
-
127
- it('has additionally provided style classes', () => {
128
- const $ = cheerio.load(
129
- renderComponent('input', {
130
- ...EXAMPLE_INPUT_MINIMAL,
131
- classes: 'extra-class another-extra-class',
132
- }),
133
- );
134
-
135
- expect($('.ons-input').hasClass('extra-class')).toBe(true);
136
- expect($('.ons-input').hasClass('another-extra-class')).toBe(true);
137
- });
138
-
139
- it('does not have "placeholder" modifier', () => {
140
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
141
-
142
- expect($('.ons-input').hasClass('ons-input--placeholder')).toBe(false);
143
- });
144
-
145
- it('has "placeholder" modifier when `accessiblePlaceholder` is provided', () => {
146
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_LABEL));
147
-
148
- expect($('.ons-input').hasClass('ons-input--placeholder')).toBe(true);
149
- });
150
-
151
- it('does not have `placeholder` attribute', () => {
152
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
153
-
154
- expect($('.ons-input').attr('placeholder')).toBeUndefined();
155
- });
156
-
157
- it('has `placeholder` attribute when `placeholder` is provided', () => {
158
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_LABEL));
159
-
160
- expect($('.ons-input').attr('placeholder')).toBe('Example input label');
161
- });
162
-
163
- it('does not have `min` attribute', () => {
164
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
165
-
166
- expect($('.ons-input').attr('min')).toBeUndefined();
167
- });
168
-
169
- it('has `min` attribute when `min` is provided', () => {
170
- const $ = cheerio.load(
171
- renderComponent('input', {
172
- ...EXAMPLE_INPUT_MINIMAL,
173
- min: 10,
174
- }),
175
- );
176
-
177
- expect($('.ons-input').attr('min')).toBe('10');
178
- });
179
-
180
- it('does not have `max` attribute', () => {
181
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
182
-
183
- expect($('.ons-input').attr('max')).toBeUndefined();
184
- });
185
-
186
- it('has `max` attribute when `max` is provided', () => {
187
- const $ = cheerio.load(
188
- renderComponent('input', {
189
- ...EXAMPLE_INPUT_MINIMAL,
190
- max: 100,
191
- }),
192
- );
193
-
194
- expect($('.ons-input').attr('max')).toBe('100');
195
- });
196
-
197
- it('does not have `value` attribute', () => {
198
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
199
-
200
- expect($('.ons-input').attr('value')).toBeUndefined();
201
- });
202
-
203
- it('has `value` attribute when `value` is provided', () => {
204
- const $ = cheerio.load(
205
- renderComponent('input', {
206
- ...EXAMPLE_INPUT_MINIMAL,
207
- value: '100',
208
- }),
209
- );
210
-
211
- expect($('.ons-input').attr('value')).toBe('100');
212
- });
213
-
214
- it('does not have `accept` attribute', () => {
215
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
216
-
217
- expect($('.ons-input').attr('accept')).toBeUndefined();
218
- });
219
-
220
- it('has `accept` attribute when `accept` is provided', () => {
221
- const $ = cheerio.load(
222
- renderComponent('input', {
223
- ...EXAMPLE_INPUT_MINIMAL,
224
- accept: 'image/*',
225
- }),
226
- );
227
-
228
- expect($('.ons-input').attr('accept')).toBe('image/*');
229
- });
230
-
231
- it('does not have `autocomplete` attribute', () => {
232
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
233
-
234
- expect($('.ons-input').attr('autocomplete')).toBeUndefined();
235
- });
236
-
237
- it('has `autocomplete` attribute when `autocomplete` is provided', () => {
238
- const $ = cheerio.load(
239
- renderComponent('input', {
240
- ...EXAMPLE_INPUT_MINIMAL,
241
- autocomplete: 'on',
242
- }),
243
- );
244
-
245
- expect($('.ons-input').attr('autocomplete')).toBe('on');
246
- });
247
-
248
- it.each([['email'], ['tel'], ['text']])('outputs `type` attribute of "%s"', (type) => {
249
- const $ = cheerio.load(
250
- renderComponent('input', {
251
- ...EXAMPLE_INPUT_MINIMAL,
252
- type,
253
- }),
254
- );
255
-
256
- expect($('.ons-input').attr('type')).toBe(type);
257
- expect($('.ons-input').attr('pattern')).toBeUndefined();
258
- expect($('.ons-input').attr('inputmode')).toBeUndefined();
259
- });
260
-
261
- it.each([
262
- ['number', 10, 'ons-input-number--w-10'],
263
- ['tel', 20, 'ons-input-number--w-20'],
264
- ])('adds class "ons-input-number" when `type` is "%s"', (type, width, expectedClass) => {
265
- const $ = cheerio.load(
266
- renderComponent('input', {
267
- ...EXAMPLE_INPUT_MINIMAL,
268
- type,
269
- width,
270
- }),
271
- );
272
-
273
- expect($('.ons-input').hasClass(expectedClass)).toBe(true);
274
- });
275
-
276
- describe('listeners', () => {
277
- it('renders each listener', () => {
278
- const $ = cheerio.load(
279
- renderComponent('input', {
280
- ...EXAMPLE_INPUT_MINIMAL,
281
- listeners: {
282
- click: `alert('Input was clicked')`,
283
- keypress: `alert('Key was pressed')`,
284
- },
285
- }),
286
- );
287
-
288
- const script = $('script').html();
289
- expect(script).toContain(
290
- `document.getElementById("example-id").addEventListener('click', function(){ alert('Input was clicked') });`,
291
- );
292
- expect(script).toContain(
293
- `document.getElementById("example-id").addEventListener('keypress', function(){ alert('Key was pressed') });`,
294
- );
295
- });
296
- });
297
-
298
- it('renders field component', () => {
299
- const faker = templateFaker();
300
- const fieldSpy = faker.spy('field');
301
-
302
- faker.renderComponent('input', {
303
- ...EXAMPLE_INPUT_WITH_ERROR,
304
- fieldId: 'example-field-id',
305
- fieldClasses: 'extra-field-class',
306
- dontWrap: true,
307
- });
83
+ it('passes jest-axe checks', async () => {
84
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_LABEL));
308
85
 
309
- expect(fieldSpy.occurrences).toContainEqual({
310
- id: 'example-field-id',
311
- classes: 'extra-field-class',
312
- dontWrap: true,
313
- error: EXAMPLE_INPUT_WITH_ERROR.error,
314
- inline: false,
86
+ const results = await axe($.html());
87
+ expect(results).toHaveNoViolations();
315
88
  });
316
- });
317
89
 
318
- describe('label', () => {
319
- it('does not output a label when `label` is not provided', () => {
320
- const faker = templateFaker();
321
- const labelSpy = faker.spy('label');
90
+ it('has the provided `id` attribute', () => {
91
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
322
92
 
323
- faker.renderComponent('input', EXAMPLE_INPUT_MINIMAL);
324
-
325
- expect(labelSpy.occurrences.length).toBe(0);
93
+ expect($('.ons-input').attr('id')).toBe('example-id');
326
94
  });
327
95
 
328
- it('outputs a label when `label` is provided', () => {
329
- const faker = templateFaker();
330
- const labelSpy = faker.spy('label');
331
-
332
- faker.renderComponent('input', EXAMPLE_INPUT_WITH_LABEL);
96
+ it('has the provided `name` attribute', () => {
97
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
333
98
 
334
- expect(labelSpy.occurrences).toContainEqual({
335
- for: 'example-id',
336
- id: 'example-input-label',
337
- text: 'Example input label',
338
- classes: 'extra-label-class',
339
- description: 'Example input label description',
340
- attributes: { a: 42 },
341
- inline: false,
342
- accessiblePlaceholder: true,
343
- });
99
+ expect($('.ons-input').attr('name')).toBe('example-name');
344
100
  });
345
101
 
346
- it('outputs `aria-describedby` attribute referencing the label', () => {
347
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_LABEL));
102
+ it('has additionally provided `attributes`', () => {
103
+ const $ = cheerio.load(
104
+ renderComponent('input', {
105
+ ...EXAMPLE_INPUT_MINIMAL,
106
+ attributes: { a: '123', b: '456' },
107
+ }),
108
+ );
348
109
 
349
- expect($('.ons-input').attr('aria-describedby')).toBe('example-input-label-description-hint');
110
+ expect($('.ons-input').attr('a')).toBe('123');
111
+ expect($('.ons-input').attr('b')).toBe('456');
350
112
  });
351
113
 
352
- it('outputs a default `aria-describedby` attribute referencing the label when label does not have an `id`', () => {
353
- const $ = cheerio.load(
354
- renderComponent('input', {
355
- ...EXAMPLE_INPUT_MINIMAL,
356
- label: {
357
- text: 'Example input label',
358
- description: 'Example input label description',
359
- },
360
- }),
361
- );
362
-
363
- expect($('.ons-input').attr('aria-describedby')).toBe('description-hint');
364
- });
365
- });
114
+ it('outputs number type in a way that works with more browsers', () => {
115
+ const $ = cheerio.load(
116
+ renderComponent('input', {
117
+ ...EXAMPLE_INPUT_MINIMAL,
118
+ type: 'number',
119
+ }),
120
+ );
366
121
 
367
- describe('prefix and suffix', () => {
368
- it('passes jest-axe checks', async () => {
369
- const $ = cheerio.load(
370
- renderComponent('input', {
371
- ...EXAMPLE_INPUT_MINIMAL,
372
- prefix: {
373
- id: 'example-prefix-id',
374
- title: 'Example prefix title',
375
- },
376
- }),
377
- );
378
-
379
- const results = await axe($.html());
380
- expect(results).toHaveNoViolations();
122
+ expect($('.ons-input').attr('type')).toBe('text');
123
+ expect($('.ons-input').attr('pattern')).toBe('[0-9]*');
124
+ expect($('.ons-input').attr('inputmode')).toBe('numeric');
381
125
  });
382
126
 
383
- it('adds `aria-labelledby` attribute when `prefix` is provided with `prefix.title`', () => {
384
- const $ = cheerio.load(
385
- renderComponent('input', {
386
- ...EXAMPLE_INPUT_MINIMAL,
387
- prefix: {
388
- id: 'example-prefix-id',
389
- title: 'Example prefix title',
390
- },
391
- }),
392
- );
393
-
394
- expect($('.ons-input').attr('aria-labelledby')).toBe('example-id example-prefix-id');
395
- });
127
+ it('has additionally provided style classes', () => {
128
+ const $ = cheerio.load(
129
+ renderComponent('input', {
130
+ ...EXAMPLE_INPUT_MINIMAL,
131
+ classes: 'extra-class another-extra-class',
132
+ }),
133
+ );
396
134
 
397
- it('adds `aria-labelledby` attribute when `prefix` is provided without `prefix.title`', () => {
398
- const $ = cheerio.load(
399
- renderComponent('input', {
400
- ...EXAMPLE_INPUT_MINIMAL,
401
- prefix: {
402
- id: 'example-prefix-id',
403
- },
404
- }),
405
- );
406
-
407
- expect($('.ons-input').attr('aria-labelledby')).toBe('example-prefix-id');
135
+ expect($('.ons-input').hasClass('extra-class')).toBe(true);
136
+ expect($('.ons-input').hasClass('another-extra-class')).toBe(true);
408
137
  });
409
138
 
410
- it('renders prefix element from `prefix.text`', () => {
411
- const $ = cheerio.load(
412
- renderComponent('input', {
413
- ...EXAMPLE_INPUT_MINIMAL,
414
- prefix: {
415
- id: 'example-prefix-id',
416
- title: 'Example prefix title',
417
- text: 'Example prefix text',
418
- },
419
- }),
420
- );
421
-
422
- expect($('.ons-input-type--prefix .ons-js-input-abbr').attr('id')).toBe('example-prefix-id');
423
- expect($('.ons-input-type--prefix .ons-js-input-abbr').attr('title')).toBe('Example prefix title');
424
- expect($('.ons-input-type--prefix .ons-js-input-abbr').text().trim()).toBe('Example prefix text');
425
- });
139
+ it('does not have "placeholder" modifier', () => {
140
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
426
141
 
427
- it('does not render prefix element when `prefix.id` not set', () => {
428
- const $ = cheerio.load(
429
- renderComponent('input', {
430
- ...EXAMPLE_INPUT_MINIMAL,
431
- prefix: {
432
- title: 'Example prefix title',
433
- text: 'Example prefix text',
434
- },
435
- }),
436
- );
437
-
438
- expect($('.ons-input-type--prefix').length).toBe(0);
142
+ expect($('.ons-input').hasClass('ons-input--placeholder')).toBe(false);
439
143
  });
440
144
 
441
- it('adds `aria-labelledby` attribute when `suffix` is provided', () => {
442
- const $ = cheerio.load(
443
- renderComponent('input', {
444
- ...EXAMPLE_INPUT_MINIMAL,
445
- suffix: {
446
- id: 'example-suffix-id',
447
- title: 'Example suffix title',
448
- },
449
- }),
450
- );
451
-
452
- expect($('.ons-input').attr('aria-labelledby')).toBe('example-id example-suffix-id');
453
- });
145
+ it('has "placeholder" modifier when `accessiblePlaceholder` is provided', () => {
146
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_LABEL));
454
147
 
455
- it('adds `aria-labelledby` attribute when `suffix` is provided without `suffix.title`', () => {
456
- const $ = cheerio.load(
457
- renderComponent('input', {
458
- ...EXAMPLE_INPUT_MINIMAL,
459
- suffix: {
460
- id: 'example-suffix-id',
461
- },
462
- }),
463
- );
464
-
465
- expect($('.ons-input').attr('aria-labelledby')).toBe('example-suffix-id');
148
+ expect($('.ons-input').hasClass('ons-input--placeholder')).toBe(true);
466
149
  });
467
150
 
468
- it('renders suffix element from `suffix.text`', () => {
469
- const $ = cheerio.load(
470
- renderComponent('input', {
471
- ...EXAMPLE_INPUT_MINIMAL,
472
- suffix: {
473
- id: 'example-suffix-id',
474
- title: 'Example suffix title',
475
- text: 'Example suffix text',
476
- },
477
- }),
478
- );
479
-
480
- expect($('.ons-js-input-abbr').attr('id')).toBe('example-suffix-id');
481
- expect($('.ons-js-input-abbr').attr('title')).toBe('Example suffix title');
482
- expect($('.ons-js-input-abbr').text().trim()).toBe('Example suffix text');
483
- });
151
+ it('does not have `placeholder` attribute', () => {
152
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
484
153
 
485
- it('does not render suffix element when `suffix.id` not set', () => {
486
- const $ = cheerio.load(
487
- renderComponent('input', {
488
- ...EXAMPLE_INPUT_MINIMAL,
489
- suffix: {
490
- title: 'Example suffix title',
491
- text: 'Example suffix text',
492
- },
493
- }),
494
- );
495
-
496
- expect($('.ons-input').length).toBe(0);
154
+ expect($('.ons-input').attr('placeholder')).toBeUndefined();
497
155
  });
498
156
 
499
- it('renders an `abbr` tag when `title` set', () => {
500
- const $ = cheerio.load(
501
- renderComponent('input', {
502
- ...EXAMPLE_INPUT_MINIMAL,
503
- suffix: {
504
- text: 'Example suffix text',
505
- title: 'Example suffix title',
506
- id: 'example-suffix-id',
507
- },
508
- }),
509
- );
510
-
511
- expect($('.ons-input + abbr').length).toBe(1);
512
- });
157
+ it('has `placeholder` attribute when `placeholder` is provided', () => {
158
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_LABEL));
513
159
 
514
- it('renders a `span` tag when `title` not set', () => {
515
- const $ = cheerio.load(
516
- renderComponent('input', {
517
- ...EXAMPLE_INPUT_MINIMAL,
518
- suffix: {
519
- text: 'Example suffix text',
520
- id: 'example-suffix-id',
521
- },
522
- }),
523
- );
524
-
525
- expect($('.ons-input + span').length).toBe(1);
160
+ expect($('.ons-input').attr('placeholder')).toBe('Example input label');
526
161
  });
527
- });
528
162
 
529
- describe('search', () => {
530
- it.each('outputs `type` attribute of "search"', () => {
531
- const $ = cheerio.load(renderComponent('input', EXAMPLE_WITH_SEARCH));
163
+ it('does not have `min` attribute', () => {
164
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
532
165
 
533
- expect($('.ons-input').attr('type')).toBe('search');
534
- expect($('.ons-input').attr('pattern')).toBeUndefined();
535
- expect($('.ons-input').attr('inputmode')).toBeUndefined();
166
+ expect($('.ons-input').attr('min')).toBeUndefined();
536
167
  });
537
168
 
538
- it('has the "ons-search__input" class', () => {
539
- const $ = cheerio.load(renderComponent('input', EXAMPLE_WITH_SEARCH));
169
+ it('has `min` attribute when `min` is provided', () => {
170
+ const $ = cheerio.load(
171
+ renderComponent('input', {
172
+ ...EXAMPLE_INPUT_MINIMAL,
173
+ min: 10,
174
+ }),
175
+ );
540
176
 
541
- expect($('.ons-input').hasClass('ons-search__input')).toBe(true);
542
- });
543
- });
544
-
545
- describe('with character limit', () => {
546
- it('passes jest-axe checks', async () => {
547
- const $ = cheerio.load(
548
- renderComponent('input', {
549
- ...EXAMPLE_INPUT_WITH_CHARACTER_LIMIT,
550
- label: {
551
- id: 'example-input-label',
552
- text: 'Example input label',
553
- },
554
- }),
555
- );
556
-
557
- const results = await axe($.html());
558
- expect(results).toHaveNoViolations();
177
+ expect($('.ons-input').attr('min')).toBe('10');
559
178
  });
560
179
 
561
- it('has the provided minimum length', () => {
562
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
180
+ it('does not have `max` attribute', () => {
181
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
563
182
 
564
- expect($('.ons-input').attr('minlength')).toBe('10');
183
+ expect($('.ons-input').attr('max')).toBeUndefined();
565
184
  });
566
185
 
567
- it('has the provided maximum length', () => {
568
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
186
+ it('has `max` attribute when `max` is provided', () => {
187
+ const $ = cheerio.load(
188
+ renderComponent('input', {
189
+ ...EXAMPLE_INPUT_MINIMAL,
190
+ max: 100,
191
+ }),
192
+ );
569
193
 
570
- expect($('.ons-input').attr('maxlength')).toBe('200');
194
+ expect($('.ons-input').attr('max')).toBe('100');
571
195
  });
572
196
 
573
- it('does not have `data-char-check-countdown` attribute when `charcheckCountdown` is not provided', () => {
574
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
197
+ it('does not have `value` attribute', () => {
198
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
575
199
 
576
- expect($('.ons-input').attr('data-char-check-countdown')).toBe(undefined);
200
+ expect($('.ons-input').attr('value')).toBeUndefined();
577
201
  });
578
202
 
579
- it('has `data-char-check-countdown` attribute when `charcheckCountdown` is true', () => {
580
- const $ = cheerio.load(
581
- renderComponent('input', {
582
- ...EXAMPLE_INPUT_WITH_CHARACTER_LIMIT,
583
- charCheckLimit: {
584
- ...EXAMPLE_INPUT_WITH_CHARACTER_LIMIT.charCheckLimit,
585
- charcheckCountdown: true,
586
- },
587
- }),
588
- );
589
-
590
- expect($('.ons-input').attr('data-char-check-countdown')).toBe('true');
591
- });
592
-
593
- it('has data attribute which references the character limit component', () => {
594
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
203
+ it('has `value` attribute when `value` is provided', () => {
204
+ const $ = cheerio.load(
205
+ renderComponent('input', {
206
+ ...EXAMPLE_INPUT_MINIMAL,
207
+ value: '100',
208
+ }),
209
+ );
595
210
 
596
- expect($('.ons-input').attr('data-char-check-ref')).toBe('example-id-check');
211
+ expect($('.ons-input').attr('value')).toBe('100');
597
212
  });
598
213
 
599
- it('has data attribute which defines limit for character check', () => {
600
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
214
+ it('does not have `accept` attribute', () => {
215
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
601
216
 
602
- expect($('.ons-input').attr('data-char-check-num')).toBe('200');
217
+ expect($('.ons-input').attr('accept')).toBeUndefined();
603
218
  });
604
219
 
605
- it('has `aria-describedby` attribute which references the character limit component', () => {
606
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
220
+ it('has `accept` attribute when `accept` is provided', () => {
221
+ const $ = cheerio.load(
222
+ renderComponent('input', {
223
+ ...EXAMPLE_INPUT_MINIMAL,
224
+ accept: 'image/*',
225
+ }),
226
+ );
607
227
 
608
- expect($('.ons-input').attr('aria-describedby')).toBe('example-id-check');
228
+ expect($('.ons-input').attr('accept')).toBe('image/*');
609
229
  });
610
230
 
611
- it('renders character limit component', () => {
612
- const faker = templateFaker();
613
- const charCheckLimitSpy = faker.spy('char-check-limit');
231
+ it('does not have `autocomplete` attribute', () => {
232
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_MINIMAL));
614
233
 
615
- faker.renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT);
616
-
617
- expect(charCheckLimitSpy.occurrences).toContainEqual({
618
- id: 'example-id-check',
619
- limit: 200,
620
- variant: 'check',
621
- charCountSingular: 'You have {x} character remaining',
622
- charCountPlural: 'You have {x} characters remaining',
623
- charCountOverLimitSingular: '{x} character too many',
624
- charCountOverLimitPlural: '{x} characters too many',
625
- });
234
+ expect($('.ons-input').attr('autocomplete')).toBeUndefined();
626
235
  });
627
- });
628
236
 
629
- describe('with error', () => {
630
- it('has the `error` modifier class', () => {
631
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_ERROR));
237
+ it('has `autocomplete` attribute when `autocomplete` is provided', () => {
238
+ const $ = cheerio.load(
239
+ renderComponent('input', {
240
+ ...EXAMPLE_INPUT_MINIMAL,
241
+ autocomplete: 'on',
242
+ }),
243
+ );
632
244
 
633
- expect($('.ons-input').hasClass('ons-input--error')).toBe(true);
634
- });
635
- });
636
-
637
- describe('with post textbox link', () => {
638
- it('renders the expected link', () => {
639
- const $ = cheerio.load(
640
- renderComponent('input', {
641
- ...EXAMPLE_INPUT_MINIMAL,
642
- postTextboxLinkUrl: 'https://example.com/link',
643
- postTextboxLinkText: 'Example link',
644
- }),
645
- );
646
-
647
- expect($('a.ons-input__post-link').attr('href')).toBe('https://example.com/link');
648
- expect($('a.ons-input__post-link').text().trim()).toBe('Example link');
245
+ expect($('.ons-input').attr('autocomplete')).toBe('on');
649
246
  });
650
- });
651
247
 
652
- describe('mutually exclusive', () => {
653
- it('passes jest-axe checks', async () => {
654
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_MUTUALLY_EXCLUSIVE_WITH_ERROR));
248
+ it.each([['email'], ['tel'], ['text']])('outputs `type` attribute of "%s"', (type) => {
249
+ const $ = cheerio.load(
250
+ renderComponent('input', {
251
+ ...EXAMPLE_INPUT_MINIMAL,
252
+ type,
253
+ }),
254
+ );
655
255
 
656
- const results = await axe($.html());
657
- expect(results).toHaveNoViolations();
256
+ expect($('.ons-input').attr('type')).toBe(type);
257
+ expect($('.ons-input').attr('pattern')).toBeUndefined();
258
+ expect($('.ons-input').attr('inputmode')).toBeUndefined();
658
259
  });
659
260
 
660
- it('has the `ons-js-exclusive-group-item` class', () => {
661
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_MUTUALLY_EXCLUSIVE_WITH_ERROR));
261
+ it.each([
262
+ ['number', 10, 'ons-input-number--w-10'],
263
+ ['tel', 20, 'ons-input-number--w-20'],
264
+ ])('adds class "ons-input-number" when `type` is "%s"', (type, width, expectedClass) => {
265
+ const $ = cheerio.load(
266
+ renderComponent('input', {
267
+ ...EXAMPLE_INPUT_MINIMAL,
268
+ type,
269
+ width,
270
+ }),
271
+ );
662
272
 
663
- expect($('.ons-input').hasClass('ons-js-exclusive-group-item')).toBe(true);
273
+ expect($('.ons-input').hasClass(expectedClass)).toBe(true);
664
274
  });
665
275
 
666
- it('renders mutually exclusive component', () => {
667
- const faker = templateFaker();
668
- const mutuallyExclusiveSpy = faker.spy('mutually-exclusive');
669
-
670
- faker.renderComponent('input', {
671
- ...EXAMPLE_INPUT_WITH_MUTUALLY_EXCLUSIVE_WITH_ERROR,
672
- fieldId: 'example-field-id',
673
- fieldClasses: 'extra-field-class',
674
- legend: 'Legend text',
675
- legendClasses: 'extra-legend-class',
676
- description: 'Example description text',
677
- legendIsQuestionTitle: true,
678
- autosuggestResults: 'RESULTS',
679
- });
680
-
681
- expect(mutuallyExclusiveSpy.occurrences).toContainEqual({
682
- id: 'example-field-id',
683
- legend: 'Legend text',
684
- legendClasses: 'extra-legend-class ons-js-input-legend',
685
- description: 'Example description text',
686
- dontWrap: true,
687
- legendIsQuestionTitle: true,
688
- exclusiveOptions: EXAMPLE_INPUT_WITH_MUTUALLY_EXCLUSIVE_WITH_ERROR.mutuallyExclusive.exclusiveOptions,
689
- or: 'Or',
690
- deselectMessage: 'Selecting this will clear your feedback',
691
- deselectGroupAdjective: 'cleared',
692
- deselectExclusiveOptionAdjective: 'deselected',
693
- error: EXAMPLE_INPUT_WITH_MUTUALLY_EXCLUSIVE_WITH_ERROR.error,
694
- autosuggestResults: 'RESULTS',
695
- });
276
+ describe('listeners', () => {
277
+ it('renders each listener', () => {
278
+ const $ = cheerio.load(
279
+ renderComponent('input', {
280
+ ...EXAMPLE_INPUT_MINIMAL,
281
+ listeners: {
282
+ click: `alert('Input was clicked')`,
283
+ keypress: `alert('Key was pressed')`,
284
+ },
285
+ }),
286
+ );
287
+
288
+ const script = $('script').html();
289
+ expect(script).toContain(
290
+ `document.getElementById("example-id").addEventListener('click', function(){ alert('Input was clicked') });`,
291
+ );
292
+ expect(script).toContain(
293
+ `document.getElementById("example-id").addEventListener('keypress', function(){ alert('Key was pressed') });`,
294
+ );
295
+ });
296
+ });
297
+
298
+ it('renders field component', () => {
299
+ const faker = templateFaker();
300
+ const fieldSpy = faker.spy('field');
301
+
302
+ faker.renderComponent('input', {
303
+ ...EXAMPLE_INPUT_WITH_ERROR,
304
+ fieldId: 'example-field-id',
305
+ fieldClasses: 'extra-field-class',
306
+ dontWrap: true,
307
+ });
308
+
309
+ expect(fieldSpy.occurrences).toContainEqual({
310
+ id: 'example-field-id',
311
+ classes: 'extra-field-class',
312
+ dontWrap: true,
313
+ error: EXAMPLE_INPUT_WITH_ERROR.error,
314
+ inline: false,
315
+ });
316
+ });
317
+
318
+ describe('label', () => {
319
+ it('does not output a label when `label` is not provided', () => {
320
+ const faker = templateFaker();
321
+ const labelSpy = faker.spy('label');
322
+
323
+ faker.renderComponent('input', EXAMPLE_INPUT_MINIMAL);
324
+
325
+ expect(labelSpy.occurrences.length).toBe(0);
326
+ });
327
+
328
+ it('outputs a label when `label` is provided', () => {
329
+ const faker = templateFaker();
330
+ const labelSpy = faker.spy('label');
331
+
332
+ faker.renderComponent('input', EXAMPLE_INPUT_WITH_LABEL);
333
+
334
+ expect(labelSpy.occurrences).toContainEqual({
335
+ for: 'example-id',
336
+ id: 'example-input-label',
337
+ text: 'Example input label',
338
+ classes: 'extra-label-class',
339
+ description: 'Example input label description',
340
+ attributes: { a: 42 },
341
+ inline: false,
342
+ accessiblePlaceholder: true,
343
+ });
344
+ });
345
+
346
+ it('outputs `aria-describedby` attribute referencing the label', () => {
347
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_LABEL));
348
+
349
+ expect($('.ons-input').attr('aria-describedby')).toBe('example-input-label-description-hint');
350
+ });
351
+
352
+ it('outputs a default `aria-describedby` attribute referencing the label when label does not have an `id`', () => {
353
+ const $ = cheerio.load(
354
+ renderComponent('input', {
355
+ ...EXAMPLE_INPUT_MINIMAL,
356
+ label: {
357
+ text: 'Example input label',
358
+ description: 'Example input label description',
359
+ },
360
+ }),
361
+ );
362
+
363
+ expect($('.ons-input').attr('aria-describedby')).toBe('description-hint');
364
+ });
365
+ });
366
+
367
+ describe('prefix and suffix', () => {
368
+ it('passes jest-axe checks', async () => {
369
+ const $ = cheerio.load(
370
+ renderComponent('input', {
371
+ ...EXAMPLE_INPUT_MINIMAL,
372
+ prefix: {
373
+ id: 'example-prefix-id',
374
+ title: 'Example prefix title',
375
+ },
376
+ }),
377
+ );
378
+
379
+ const results = await axe($.html());
380
+ expect(results).toHaveNoViolations();
381
+ });
382
+
383
+ it('adds `aria-labelledby` attribute when `prefix` is provided with `prefix.title`', () => {
384
+ const $ = cheerio.load(
385
+ renderComponent('input', {
386
+ ...EXAMPLE_INPUT_MINIMAL,
387
+ prefix: {
388
+ id: 'example-prefix-id',
389
+ title: 'Example prefix title',
390
+ },
391
+ }),
392
+ );
393
+
394
+ expect($('.ons-input').attr('aria-labelledby')).toBe('example-id example-prefix-id');
395
+ });
396
+
397
+ it('adds `aria-labelledby` attribute when `prefix` is provided without `prefix.title`', () => {
398
+ const $ = cheerio.load(
399
+ renderComponent('input', {
400
+ ...EXAMPLE_INPUT_MINIMAL,
401
+ prefix: {
402
+ id: 'example-prefix-id',
403
+ },
404
+ }),
405
+ );
406
+
407
+ expect($('.ons-input').attr('aria-labelledby')).toBe('example-prefix-id');
408
+ });
409
+
410
+ it('renders prefix element from `prefix.text`', () => {
411
+ const $ = cheerio.load(
412
+ renderComponent('input', {
413
+ ...EXAMPLE_INPUT_MINIMAL,
414
+ prefix: {
415
+ id: 'example-prefix-id',
416
+ title: 'Example prefix title',
417
+ text: 'Example prefix text',
418
+ },
419
+ }),
420
+ );
421
+
422
+ expect($('.ons-input-type--prefix .ons-js-input-abbr').attr('id')).toBe('example-prefix-id');
423
+ expect($('.ons-input-type--prefix .ons-js-input-abbr').attr('title')).toBe('Example prefix title');
424
+ expect($('.ons-input-type--prefix .ons-js-input-abbr').text().trim()).toBe('Example prefix text');
425
+ });
426
+
427
+ it('does not render prefix element when `prefix.id` not set', () => {
428
+ const $ = cheerio.load(
429
+ renderComponent('input', {
430
+ ...EXAMPLE_INPUT_MINIMAL,
431
+ prefix: {
432
+ title: 'Example prefix title',
433
+ text: 'Example prefix text',
434
+ },
435
+ }),
436
+ );
437
+
438
+ expect($('.ons-input-type--prefix').length).toBe(0);
439
+ });
440
+
441
+ it('adds `aria-labelledby` attribute when `suffix` is provided', () => {
442
+ const $ = cheerio.load(
443
+ renderComponent('input', {
444
+ ...EXAMPLE_INPUT_MINIMAL,
445
+ suffix: {
446
+ id: 'example-suffix-id',
447
+ title: 'Example suffix title',
448
+ },
449
+ }),
450
+ );
451
+
452
+ expect($('.ons-input').attr('aria-labelledby')).toBe('example-id example-suffix-id');
453
+ });
454
+
455
+ it('adds `aria-labelledby` attribute when `suffix` is provided without `suffix.title`', () => {
456
+ const $ = cheerio.load(
457
+ renderComponent('input', {
458
+ ...EXAMPLE_INPUT_MINIMAL,
459
+ suffix: {
460
+ id: 'example-suffix-id',
461
+ },
462
+ }),
463
+ );
464
+
465
+ expect($('.ons-input').attr('aria-labelledby')).toBe('example-suffix-id');
466
+ });
467
+
468
+ it('renders suffix element from `suffix.text`', () => {
469
+ const $ = cheerio.load(
470
+ renderComponent('input', {
471
+ ...EXAMPLE_INPUT_MINIMAL,
472
+ suffix: {
473
+ id: 'example-suffix-id',
474
+ title: 'Example suffix title',
475
+ text: 'Example suffix text',
476
+ },
477
+ }),
478
+ );
479
+
480
+ expect($('.ons-js-input-abbr').attr('id')).toBe('example-suffix-id');
481
+ expect($('.ons-js-input-abbr').attr('title')).toBe('Example suffix title');
482
+ expect($('.ons-js-input-abbr').text().trim()).toBe('Example suffix text');
483
+ });
484
+
485
+ it('does not render suffix element when `suffix.id` not set', () => {
486
+ const $ = cheerio.load(
487
+ renderComponent('input', {
488
+ ...EXAMPLE_INPUT_MINIMAL,
489
+ suffix: {
490
+ title: 'Example suffix title',
491
+ text: 'Example suffix text',
492
+ },
493
+ }),
494
+ );
495
+
496
+ expect($('.ons-input').length).toBe(0);
497
+ });
498
+
499
+ it('renders an `abbr` tag when `title` set', () => {
500
+ const $ = cheerio.load(
501
+ renderComponent('input', {
502
+ ...EXAMPLE_INPUT_MINIMAL,
503
+ suffix: {
504
+ text: 'Example suffix text',
505
+ title: 'Example suffix title',
506
+ id: 'example-suffix-id',
507
+ },
508
+ }),
509
+ );
510
+
511
+ expect($('.ons-input + abbr').length).toBe(1);
512
+ });
513
+
514
+ it('renders a `span` tag when `title` not set', () => {
515
+ const $ = cheerio.load(
516
+ renderComponent('input', {
517
+ ...EXAMPLE_INPUT_MINIMAL,
518
+ suffix: {
519
+ text: 'Example suffix text',
520
+ id: 'example-suffix-id',
521
+ },
522
+ }),
523
+ );
524
+
525
+ expect($('.ons-input + span').length).toBe(1);
526
+ });
527
+ });
528
+
529
+ describe('search', () => {
530
+ it.each('outputs `type` attribute of "search"', () => {
531
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_WITH_SEARCH));
532
+
533
+ expect($('.ons-input').attr('type')).toBe('search');
534
+ expect($('.ons-input').attr('pattern')).toBeUndefined();
535
+ expect($('.ons-input').attr('inputmode')).toBeUndefined();
536
+ });
537
+
538
+ it('has the "ons-search__input" class', () => {
539
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_WITH_SEARCH));
540
+
541
+ expect($('.ons-input').hasClass('ons-search__input')).toBe(true);
542
+ });
543
+ });
544
+
545
+ describe('with character limit', () => {
546
+ it('passes jest-axe checks', async () => {
547
+ const $ = cheerio.load(
548
+ renderComponent('input', {
549
+ ...EXAMPLE_INPUT_WITH_CHARACTER_LIMIT,
550
+ label: {
551
+ id: 'example-input-label',
552
+ text: 'Example input label',
553
+ },
554
+ }),
555
+ );
556
+
557
+ const results = await axe($.html());
558
+ expect(results).toHaveNoViolations();
559
+ });
560
+
561
+ it('has the provided minimum length', () => {
562
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
563
+
564
+ expect($('.ons-input').attr('minlength')).toBe('10');
565
+ });
566
+
567
+ it('has the provided maximum length', () => {
568
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
569
+
570
+ expect($('.ons-input').attr('maxlength')).toBe('200');
571
+ });
572
+
573
+ it('does not have `data-char-check-countdown` attribute when `charcheckCountdown` is not provided', () => {
574
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
575
+
576
+ expect($('.ons-input').attr('data-char-check-countdown')).toBe(undefined);
577
+ });
578
+
579
+ it('has `data-char-check-countdown` attribute when `charcheckCountdown` is true', () => {
580
+ const $ = cheerio.load(
581
+ renderComponent('input', {
582
+ ...EXAMPLE_INPUT_WITH_CHARACTER_LIMIT,
583
+ charCheckLimit: {
584
+ ...EXAMPLE_INPUT_WITH_CHARACTER_LIMIT.charCheckLimit,
585
+ charcheckCountdown: true,
586
+ },
587
+ }),
588
+ );
589
+
590
+ expect($('.ons-input').attr('data-char-check-countdown')).toBe('true');
591
+ });
592
+
593
+ it('has data attribute which references the character limit component', () => {
594
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
595
+
596
+ expect($('.ons-input').attr('data-char-check-ref')).toBe('example-id-check');
597
+ });
598
+
599
+ it('has data attribute which defines limit for character check', () => {
600
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
601
+
602
+ expect($('.ons-input').attr('data-char-check-num')).toBe('200');
603
+ });
604
+
605
+ it('has `aria-describedby` attribute which references the character limit component', () => {
606
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
607
+
608
+ expect($('.ons-input').attr('aria-describedby')).toBe('example-id-check');
609
+ });
610
+
611
+ it('renders character limit component', () => {
612
+ const faker = templateFaker();
613
+ const charCheckLimitSpy = faker.spy('char-check-limit');
614
+
615
+ faker.renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT);
616
+
617
+ expect(charCheckLimitSpy.occurrences).toContainEqual({
618
+ id: 'example-id-check',
619
+ limit: 200,
620
+ variant: 'check',
621
+ charCountSingular: 'You have {x} character remaining',
622
+ charCountPlural: 'You have {x} characters remaining',
623
+ charCountOverLimitSingular: '{x} character too many',
624
+ charCountOverLimitPlural: '{x} characters too many',
625
+ });
626
+ });
627
+ });
628
+
629
+ describe('with error', () => {
630
+ it('has the `error` modifier class', () => {
631
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_ERROR));
632
+
633
+ expect($('.ons-input').hasClass('ons-input--error')).toBe(true);
634
+ });
635
+ });
636
+
637
+ describe('with post textbox link', () => {
638
+ it('renders the expected link', () => {
639
+ const $ = cheerio.load(
640
+ renderComponent('input', {
641
+ ...EXAMPLE_INPUT_MINIMAL,
642
+ postTextboxLinkUrl: 'https://example.com/link',
643
+ postTextboxLinkText: 'Example link',
644
+ }),
645
+ );
646
+
647
+ expect($('a.ons-input__post-link').attr('href')).toBe('https://example.com/link');
648
+ expect($('a.ons-input__post-link').text().trim()).toBe('Example link');
649
+ });
650
+ });
651
+
652
+ describe('mutually exclusive', () => {
653
+ it('passes jest-axe checks', async () => {
654
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_MUTUALLY_EXCLUSIVE_WITH_ERROR));
655
+
656
+ const results = await axe($.html());
657
+ expect(results).toHaveNoViolations();
658
+ });
659
+
660
+ it('has the `ons-js-exclusive-group-item` class', () => {
661
+ const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_MUTUALLY_EXCLUSIVE_WITH_ERROR));
662
+
663
+ expect($('.ons-input').hasClass('ons-js-exclusive-group-item')).toBe(true);
664
+ });
665
+
666
+ it('renders mutually exclusive component', () => {
667
+ const faker = templateFaker();
668
+ const mutuallyExclusiveSpy = faker.spy('mutually-exclusive');
669
+
670
+ faker.renderComponent('input', {
671
+ ...EXAMPLE_INPUT_WITH_MUTUALLY_EXCLUSIVE_WITH_ERROR,
672
+ fieldId: 'example-field-id',
673
+ fieldClasses: 'extra-field-class',
674
+ legend: 'Legend text',
675
+ legendClasses: 'extra-legend-class',
676
+ description: 'Example description text',
677
+ legendIsQuestionTitle: true,
678
+ autosuggestResults: 'RESULTS',
679
+ });
680
+
681
+ expect(mutuallyExclusiveSpy.occurrences).toContainEqual({
682
+ id: 'example-field-id',
683
+ legend: 'Legend text',
684
+ legendClasses: 'extra-legend-class ons-js-input-legend',
685
+ description: 'Example description text',
686
+ dontWrap: true,
687
+ legendIsQuestionTitle: true,
688
+ exclusiveOptions: EXAMPLE_INPUT_WITH_MUTUALLY_EXCLUSIVE_WITH_ERROR.mutuallyExclusive.exclusiveOptions,
689
+ or: 'Or',
690
+ deselectMessage: 'Selecting this will clear your feedback',
691
+ deselectGroupAdjective: 'cleared',
692
+ deselectExclusiveOptionAdjective: 'deselected',
693
+ error: EXAMPLE_INPUT_WITH_MUTUALLY_EXCLUSIVE_WITH_ERROR.error,
694
+ autosuggestResults: 'RESULTS',
695
+ });
696
+ });
696
697
  });
697
- });
698
698
  });