@ons/design-system 50.0.1 → 53.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/README.md +35 -15
  2. package/components/access-code/_macro.njk +1 -1
  3. package/components/access-code/_macro.spec.js +162 -0
  4. package/components/access-code/uac.spec.js +26 -0
  5. package/components/accordion/_macro.spec.js +224 -0
  6. package/components/accordion/accordion.spec.js +134 -0
  7. package/components/address-input/_macro.njk +1 -1
  8. package/components/address-input/_macro.spec.js +465 -0
  9. package/components/address-input/autosuggest.address.js +5 -4
  10. package/components/address-input/autosuggest.address.setter.js +9 -3
  11. package/components/address-input/autosuggest.address.spec.js +733 -0
  12. package/components/address-output/_macro.njk +6 -6
  13. package/components/address-output/_macro.spec.js +122 -0
  14. package/components/autosuggest/_macro.njk +1 -1
  15. package/components/autosuggest/_macro.spec.js +229 -0
  16. package/components/autosuggest/autosuggest.helpers.js +2 -3
  17. package/components/autosuggest/autosuggest.helpers.spec.js +85 -0
  18. package/components/autosuggest/autosuggest.js +4 -2
  19. package/components/autosuggest/autosuggest.spec.js +625 -0
  20. package/components/autosuggest/autosuggest.ui.js +6 -2
  21. package/components/breadcrumbs/_macro.spec.js +129 -0
  22. package/components/button/_button.scss +75 -33
  23. package/components/button/_macro.njk +6 -6
  24. package/components/button/_macro.spec.js +446 -0
  25. package/components/button/button.spec.js +290 -0
  26. package/components/call-to-action/_macro.njk +3 -1
  27. package/components/call-to-action/_macro.spec.js +52 -0
  28. package/components/card/_macro.njk +26 -19
  29. package/components/card/_macro.spec.js +261 -0
  30. package/components/char-check-limit/_macro.spec.js +73 -0
  31. package/components/char-check-limit/character-check.spec.js +196 -0
  32. package/components/char-check-limit/character-limit.js +1 -1
  33. package/components/checkboxes/_checkbox-macro.spec.js +419 -0
  34. package/components/checkboxes/_macro.njk +1 -3
  35. package/components/checkboxes/_macro.spec.js +306 -0
  36. package/components/checkboxes/checkbox-with-autoselect.js +2 -1
  37. package/components/checkboxes/checkboxes.spec.js +208 -0
  38. package/components/code-highlight/_macro.spec.js +56 -0
  39. package/components/code-highlight/code-highlight.spec.js +18 -0
  40. package/components/collapsible/_macro.spec.js +204 -0
  41. package/components/collapsible/collapsible.js +2 -1
  42. package/components/collapsible/collapsible.spec.js +236 -0
  43. package/components/content-pagination/_macro.spec.js +199 -0
  44. package/components/cookies-banner/_macro.njk +1 -1
  45. package/components/cookies-banner/_macro.spec.js +171 -0
  46. package/components/cookies-banner/cookies-banner.spec.js +90 -0
  47. package/components/date-input/_macro.njk +6 -3
  48. package/components/date-input/_macro.spec.js +286 -0
  49. package/components/document-list/_macro.njk +3 -5
  50. package/components/document-list/_macro.spec.js +491 -0
  51. package/components/download-resources/download-resources.spec.js +540 -0
  52. package/components/duration/_macro.njk +7 -6
  53. package/components/duration/_macro.spec.js +251 -0
  54. package/components/error/_macro.spec.js +97 -0
  55. package/components/external-link/_macro.njk +5 -2
  56. package/components/external-link/_macro.spec.js +77 -0
  57. package/components/feedback/_macro.njk +5 -3
  58. package/components/feedback/_macro.spec.js +122 -0
  59. package/components/field/_macro.njk +2 -2
  60. package/components/field/_macro.spec.js +97 -0
  61. package/components/fieldset/_macro.njk +3 -3
  62. package/components/fieldset/_macro.spec.js +173 -0
  63. package/components/footer/_footer.scss +19 -4
  64. package/components/footer/_macro.njk +106 -137
  65. package/components/footer/_macro.spec.js +678 -0
  66. package/components/header/_header.scss +65 -46
  67. package/components/header/_macro.njk +173 -121
  68. package/components/header/_macro.spec.js +618 -0
  69. package/components/hero/_hero.scss +30 -143
  70. package/components/hero/_macro.njk +12 -23
  71. package/components/hero/_macro.spec.js +218 -0
  72. package/components/icons/_macro.njk +258 -30
  73. package/components/icons/_macro.spec.js +140 -0
  74. package/components/images/_macro.njk +1 -1
  75. package/components/images/_macro.spec.js +121 -0
  76. package/components/input/_input-type.scss +12 -5
  77. package/components/input/_input.scss +8 -0
  78. package/components/input/_macro.njk +4 -5
  79. package/components/input/_macro.spec.js +658 -0
  80. package/components/label/_macro.spec.js +189 -0
  81. package/components/language-selector/_macro.njk +1 -1
  82. package/components/language-selector/_macro.spec.js +137 -0
  83. package/components/lists/_list.scss +4 -0
  84. package/components/lists/_macro.njk +4 -7
  85. package/components/lists/_macro.spec.js +618 -0
  86. package/components/message/_macro.spec.js +137 -0
  87. package/components/message-list/_macro.njk +7 -7
  88. package/components/message-list/_macro.spec.js +159 -0
  89. package/components/metadata/_macro.spec.js +167 -0
  90. package/components/modal/_macro.njk +6 -6
  91. package/components/modal/_macro.spec.js +87 -0
  92. package/components/modal/modal.spec.js +59 -0
  93. package/components/mutually-exclusive/_macro.njk +2 -2
  94. package/components/mutually-exclusive/_macro.spec.js +184 -0
  95. package/components/mutually-exclusive/mutually-exclusive.checkboxes.spec.js +203 -0
  96. package/components/mutually-exclusive/mutually-exclusive.date.spec.js +142 -0
  97. package/components/mutually-exclusive/mutually-exclusive.duration.spec.js +141 -0
  98. package/components/mutually-exclusive/mutually-exclusive.email.spec.js +117 -0
  99. package/components/mutually-exclusive/mutually-exclusive.multiple-options.checkboxes.spec.js +213 -0
  100. package/components/mutually-exclusive/mutually-exclusive.number.spec.js +125 -0
  101. package/components/mutually-exclusive/mutually-exclusive.textarea.spec.js +131 -0
  102. package/components/navigation/_macro.njk +45 -38
  103. package/components/navigation/_macro.spec.js +329 -0
  104. package/components/navigation/_navigation.scss +20 -4
  105. package/components/navigation/navigation.dom.js +1 -1
  106. package/components/navigation/navigation.spec.js +232 -0
  107. package/components/pagination/_macro.njk +1 -1
  108. package/components/pagination/_macro.spec.js +411 -0
  109. package/components/panel/_macro.njk +6 -6
  110. package/components/panel/_macro.spec.js +423 -0
  111. package/components/password/_macro.spec.js +137 -0
  112. package/components/password/password.spec.js +40 -0
  113. package/components/phase-banner/_macro.spec.js +73 -0
  114. package/components/promotional-banner/_macro.spec.js +97 -0
  115. package/components/question/_macro.njk +16 -22
  116. package/components/question/_macro.spec.js +309 -0
  117. package/components/quote/_macro.spec.js +81 -0
  118. package/components/radios/_macro.njk +3 -6
  119. package/components/radios/_macro.spec.js +575 -0
  120. package/components/radios/radios.spec.js +180 -0
  121. package/components/related-content/_macro.njk +14 -21
  122. package/components/related-content/_macro.spec.js +133 -0
  123. package/components/related-content/_section-macro.njk +10 -0
  124. package/components/related-content/_section-macro.spec.js +43 -0
  125. package/components/relationships/_macro.spec.js +108 -0
  126. package/components/relationships/relationships.spec.js +84 -0
  127. package/components/reply/_macro.njk +2 -2
  128. package/components/reply/_macro.spec.js +69 -0
  129. package/components/reply/reply.spec.js +78 -0
  130. package/components/search/_macro.njk +14 -12
  131. package/components/search/_macro.spec.js +44 -0
  132. package/components/search/_search.scss +7 -7
  133. package/components/section-navigation/_macro.njk +7 -2
  134. package/components/section-navigation/_macro.spec.js +206 -0
  135. package/components/select/_macro.njk +3 -3
  136. package/components/select/_macro.spec.js +203 -0
  137. package/components/select/select.spec.js +56 -0
  138. package/components/share-page/_macro.njk +6 -4
  139. package/components/share-page/_macro.spec.js +110 -0
  140. package/components/skip-to-content/_macro.spec.js +57 -0
  141. package/components/skip-to-content/skip-to-content.spec.js +44 -0
  142. package/components/status/_macro.spec.js +77 -0
  143. package/components/summary/_macro.njk +5 -5
  144. package/components/summary/_macro.spec.js +472 -0
  145. package/components/table/_macro.njk +2 -2
  146. package/components/table/_macro.spec.js +557 -0
  147. package/components/table/table.spec.js +155 -0
  148. package/components/table-of-contents/_macro.njk +35 -35
  149. package/components/table-of-contents/_macro.spec.js +178 -0
  150. package/components/table-of-contents/toc.js +29 -25
  151. package/components/table-of-contents/toc.spec.js +61 -0
  152. package/components/tabs/_macro.njk +1 -1
  153. package/components/tabs/_macro.spec.js +79 -0
  154. package/components/tabs/tabs.spec.js +162 -0
  155. package/components/text-indent/_macro.spec.js +52 -0
  156. package/components/textarea/_macro.njk +5 -3
  157. package/components/textarea/_macro.spec.js +300 -0
  158. package/components/textarea/textarea.spec.js +98 -0
  159. package/components/timeline/_macro.njk +3 -3
  160. package/components/timeline/_macro.spec.js +81 -0
  161. package/components/timeout-modal/_macro.spec.js +68 -0
  162. package/components/timeout-modal/timeout-modal.spec.js +226 -0
  163. package/components/timeout-panel/_macro.njk +0 -1
  164. package/components/timeout-panel/_macro.spec.js +54 -0
  165. package/components/timeout-panel/timeout-panel.dom.js +1 -2
  166. package/components/timeout-panel/timeout-panel.spec.js +161 -0
  167. package/components/upload/_macro.spec.js +75 -0
  168. package/components/video/_macro.spec.js +34 -0
  169. package/css/census.css +3 -1
  170. package/css/ids.css +2 -0
  171. package/css/main.css +1 -1
  172. package/img/dummy-brand-logo.svg +1 -0
  173. package/js/cookies-settings.spec.js +154 -0
  174. package/layout/_template.njk +7 -4
  175. package/package.json +10 -23
  176. package/scripts/main.es5.js +2 -2
  177. package/scripts/main.js +1 -1
  178. package/scss/ids.scss +2 -0
  179. package/scss/settings/_census.scss +141 -0
  180. package/scss/settings/_ids.scss +48 -0
  181. package/scss/utilities/_margin.scss +1 -0
  182. package/scss/vars/_colors.scss +5 -2
@@ -0,0 +1,73 @@
1
+ /** @jest-environment jsdom */
2
+
3
+ import * as cheerio from 'cheerio';
4
+
5
+ import axe from '../../tests/helpers/axe';
6
+ import { renderComponent } from '../../tests/helpers/rendering';
7
+
8
+ const EXAMPLE_PHASE_BANNER_MINIMAL = {
9
+ html: 'Example content with a <a href="#">link</a>',
10
+ };
11
+
12
+ describe('macro: phase-banner', () => {
13
+ it('passes jest-axe checks with', async () => {
14
+ const $ = cheerio.load(renderComponent('phase-banner', EXAMPLE_PHASE_BANNER_MINIMAL));
15
+
16
+ const results = await axe($.html());
17
+ expect(results).toHaveNoViolations();
18
+ });
19
+
20
+ it('has expected html content', () => {
21
+ const $ = cheerio.load(renderComponent('phase-banner', EXAMPLE_PHASE_BANNER_MINIMAL));
22
+
23
+ const htmlContent = $('.ons-phase-banner__desc')
24
+ .html()
25
+ .trim();
26
+ expect(htmlContent).toBe('Example content with a <a href="#">link</a>');
27
+ });
28
+
29
+ it('has the "Beta" badge by default', () => {
30
+ const $ = cheerio.load(renderComponent('phase-banner', EXAMPLE_PHASE_BANNER_MINIMAL));
31
+
32
+ const badgeText = $('.ons-phase-banner__badge')
33
+ .text()
34
+ .trim();
35
+ expect(badgeText).toBe('Beta');
36
+ });
37
+
38
+ it('has the provided `badge` text', () => {
39
+ const $ = cheerio.load(
40
+ renderComponent('phase-banner', {
41
+ ...EXAMPLE_PHASE_BANNER_MINIMAL,
42
+ badge: 'Alpha',
43
+ }),
44
+ );
45
+
46
+ const badgeText = $('.ons-phase-banner__badge')
47
+ .text()
48
+ .trim();
49
+ expect(badgeText).toBe('Alpha');
50
+ });
51
+
52
+ it('has no badge when `hideBadge` is true', () => {
53
+ const $ = cheerio.load(
54
+ renderComponent('phase-banner', {
55
+ ...EXAMPLE_PHASE_BANNER_MINIMAL,
56
+ hideBadge: true,
57
+ }),
58
+ );
59
+
60
+ expect($('.ons-phase-banner__badge').length).toBe(0);
61
+ });
62
+
63
+ it('has `container--wide` class when `wide` is true', () => {
64
+ const $ = cheerio.load(
65
+ renderComponent('phase-banner', {
66
+ ...EXAMPLE_PHASE_BANNER_MINIMAL,
67
+ wide: true,
68
+ }),
69
+ );
70
+
71
+ expect($('.ons-container').hasClass('ons-container--wide')).toBe(true);
72
+ });
73
+ });
@@ -0,0 +1,97 @@
1
+ /** @jest-environment jsdom */
2
+
3
+ import * as cheerio from 'cheerio';
4
+
5
+ import axe from '../../tests/helpers/axe';
6
+ import { renderComponent } from '../../tests/helpers/rendering';
7
+
8
+ const EXAMPLE_PROMOTIONAL_BANNER_MINIMAL = {
9
+ content: 'Example content with a <a href="#">link</a>',
10
+ };
11
+
12
+ const EXAMPLE_PROMOTIONAL_BANNER_WITH_IMAGE_URL = {
13
+ content: 'Example content with a <a href="#">link</a>',
14
+ image: {
15
+ src: 'example.png',
16
+ alt: 'Example image',
17
+ },
18
+ };
19
+
20
+ const EXAMPLE_PROMOTIONAL_BANNER_WITH_IMAGE_IMAGE = {
21
+ content: 'Example content with a <a href="#">link</a>',
22
+ image: {
23
+ smallSrc: 'example-small.png',
24
+ largeSrc: 'example-large.png',
25
+ alt: 'Example image',
26
+ },
27
+ };
28
+
29
+ describe('macro: promotional-banner', () => {
30
+ describe.each([
31
+ ['without image', EXAMPLE_PROMOTIONAL_BANNER_MINIMAL],
32
+ ['with image url', EXAMPLE_PROMOTIONAL_BANNER_WITH_IMAGE_URL],
33
+ ['with image small/large source', EXAMPLE_PROMOTIONAL_BANNER_WITH_IMAGE_IMAGE],
34
+ ])('mode: %s', (_, params) => {
35
+ it('passes jest-axe checks with', async () => {
36
+ const $ = cheerio.load(renderComponent('promotional-banner', params));
37
+
38
+ const results = await axe($.html());
39
+ expect(results).toHaveNoViolations();
40
+ });
41
+
42
+ it('has expected html content', () => {
43
+ const $ = cheerio.load(renderComponent('promotional-banner', params));
44
+
45
+ const htmlContent = $('.ons-promo-banner__content')
46
+ .html()
47
+ .trim();
48
+ expect(htmlContent).toBe('Example content with a <a href="#">link</a>');
49
+ });
50
+
51
+ it('has expected html content when called', () => {
52
+ const $ = cheerio.load(renderComponent('promotional-banner', params, ['<p>Nested content</p>']));
53
+
54
+ const htmlContent = $('.ons-promo-banner__content').html();
55
+ expect(htmlContent).toContain('<p>Nested content</p>');
56
+ });
57
+ });
58
+
59
+ describe('mode: with image url', () => {
60
+ it('has expected `src` attribute', () => {
61
+ const $ = cheerio.load(renderComponent('promotional-banner', EXAMPLE_PROMOTIONAL_BANNER_WITH_IMAGE_URL));
62
+
63
+ const src = $('.ons-promo-banner__image img').attr('src');
64
+ expect(src).toBe('example.png');
65
+ });
66
+
67
+ it('has expected `alt` attribute', () => {
68
+ const $ = cheerio.load(renderComponent('promotional-banner', EXAMPLE_PROMOTIONAL_BANNER_WITH_IMAGE_URL));
69
+
70
+ const alt = $('.ons-promo-banner__image img').attr('alt');
71
+ expect(alt).toBe('Example image');
72
+ });
73
+ });
74
+
75
+ describe('mode: with image small/large source', () => {
76
+ it('has expected `srcset` attribute', () => {
77
+ const $ = cheerio.load(renderComponent('promotional-banner', EXAMPLE_PROMOTIONAL_BANNER_WITH_IMAGE_IMAGE));
78
+
79
+ const srcset = $('.ons-promo-banner__image img').attr('srcset');
80
+ expect(srcset).toBe('example-small.png 1x, example-large.png 2x');
81
+ });
82
+
83
+ it('has expected `src` attribute', () => {
84
+ const $ = cheerio.load(renderComponent('promotional-banner', EXAMPLE_PROMOTIONAL_BANNER_WITH_IMAGE_IMAGE));
85
+
86
+ const src = $('.ons-promo-banner__image img').attr('src');
87
+ expect(src).toBe('example-small.png');
88
+ });
89
+
90
+ it('has expected `alt` attribute', () => {
91
+ const $ = cheerio.load(renderComponent('promotional-banner', EXAMPLE_PROMOTIONAL_BANNER_WITH_IMAGE_IMAGE));
92
+
93
+ const alt = $('.ons-promo-banner__image img').attr('alt');
94
+ expect(alt).toBe('Example image');
95
+ });
96
+ });
97
+ });
@@ -1,21 +1,16 @@
1
1
  {% macro onsQuestion(params) %}
2
2
 
3
- {% set titleHtml %}
4
- {%- if params.readDescriptionFirst is defined and params.readDescriptionFirst == true and params.description is defined and params.description %}
5
- <div class="ons-question__description ons-u-vh">{{- params.description | safe -}}</div>
6
- {% endif -%}
7
- {{- params.title | safe -}}
8
- {% endset %}
3
+ {%- set titleHtml -%}{% if params.readDescriptionFirst is defined and params.readDescriptionFirst == true and params.description is defined and params.description %}
4
+ <div class="ons-question__description ons-u-vh">{{ params.description | safe }} </div>{% endif %}{{- params.title | safe -}}
5
+ {%- endset -%}
9
6
 
10
- {% set descHtml %}
11
- {% if params.readDescriptionFirst is defined and params.readDescriptionFirst == true %}
12
- <div aria-hidden="true" {% if params.legendIsQuestionTitle is not defined %}class="ons-question__description"{% endif %}>{{ params.description | safe }}</div>
7
+ {%- set descHtml -%}{% if params.readDescriptionFirst is defined and params.readDescriptionFirst == true %}
8
+ <div aria-hidden="true" {% if params.legendIsQuestionTitle is not defined %}class="ons-question__description ons-question__description--aria-hidden"{% endif %}>{{- params.description | safe -}}</div>
13
9
  {% elif params.legendIsQuestionTitle is not defined %}
14
- <div class="ons-question__description ons-u-mb-m">{{ params.description | safe }}</div>
10
+ <div class="ons-question__description ons-u-mb-m">{{- params.description | safe -}}</div>
15
11
  {% else %}
16
- {{ params.description | safe }}
17
- {% endif %}
18
- {% endset %}
12
+ {{- params.description | safe -}}
13
+ {% endif %}{%- endset -%}
19
14
 
20
15
  {% set instHtml %}
21
16
  <div class="ons-question__instruction ons-u-mb-m">{{ params.instruction | safe }}</div>
@@ -25,9 +20,9 @@
25
20
  {% set questionDefinition %}
26
21
  {% from "components/collapsible/_macro.njk" import onsCollapsible %}
27
22
  {% call onsCollapsible({
28
- "id": params.definition.id if params.definition.id is defined and params.definition.id else '',
23
+ "id": params.definition.id,
29
24
  "classes": 'ons-u-mb-m',
30
- "title": params.definition.title if params.definition.title is defined and params.definition.title else ''
25
+ "title": params.definition.title
31
26
  }) %}
32
27
  {% if params.definition.content %}
33
28
  {{ params.definition.content | safe }}
@@ -40,7 +35,7 @@
40
35
  {% set questionGuidance %}
41
36
  {% from "components/panel/_macro.njk" import onsPanel %}
42
37
  {% call onsPanel({
43
- "classes": "ons-u-mb-m"
38
+ "classes": "ons-question-guidance ons-u-mb-m"
44
39
  }) %}
45
40
  {% if params.guidance.content is defined and params.guidance.content %}
46
41
  {{ params.guidance.content | safe }}
@@ -48,10 +43,10 @@
48
43
  {% if params.guidance.lists is defined and params.guidance.lists %}
49
44
  {%- for item in params.guidance.lists -%}
50
45
  {% if item.listHeading is defined and item.listHeading %}
51
- <h2 class="ons-u-fs-r--b">{{ item.listHeading }}</h2>
46
+ <h2 class="ons-question-guidance__list-heading ons-u-fs-r--b">{{ item.listHeading }}</h2>
52
47
  {% endif %}
53
48
  {% if item.listLeadingLine is defined and item.listLeadingLine %}
54
- <p>{{ item.listLeadingLine }}</h2>
49
+ <p class="ons-question-guidance__list-leading-line">{{ item.listLeadingLine }}</p>
55
50
  {% endif %}
56
51
  {% from "components/lists/_macro.njk" import onsList %}
57
52
  {{
@@ -74,7 +69,7 @@
74
69
  {% from "components/fieldset/_macro.njk" import onsFieldset %}
75
70
 
76
71
  {# Resolves caller issue in jijna: https://github.com/pallets/jinja/issues/371 #}
77
- {% set content = caller() %}
72
+ {% set content = caller() if caller %}
78
73
  <div class="ons-question__answer ons-u-mb-m">
79
74
  {% call onsFieldset({
80
75
  "legendIsQuestionTitle": params.legendIsQuestionTitle,
@@ -109,7 +104,7 @@
109
104
  {% endif %}
110
105
 
111
106
  <div class="ons-question__answer ons-u-mb-m">
112
- {{ caller () }}
107
+ {{ caller() if caller }}
113
108
  </div>
114
109
  {% endif %}
115
110
 
@@ -125,9 +120,8 @@
125
120
  {% endif %}
126
121
  </div>
127
122
 
128
- {% if params.submitButton is defined and params.submitButton %}
123
+ {% if params.submitButton != (false or null) %}
129
124
  {% from "components/button/_macro.njk" import onsButton %}
130
-
131
125
  {{
132
126
  onsButton({
133
127
  "id": params.submitButton.id,
@@ -0,0 +1,309 @@
1
+ /** @jest-environment jsdom */
2
+
3
+ import * as cheerio from 'cheerio';
4
+
5
+ import axe from '../../tests/helpers/axe';
6
+ import { renderComponent, templateFaker } from '../../tests/helpers/rendering';
7
+
8
+ const EXAMPLE_QUESTION_BASIC = {
9
+ id: 'example-question',
10
+ title: 'Question title',
11
+ description: 'Question description',
12
+ };
13
+
14
+ const EXAMPLE_QUESTION_DEFINITION = {
15
+ ...EXAMPLE_QUESTION_BASIC,
16
+ definition: {
17
+ id: 'definition-id',
18
+ title: 'Definition title',
19
+ content: '<p>Definition content</p>',
20
+ },
21
+ };
22
+
23
+ const EXAMPLE_QUESTION_GUIDANCE = {
24
+ ...EXAMPLE_QUESTION_BASIC,
25
+ guidance: {
26
+ content: '<span class="fake-content">Guidance content</span>',
27
+ lists: [
28
+ {
29
+ listHeading: 'List heading 1',
30
+ listLeadingLine: 'List leading line 1',
31
+ itemsList: [{ text: 'Test item 1' }, { text: 'Test item 2' }],
32
+ },
33
+ ],
34
+ },
35
+ };
36
+
37
+ const EXAMPLE_QUESTION_JUSTIFICATION = {
38
+ ...EXAMPLE_QUESTION_BASIC,
39
+ justification: {
40
+ id: 'justification-id',
41
+ title: 'Justification title',
42
+ content: '<p>Justification content</p>',
43
+ },
44
+ };
45
+
46
+ const EXAMPLE_QUESTION_BUTTON = {
47
+ ...EXAMPLE_QUESTION_BASIC,
48
+ submitButton: {
49
+ id: 'button-id',
50
+ submitType: 'button',
51
+ text: 'Button text',
52
+ },
53
+ };
54
+
55
+ const EXAMPLE_QUESTION_INSTRUCTION = {
56
+ ...EXAMPLE_QUESTION_BASIC,
57
+ instruction: 'Instruction text',
58
+ };
59
+
60
+ const EXAMPLE_QUESTION_LEGENDISQUESTIONTITLE = {
61
+ ...EXAMPLE_QUESTION_BASIC,
62
+ legendIsQuestionTitle: true,
63
+ };
64
+
65
+ const EXAMPLE_QUESTION_DESCRIPTION_FIRST = {
66
+ ...EXAMPLE_QUESTION_BASIC,
67
+ readDescriptionFirst: true,
68
+ };
69
+
70
+ describe('macro: question', () => {
71
+ describe.each([
72
+ ['with basic parameters', EXAMPLE_QUESTION_BASIC],
73
+ ['with definition', EXAMPLE_QUESTION_DEFINITION],
74
+ ['with guidance', EXAMPLE_QUESTION_GUIDANCE],
75
+ ['with justification', EXAMPLE_QUESTION_JUSTIFICATION],
76
+ ['with button', EXAMPLE_QUESTION_BUTTON],
77
+ ['with instruction', EXAMPLE_QUESTION_INSTRUCTION],
78
+ ['with `legendIsQuestionTitle`', EXAMPLE_QUESTION_LEGENDISQUESTIONTITLE],
79
+ ['with `readDescriptionFirst`', EXAMPLE_QUESTION_DESCRIPTION_FIRST],
80
+ [
81
+ 'with all options combined',
82
+ {
83
+ ...EXAMPLE_QUESTION_DEFINITION,
84
+ ...EXAMPLE_QUESTION_GUIDANCE,
85
+ ...EXAMPLE_QUESTION_JUSTIFICATION,
86
+ ...EXAMPLE_QUESTION_BUTTON,
87
+ ...EXAMPLE_QUESTION_INSTRUCTION,
88
+ ...EXAMPLE_QUESTION_LEGENDISQUESTIONTITLE,
89
+ ...EXAMPLE_QUESTION_DESCRIPTION_FIRST,
90
+ },
91
+ ],
92
+ ])('mode: %s', (_, params) => {
93
+ it('passes jest-axe checks with', async () => {
94
+ const $ = cheerio.load(renderComponent('question', params));
95
+
96
+ const results = await axe($.html());
97
+ expect(results).toHaveNoViolations();
98
+ });
99
+ });
100
+
101
+ describe('mode: with basic parameters', () => {
102
+ it('has the `title` text', () => {
103
+ const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_BASIC));
104
+
105
+ expect(
106
+ $('.ons-question__title')
107
+ .text()
108
+ .trim(),
109
+ ).toBe('Question title');
110
+ });
111
+
112
+ it('has the provided `id` attribute', () => {
113
+ const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_BASIC));
114
+
115
+ expect($('.ons-question').attr('id')).toBe('example-question');
116
+ });
117
+
118
+ it('has additionally provided `attributes`', () => {
119
+ const $ = cheerio.load(
120
+ renderComponent('question', {
121
+ ...EXAMPLE_QUESTION_BASIC,
122
+ attributes: {
123
+ a: 123,
124
+ b: 456,
125
+ },
126
+ }),
127
+ );
128
+
129
+ expect($('.ons-question').attr('a')).toBe('123');
130
+ expect($('.ons-question').attr('b')).toBe('456');
131
+ });
132
+
133
+ it('has additionally provided style classes', () => {
134
+ const $ = cheerio.load(
135
+ renderComponent('question', {
136
+ ...EXAMPLE_QUESTION_BASIC,
137
+ classes: 'extra-class another-extra-class',
138
+ }),
139
+ );
140
+
141
+ expect($('.ons-question').hasClass('extra-class')).toBe(true);
142
+ expect($('.ons-question').hasClass('another-extra-class')).toBe(true);
143
+ });
144
+
145
+ it('has the `description` text', () => {
146
+ const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_BASIC));
147
+
148
+ expect(
149
+ $('.ons-question__description')
150
+ .text()
151
+ .trim(),
152
+ ).toBe('Question description');
153
+ });
154
+
155
+ it('calls with content', () => {
156
+ const $ = cheerio.load(renderComponent('question', { EXAMPLE_QUESTION_BASIC }, 'Example content...'));
157
+
158
+ const content = $('.ons-question__answer')
159
+ .text()
160
+ .trim();
161
+ expect(content).toEqual(expect.stringContaining('Example content...'));
162
+ });
163
+ });
164
+
165
+ describe('mode: with definition', () => {
166
+ it('outputs the expected collapsible', () => {
167
+ const faker = templateFaker();
168
+ const collapsibleSpy = faker.spy('collapsible');
169
+
170
+ faker.renderComponent('question', EXAMPLE_QUESTION_DEFINITION);
171
+
172
+ expect(collapsibleSpy.occurrences[0]).toHaveProperty('classes', 'ons-u-mb-m');
173
+ expect(collapsibleSpy.occurrences[0]).toHaveProperty('id', 'definition-id');
174
+ expect(collapsibleSpy.occurrences[0]).toHaveProperty('title', 'Definition title');
175
+ });
176
+
177
+ it('outputs the expected collapsible call content', () => {
178
+ const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_DEFINITION));
179
+
180
+ expect($('.ons-collapsible__content > p').text()).toBe('Definition content');
181
+ });
182
+ });
183
+
184
+ describe('mode: with guidance', () => {
185
+ it('outputs the expected panel', () => {
186
+ const faker = templateFaker();
187
+ const panelSpy = faker.spy('panel');
188
+
189
+ faker.renderComponent('question', EXAMPLE_QUESTION_GUIDANCE);
190
+
191
+ expect(panelSpy.occurrences[0]).toHaveProperty('classes', 'ons-question-guidance ons-u-mb-m');
192
+ });
193
+
194
+ it('outputs the expected panel call content', () => {
195
+ const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_GUIDANCE));
196
+
197
+ expect($('.ons-panel__body .fake-content').text()).toBe('Guidance content');
198
+ });
199
+
200
+ it('outputs the expected `listHeading`', () => {
201
+ const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_GUIDANCE));
202
+
203
+ expect($('.ons-question-guidance__list-heading').text()).toBe('List heading 1');
204
+ });
205
+
206
+ it('outputs the expected `listLeadingLine`', () => {
207
+ const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_GUIDANCE));
208
+
209
+ expect($('.ons-question-guidance__list-leading-line').text()).toBe('List leading line 1');
210
+ });
211
+
212
+ it('outputs the expected list', () => {
213
+ const faker = templateFaker();
214
+ const listSpy = faker.spy('lists');
215
+
216
+ faker.renderComponent('question', EXAMPLE_QUESTION_GUIDANCE);
217
+
218
+ expect(listSpy.occurrences[0].itemsList).toEqual([
219
+ {
220
+ text: 'Test item 1',
221
+ },
222
+ {
223
+ text: 'Test item 2',
224
+ },
225
+ ]);
226
+ });
227
+ });
228
+
229
+ describe('mode: with justification', () => {
230
+ it('outputs the expected collapsible', () => {
231
+ const faker = templateFaker();
232
+ const collapsibleSpy = faker.spy('collapsible');
233
+
234
+ faker.renderComponent('question', EXAMPLE_QUESTION_JUSTIFICATION);
235
+
236
+ expect(collapsibleSpy.occurrences[0]).toHaveProperty('classes', 'ons-u-mb-m');
237
+ expect(collapsibleSpy.occurrences[0]).toHaveProperty('id', 'justification-id');
238
+ expect(collapsibleSpy.occurrences[0]).toHaveProperty('title', 'Justification title');
239
+ });
240
+
241
+ it('outputs the expected collapsible call content', () => {
242
+ const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_JUSTIFICATION));
243
+
244
+ expect($('.ons-collapsible__content > p').text()).toBe('Justification content');
245
+ });
246
+ });
247
+
248
+ describe('mode: with button', () => {
249
+ it('outputs the expected button', () => {
250
+ const faker = templateFaker();
251
+ const buttonSpy = faker.spy('button');
252
+
253
+ faker.renderComponent('question', EXAMPLE_QUESTION_BUTTON);
254
+
255
+ expect(buttonSpy.occurrences[0]).toHaveProperty('submitType', 'button');
256
+ expect(buttonSpy.occurrences[0]).toHaveProperty('id', 'button-id');
257
+ expect(buttonSpy.occurrences[0]).toHaveProperty('text', 'Button text');
258
+ });
259
+ });
260
+
261
+ describe('mode: with instruction', () => {
262
+ it('has the instruction text', () => {
263
+ const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_INSTRUCTION));
264
+
265
+ expect($('.ons-question__instruction').text()).toBe('Instruction text');
266
+ });
267
+ });
268
+
269
+ describe('mode: with `legendIsQuestionTitle`', () => {
270
+ it('has the expected `fieldset` output', () => {
271
+ const faker = templateFaker();
272
+ const fieldsetSpy = faker.spy('fieldset');
273
+
274
+ faker.renderComponent('question', EXAMPLE_QUESTION_LEGENDISQUESTIONTITLE);
275
+
276
+ expect(fieldsetSpy.occurrences[0]).toEqual({
277
+ legendIsQuestionTitle: true,
278
+ legend: 'Question title',
279
+ description: 'Question description',
280
+ legendClasses: undefined,
281
+ legendTitleClasses: undefined,
282
+ });
283
+ });
284
+
285
+ it('does not add the description style class', () => {
286
+ const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_LEGENDISQUESTIONTITLE));
287
+
288
+ expect($('.ons-question__description').length).toBe(0);
289
+ });
290
+ });
291
+
292
+ describe('mode: with `readDescriptionFirst`', () => {
293
+ it('has a description element visually hidden before the title', () => {
294
+ const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_DESCRIPTION_FIRST));
295
+
296
+ expect(
297
+ $('.ons-question__title')
298
+ .text()
299
+ .trim(),
300
+ ).toBe('Question description Question title');
301
+ });
302
+
303
+ it('has the visible description element with aria-hidden attribute', () => {
304
+ const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_DESCRIPTION_FIRST));
305
+
306
+ expect($('.ons-question__description--aria-hidden').attr('aria-hidden')).toBe('true');
307
+ });
308
+ });
309
+ });
@@ -0,0 +1,81 @@
1
+ /** @jest-environment jsdom */
2
+
3
+ import * as cheerio from 'cheerio';
4
+
5
+ import axe from '../../tests/helpers/axe';
6
+ import { renderComponent, templateFaker } from '../../tests/helpers/rendering';
7
+
8
+ describe('macro: quote', () => {
9
+ it('passes jest-axe checks', async () => {
10
+ const $ = cheerio.load(
11
+ renderComponent('quote', {
12
+ text: 'Example quote text.',
13
+ ref: 'Example quote reference.',
14
+ }),
15
+ );
16
+
17
+ const results = await axe($.html());
18
+ expect(results).toHaveNoViolations();
19
+ });
20
+
21
+ it('has the provided `text` text', () => {
22
+ const $ = cheerio.load(
23
+ renderComponent('quote', {
24
+ text: 'Example quote text.',
25
+ }),
26
+ );
27
+
28
+ expect(
29
+ $('.ons-quote__text')
30
+ .text()
31
+ .trim(),
32
+ ).toBe('Example quote text.');
33
+ });
34
+
35
+ it('has the provided `ref` text with a leading "—" character', () => {
36
+ const $ = cheerio.load(
37
+ renderComponent('quote', {
38
+ text: 'Example quote text.',
39
+ ref: 'Example quote reference.',
40
+ }),
41
+ );
42
+
43
+ expect(
44
+ $('.ons-quote__ref')
45
+ .text()
46
+ .trim(),
47
+ ).toBe('— Example quote reference.');
48
+ });
49
+
50
+ it('has a default `textFontSize` of "l"', () => {
51
+ const $ = cheerio.load(
52
+ renderComponent('quote', {
53
+ text: 'Example quote text.',
54
+ }),
55
+ );
56
+
57
+ expect($('.ons-quote__text').hasClass('ons-u-fs-l')).toBe(true);
58
+ });
59
+
60
+ it('has the provided `textFontSize`', () => {
61
+ const $ = cheerio.load(
62
+ renderComponent('quote', {
63
+ text: 'Example quote text.',
64
+ textFontSize: 's',
65
+ }),
66
+ );
67
+
68
+ expect($('.ons-quote__text').hasClass('ons-u-fs-s')).toBe(true);
69
+ });
70
+
71
+ it('has `quote` icon', () => {
72
+ const faker = templateFaker();
73
+ const iconsSpy = faker.spy('icons');
74
+
75
+ faker.renderComponent('quote', {
76
+ text: 'Example quote text.',
77
+ });
78
+
79
+ expect(iconsSpy.occurrences[0].iconType).toBe('quote');
80
+ });
81
+ });
@@ -54,7 +54,7 @@
54
54
  "name": radio.other.name,
55
55
  "type": radio.other.type,
56
56
  "required": radio.other.required,
57
- "classes": ("ons-input--error" if params.error else "") + radio.other.classes | default(''),
57
+ "classes": ("ons-input--error " if params.error else "") + radio.other.classes | default(''),
58
58
  "width": radio.other.width | default('auto'),
59
59
  "attributes": radio.other.attributes,
60
60
  "label": {
@@ -73,17 +73,14 @@
73
73
  "id": radio.other.id,
74
74
  "name": radio.other.name,
75
75
  "options": radio.other.options,
76
- "classes": ("ons-input--error" if params.error else "") + radio.other.classes | default(''),
76
+ "classes": ("ons-input--error " if params.error else "") + radio.other.classes | default(''),
77
77
  "label": {
78
78
  "id": radio.other.id + "-label",
79
79
  "text": radio.other.label.text,
80
80
  "classes": 'ons-u-fw-n'
81
81
  },
82
82
  "dontWrap": true,
83
- "value": radio.other.value,
84
- "select": {
85
- "error": params.error
86
- }
83
+ "value": radio.other.value
87
84
  })
88
85
  }}
89
86
  {% elif otherType == "checkboxes" %}