@muonic/muon 0.0.2-beta.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 (124) hide show
  1. package/.nycrc +17 -0
  2. package/.versionrc +3 -0
  3. package/CHANGELOG.md +389 -0
  4. package/components/card/index.js +1 -0
  5. package/components/card/src/card-component.js +43 -0
  6. package/components/card/src/card-styles.css +25 -0
  7. package/components/card/src/config-tokens.json +11 -0
  8. package/components/card/src/design-tokens.json +34 -0
  9. package/components/card/story.js +52 -0
  10. package/components/cta/index.js +1 -0
  11. package/components/cta/src/config-tokens.json +11 -0
  12. package/components/cta/src/cta-component.js +174 -0
  13. package/components/cta/src/cta-styles.css +105 -0
  14. package/components/cta/src/design-tokens.json +132 -0
  15. package/components/cta/story.js +99 -0
  16. package/components/detail/index.js +1 -0
  17. package/components/detail/src/config-tokens.json +11 -0
  18. package/components/detail/src/design-tokens.json +102 -0
  19. package/components/detail/src/detail-component.js +27 -0
  20. package/components/detail/src/detail-styles.css +83 -0
  21. package/components/detail/story.js +33 -0
  22. package/components/form/index.js +1 -0
  23. package/components/form/src/config-tokens.json +11 -0
  24. package/components/form/src/design-tokens.json +9 -0
  25. package/components/form/src/form-component.js +197 -0
  26. package/components/form/src/form-styles.css +10 -0
  27. package/components/form/story.js +71 -0
  28. package/components/icon/index.js +1 -0
  29. package/components/icon/src/config-tokens.json +31 -0
  30. package/components/icon/src/design-tokens.json +8 -0
  31. package/components/icon/src/icon-component.js +91 -0
  32. package/components/icon/src/icon-styles.css +26 -0
  33. package/components/icon/story.js +26 -0
  34. package/components/image/index.js +1 -0
  35. package/components/image/src/config-tokens.json +26 -0
  36. package/components/image/src/image-component.js +96 -0
  37. package/components/image/src/image-styles.css +71 -0
  38. package/components/image/story.js +31 -0
  39. package/components/inputter/index.js +1 -0
  40. package/components/inputter/src/config-tokens.json +14 -0
  41. package/components/inputter/src/design-tokens.json +308 -0
  42. package/components/inputter/src/inputter-component.js +227 -0
  43. package/components/inputter/src/inputter-styles-detail.css +59 -0
  44. package/components/inputter/src/inputter-styles.css +305 -0
  45. package/components/inputter/src/inputter-styles.slotted.css +64 -0
  46. package/components/inputter/story.js +243 -0
  47. package/css/accessibility.css +3 -0
  48. package/css/default.css +9 -0
  49. package/css/global.css +8 -0
  50. package/directives/image-loader-directive.js +116 -0
  51. package/directives/svg-loader-directive.js +94 -0
  52. package/index.js +52 -0
  53. package/mixins/card-mixin.js +27 -0
  54. package/mixins/detail-mixin.js +128 -0
  55. package/mixins/form-associate-mixin.js +36 -0
  56. package/mixins/form-element-mixin.js +378 -0
  57. package/mixins/image-holder-mixin.js +20 -0
  58. package/mixins/mask-mixin.js +159 -0
  59. package/mixins/validation-mixin.js +272 -0
  60. package/muon-element/index.js +97 -0
  61. package/package.json +72 -0
  62. package/rollup.config.mjs +30 -0
  63. package/scripts/build/storybook/index.mjs +11 -0
  64. package/scripts/build/storybook/run.mjs +47 -0
  65. package/scripts/rollup-plugins.mjs +116 -0
  66. package/scripts/serve/index.mjs +11 -0
  67. package/scripts/serve/run.mjs +27 -0
  68. package/scripts/style-dictionary.mjs +64 -0
  69. package/scripts/utils/config.mjs +30 -0
  70. package/scripts/utils/index.mjs +283 -0
  71. package/storybook/find-stories.js +36 -0
  72. package/storybook/server.config.mjs +19 -0
  73. package/storybook/stories.js +86 -0
  74. package/storybook/tokens/color.js +87 -0
  75. package/storybook/tokens/font.js +52 -0
  76. package/storybook/tokens/spacer.js +48 -0
  77. package/tests/README.md +3 -0
  78. package/tests/components/card/__snapshots__/card.test.snap.js +70 -0
  79. package/tests/components/card/card.test.js +81 -0
  80. package/tests/components/cta/__snapshots__/cta.test.snap.js +246 -0
  81. package/tests/components/cta/cta.test.js +212 -0
  82. package/tests/components/form/__snapshots__/form.test.snap.js +115 -0
  83. package/tests/components/form/form.test.js +336 -0
  84. package/tests/components/icon/__snapshots__/icon.test.snap.js +95 -0
  85. package/tests/components/icon/icon.test.js +197 -0
  86. package/tests/components/image/__snapshots__/image.test.snap.js +205 -0
  87. package/tests/components/image/image.test.js +314 -0
  88. package/tests/components/image/images/15.png +0 -0
  89. package/tests/components/image/images/150.png +0 -0
  90. package/tests/components/inputter/__snapshots__/inputter.test.snap.js +357 -0
  91. package/tests/components/inputter/inputter.test.js +427 -0
  92. package/tests/helpers/index.js +30 -0
  93. package/tests/mixins/__snapshots__/card.test.snap.js +35 -0
  94. package/tests/mixins/__snapshots__/detail.test.snap.js +237 -0
  95. package/tests/mixins/__snapshots__/form-element.test.snap.js +137 -0
  96. package/tests/mixins/__snapshots__/mask.test.snap.js +53 -0
  97. package/tests/mixins/__snapshots__/validation.test.snap.js +297 -0
  98. package/tests/mixins/card.test.js +63 -0
  99. package/tests/mixins/detail.test.js +223 -0
  100. package/tests/mixins/form-element.test.js +473 -0
  101. package/tests/mixins/mask.test.js +261 -0
  102. package/tests/mixins/muon-element.test.js +52 -0
  103. package/tests/mixins/validation.test.js +423 -0
  104. package/tests/runner/commands.mjs +19 -0
  105. package/tests/scripts/utils/card-component.js +26 -0
  106. package/tests/scripts/utils/muon.config.test.json +13 -0
  107. package/tests/scripts/utils/single.component.config.json +5 -0
  108. package/tests/scripts/utils/test-runner.mjs +1 -0
  109. package/tests/scripts/utils/utils-test.mjs +284 -0
  110. package/tests/utils/validation.functions.test.js +199 -0
  111. package/tokens/theme/color.json +482 -0
  112. package/tokens/theme/font.json +61 -0
  113. package/tokens/theme/size.json +27 -0
  114. package/tokens/theme/spacer.json +73 -0
  115. package/tokens/utils/formats/reference.js +17 -0
  116. package/tokens/utils/modular-scale.js +33 -0
  117. package/tokens/utils/templates/font-face.css.template +30 -0
  118. package/tokens/utils/transforms/color.js +27 -0
  119. package/tokens/utils/transforms/string.js +6 -0
  120. package/tokens/utils/validation.json +76 -0
  121. package/utils/scroll/index.js +31 -0
  122. package/utils/validation/index.js +205 -0
  123. package/web-test-runner.browserstack.config.mjs +123 -0
  124. package/web-test-runner.config.mjs +44 -0
@@ -0,0 +1,427 @@
1
+ /* eslint-disable no-undef */
2
+ import { expect, fixture, html, defineCE, unsafeStatic } from '@open-wc/testing';
3
+ import { Inputter } from '@muonic/muon/components/inputter';
4
+ import { defaultChecks, fillIn } from '../../helpers';
5
+ import sinon from 'sinon';
6
+
7
+ const tagName = defineCE(Inputter);
8
+ const tag = unsafeStatic(tagName);
9
+
10
+ describe('Inputter', () => {
11
+ it('standard default', async () => {
12
+ const inputter = await fixture(html`<${tag}></${tag}>`);
13
+
14
+ await defaultChecks(inputter);
15
+
16
+ expect(inputter.type).to.equal('standard', 'default type is set');
17
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
18
+ });
19
+
20
+ describe('helper', async () => {
21
+ it('text', async () => {
22
+ const inputter = await fixture(html`
23
+ <${tag} helper="What is this?">
24
+ <label slot="label">input label</label>
25
+ <input type="text" value=""/>
26
+ </${tag}>`);
27
+ const shadowRoot = inputter.shadowRoot;
28
+
29
+ await defaultChecks(inputter);
30
+ expect(inputter.type).to.equal('standard', 'default type is set');
31
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
32
+
33
+ expect(shadowRoot.querySelector('inputter-detail')).to.be.null; // eslint-disable-line no-unused-expressions
34
+
35
+ const helper = shadowRoot.querySelector('.helper');
36
+ expect(helper.textContent).to.equal('What is this?', 'helper text has correct value'); // eslint-disable-line no-unused-expressions
37
+ expect(getComputedStyle(helper).color).to.equal('rgb(64, 64, 64)', 'helper has correct color');
38
+ });
39
+
40
+ it('detail', async () => {
41
+ const inputter = await fixture(html`
42
+ <${tag} helper="What is this?">
43
+ <label slot="label">input label</label>
44
+ <input type="text" value=""/>
45
+ <p slot="tip-details">More info about the input</p>
46
+ </${tag}>`);
47
+ const shadowRoot = inputter.shadowRoot;
48
+
49
+ await defaultChecks(inputter);
50
+ expect(inputter.type).to.equal('standard', 'default type is set');
51
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
52
+
53
+ const inputterDetail = shadowRoot.querySelector('inputter-detail');
54
+ expect(inputterDetail).to.be.not.null; // eslint-disable-line no-unused-expressions
55
+ expect(inputterDetail.open).to.be.false; // eslint-disable-line no-unused-expressions
56
+ expect(inputterDetail.querySelector('[slot="heading"]').textContent).to.equal('What is this?', 'helper text has correct value');
57
+ expect(inputterDetail.querySelector('[name="tip-details"]').assignedNodes()[0].textContent)
58
+ .to.equal('More info about the input', 'tip details has correct value');
59
+
60
+ const detailShadowRoot = inputterDetail.shadowRoot;
61
+ const detailsElement = detailShadowRoot.querySelector('.details');
62
+ expect(getComputedStyle(detailsElement).color).to.equal('rgb(64, 64, 64)', 'helper has correct color');
63
+
64
+ const content = detailShadowRoot.querySelector('.content');
65
+ expect(getComputedStyle(content).borderInlineStartColor).to.equal('rgb(201, 201, 201)', 'helper detail has correct border start colour');
66
+ });
67
+
68
+ it('detail open', async () => {
69
+ const inputter = await fixture(html`
70
+ <${tag} helper="What is this?" isHelperOpen>
71
+ <label slot="label">input label</label>
72
+ <input type="text" value=""/>
73
+ <p slot="tip-details">More info about the input</p>
74
+ </${tag}>`);
75
+ const shadowRoot = inputter.shadowRoot;
76
+
77
+ await defaultChecks(inputter);
78
+ expect(inputter.type).to.equal('standard', 'default type is set');
79
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
80
+
81
+ const inputterDetail = shadowRoot.querySelector('inputter-detail');
82
+ expect(inputterDetail).to.be.not.null; // eslint-disable-line no-unused-expressions
83
+ expect(inputterDetail.open).to.be.true; // eslint-disable-line no-unused-expressions
84
+ expect(inputterDetail.querySelector('[slot="heading"]').textContent).to.equal('What is this?', 'helper text has correct value');
85
+ expect(inputterDetail.querySelector('[name="tip-details"]').assignedNodes()[0].textContent)
86
+ .to.equal('More info about the input', 'tip details has correct value');
87
+ });
88
+ });
89
+
90
+ describe('text', async () => {
91
+ it('disabled', async () => {
92
+ const inputter = await fixture(html`
93
+ <${tag}>
94
+ <label slot="label">input label</label>
95
+ <input type="text" value="" disabled/>
96
+ </${tag}>`);
97
+ const shadowRoot = inputter.shadowRoot;
98
+
99
+ await defaultChecks(inputter);
100
+ expect(inputter.type).to.equal('standard', 'default type is set');
101
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
102
+
103
+ const mask = shadowRoot.querySelector('.has-mask');
104
+ expect(mask).to.be.null; // eslint-disable-line no-unused-expressions
105
+ expect(shadowRoot.querySelector('.has-disabled')).to.not.be.null; // eslint-disable-line no-unused-expressions
106
+
107
+ const inputElement = inputter.querySelector('input');
108
+ expect(getComputedStyle(inputElement).color).to.equal('rgb(176, 176, 176)', 'disabled input has correct colour');
109
+ expect(getComputedStyle(inputElement).backgroundColor).to.equal('rgb(226, 226, 226)', 'disabled input has correct background colour');
110
+ expect(getComputedStyle(inputElement).borderTopColor).to.equal('rgb(176, 176, 176)', 'disabled input has correct border top colour');
111
+ expect(getComputedStyle(inputElement).borderBottomColor).to.equal('rgb(176, 176, 176)', 'disabled input has correct border bottom colour');
112
+ expect(getComputedStyle(inputElement).borderLeftColor).to.equal('rgb(176, 176, 176)', 'disabled input has correct border left colour');
113
+ expect(getComputedStyle(inputElement).borderRightColor).to.equal('rgb(176, 176, 176)', 'disabled input has correct border right colour');
114
+ });
115
+
116
+ it('mask text', async () => {
117
+ const inputter = await fixture(html`
118
+ <${tag} mask="0000">
119
+ <label slot="label">input label</label>
120
+ <input type="text" value=""/>
121
+ </${tag}>`);
122
+ const shadowRoot = inputter.shadowRoot;
123
+
124
+ await defaultChecks(inputter);
125
+ expect(inputter.type).to.equal('standard', 'default type is set');
126
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
127
+
128
+ const mask = shadowRoot.querySelector('.has-mask');
129
+ expect(mask).to.not.be.null; // eslint-disable-line no-unused-expressions
130
+ expect(shadowRoot.querySelector('.has-disabled')).to.be.null; // eslint-disable-line no-unused-expressions
131
+
132
+ const inputMask = shadowRoot.querySelector('.input-mask');
133
+ expect(inputMask).to.not.be.null; // eslint-disable-line no-unused-expressions
134
+
135
+ expect(getComputedStyle(inputMask).fontFamily).contains('Courier, monospace', 'mask has correct font family');
136
+ expect(getComputedStyle(inputMask).color).to.equal('rgb(118, 118, 118)', 'mask has correct color');
137
+ });
138
+
139
+ it('validation on input', async () => {
140
+ const inputter = await fixture(html`
141
+ <${tag} validation=["isRequired","isBetween(8,20)"]>
142
+ <label slot="label">input label</label>
143
+ <input type="text" value=""/>
144
+ </${tag}>`);
145
+ const shadowRoot = inputter.shadowRoot;
146
+
147
+ await defaultChecks(inputter);
148
+ const changeEventSpy = sinon.spy();
149
+ inputter.addEventListener('change', changeEventSpy);
150
+
151
+ expect(inputter.type).to.equal('standard', 'default type is set');
152
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
153
+ const inputElement = inputter.querySelector('input');
154
+ await fillIn(inputElement, 'abcd', 'input');
155
+
156
+ await inputter.updateComplete;
157
+ expect(changeEventSpy.callCount).to.equal(1, '`change` event fired');
158
+ expect(changeEventSpy.lastCall.args[0].detail.value).to.equal('abcd', '`change` event has value `abcd`');
159
+ const validation = shadowRoot.querySelector('.validation');
160
+ expect(validation).to.not.be.null; // eslint-disable-line no-unused-expressions
161
+ expect(getComputedStyle(validation).color).to.equal('rgb(227, 102, 14)', 'validation has correct color');
162
+
163
+ const validationMessage = shadowRoot.querySelector('.validation .message');
164
+ expect(validationMessage).to.not.be.null; // eslint-disable-line no-unused-expressions
165
+ expect(validationMessage.textContent.trim()).to.equal('Length must be between 8 and 20 characters.', 'validation message has correct value');
166
+
167
+ const validationIcon = shadowRoot.querySelector('.validation .icon');
168
+ expect(validationIcon).to.not.be.null; // eslint-disable-line no-unused-expressions
169
+ expect(validationIcon.name).to.equal('exclamation-circle', 'validation icon has correct value');
170
+ });
171
+
172
+ it('validation on change', async () => {
173
+ const inputter = await fixture(html`
174
+ <${tag} validation=["isRequired","isBetween(8,20)"]>
175
+ <label slot="label">input label</label>
176
+ <input type="text" value=""/>
177
+ </${tag}>`);
178
+ const shadowRoot = inputter.shadowRoot;
179
+
180
+ await defaultChecks(inputter);
181
+ const changeEventSpy = sinon.spy();
182
+ inputter.addEventListener('change', changeEventSpy);
183
+
184
+ expect(inputter.type).to.equal('standard', 'default type is set');
185
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
186
+ const inputElement = inputter.querySelector('input');
187
+ await fillIn(inputElement, 'abcd', 'change');
188
+
189
+ await inputter.updateComplete;
190
+ expect(changeEventSpy.callCount).to.equal(1, '`change` event fired');
191
+ expect(changeEventSpy.lastCall.args[0].detail.value).to.equal('abcd', '`change` event has value `abcd`');
192
+ const validation = shadowRoot.querySelector('.validation');
193
+ expect(validation).to.not.be.null; // eslint-disable-line no-unused-expressions
194
+ expect(getComputedStyle(validation).color).to.equal('rgb(227, 102, 14)', 'validation has correct color');
195
+
196
+ const validationMessage = shadowRoot.querySelector('.validation .message');
197
+ expect(validationMessage).to.not.be.null; // eslint-disable-line no-unused-expressions
198
+ expect(validationMessage.textContent.trim()).to.equal('Length must be between 8 and 20 characters.', 'validation message has correct value');
199
+
200
+ const validationIcon = shadowRoot.querySelector('.validation .icon');
201
+ expect(validationIcon).to.not.be.null; // eslint-disable-line no-unused-expressions
202
+ expect(validationIcon.name).to.equal('exclamation-circle', 'validation icon has correct value');
203
+ });
204
+
205
+ it('mask & validation', async () => {
206
+ const inputter = await fixture(html`
207
+ <${tag} mask="0000" validation=["isRequired"]>
208
+ <label slot="label">input label</label>
209
+ <input type="text" value=""/>
210
+ </${tag}>`);
211
+ const shadowRoot = inputter.shadowRoot;
212
+
213
+ await defaultChecks(inputter);
214
+ inputter.value = '12';
215
+ const changeEventSpy = sinon.spy();
216
+ inputter.addEventListener('change', changeEventSpy);
217
+
218
+ expect(inputter.type).to.equal('standard', 'default type is set');
219
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
220
+
221
+ const mask = shadowRoot.querySelector('.has-mask');
222
+ expect(mask).to.not.be.null; // eslint-disable-line no-unused-expressions
223
+
224
+ let inputMask = shadowRoot.querySelector('.input-mask');
225
+ expect(inputMask).to.not.be.null; // eslint-disable-line no-unused-expressions
226
+
227
+ const inputElement = inputter.querySelector('input');
228
+ await fillIn(inputElement, '', 'change');
229
+
230
+ await inputter.updateComplete;
231
+ expect(changeEventSpy.callCount).to.equal(1, '`change` event fired');
232
+ expect(changeEventSpy.lastCall.args[0].detail.value).to.equal('', '`change` event has value ``');
233
+ let validation = shadowRoot.querySelector('.validation');
234
+ expect(validation).to.not.be.null; // eslint-disable-line no-unused-expressions
235
+ expect(getComputedStyle(validation).color).to.equal('rgb(227, 102, 14)', 'validation has correct color');
236
+
237
+ const validationMessage = shadowRoot.querySelector('.validation .message');
238
+ expect(validationMessage).to.not.be.null; // eslint-disable-line no-unused-expressions
239
+ expect(validationMessage.textContent.trim()).to.equal('This field is required.', 'validation message has correct value');
240
+
241
+ const validationIcon = shadowRoot.querySelector('.validation .icon');
242
+ expect(validationIcon).to.not.be.null; // eslint-disable-line no-unused-expressions
243
+ expect(validationIcon.name).to.equal('exclamation-circle', 'validation icon has correct value');
244
+
245
+ await fillIn(inputElement, '123', 'input');
246
+ await inputter.updateComplete;
247
+ expect(changeEventSpy.callCount).to.equal(2, '`change` event fired');
248
+ expect(changeEventSpy.lastCall.args[0].detail.value).to.equal('123', '`change` event has value `123`');
249
+ validation = shadowRoot.querySelector('.validation');
250
+ expect(validation).to.be.null; // eslint-disable-line no-unused-expressions
251
+
252
+ inputMask = shadowRoot.querySelector('.input-mask');
253
+ expect(inputMask.textContent).to.be.equal(' 0', '`input-mask` has correct value');
254
+ });
255
+ });
256
+
257
+ describe('radio', async () => {
258
+ it('standard radio', async () => {
259
+ const inputter = await fixture(html`
260
+ <${tag} heading="What is your heating source?">
261
+ <input type="radio" id="question-gas" name="question" value="gas"></input>
262
+ <label for="question-gas">Gas</label>
263
+ <input type="radio" id="question-electricity" name="question" value="electricity"></input>
264
+ <label for="question-electricity">Electricity</label>
265
+ </${tag}>`);
266
+ const shadowRoot = inputter.shadowRoot;
267
+
268
+ await defaultChecks(inputter);
269
+ expect(inputter.type).to.equal('standard', 'default type is set');
270
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
271
+ expect(shadowRoot.querySelector('.input-heading')).to.not.be.null; // eslint-disable-line no-unused-expressions
272
+ expect(shadowRoot.querySelector('.input-mask')).to.be.null; // eslint-disable-line no-unused-expressions
273
+ });
274
+
275
+ it('radio mask', async () => {
276
+ const inputter = await fixture(html`
277
+ <${tag} mask="xxx" heading="What is your heating source?">
278
+ <input type="radio" id="question-gas" name="question" value="gas" checked></input>
279
+ <label for="question-gas">Gas</label>
280
+ <input type="radio" id="question-electricity" name="question" value="electricity"></input>
281
+ <label for="question-electricity">Electricity</label>
282
+ </${tag}>`);
283
+ const shadowRoot = inputter.shadowRoot;
284
+
285
+ await defaultChecks(inputter);
286
+ expect(inputter.type).to.equal('standard', 'default type is set');
287
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
288
+ expect(shadowRoot.querySelector('.input-heading')).to.not.be.null; // eslint-disable-line no-unused-expressions
289
+ expect(shadowRoot.querySelector('.input-mask')).to.be.null; // eslint-disable-line no-unused-expressions
290
+
291
+ const changeEventSpy = sinon.spy();
292
+ inputter.addEventListener('change', changeEventSpy);
293
+ const inputElement = inputter.querySelectorAll('input');
294
+
295
+ // eslint-disable-next-line no-unused-expressions
296
+ expect(inputElement[0].checked).to.true;
297
+
298
+ inputElement[1].click();
299
+ // eslint-disable-next-line no-unused-expressions
300
+ expect(inputElement[0].checked).to.false;
301
+ // eslint-disable-next-line no-unused-expressions
302
+ expect(inputElement[1].checked).to.true;
303
+ expect(inputter.value).to.equal('electricity', '`value` property has value `electricity`');
304
+ expect(changeEventSpy.callCount).to.equal(1, '`change` event fired');
305
+ expect(changeEventSpy.lastCall.args[0].detail.value).to.equal('electricity', '`change` event has value `electricity`');
306
+ expect(shadowRoot.querySelector('.input-mask')).to.be.null; // eslint-disable-line no-unused-expressions
307
+ });
308
+
309
+ it('radio mask validation', async () => {
310
+ const inputter = await fixture(html`
311
+ <${tag} mask="xxx" heading="What is your heating source?" validation=["isRequired"]>
312
+ <input type="radio" id="question-gas" name="question" value="gas"></input>
313
+ <label for="question-gas">Gas</label>
314
+ <input type="radio" id="question-electricity" name="question" value="electricity"></input>
315
+ <label for="question-electricity">Electricity</label>
316
+ </${tag}>`);
317
+ const shadowRoot = inputter.shadowRoot;
318
+
319
+ await defaultChecks(inputter);
320
+ expect(inputter.type).to.equal('standard', 'default type is set');
321
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
322
+ expect(shadowRoot.querySelector('.input-heading')).to.not.be.null; // eslint-disable-line no-unused-expressions
323
+ expect(shadowRoot.querySelector('.input-mask')).to.be.null; // eslint-disable-line no-unused-expressions
324
+
325
+ const changeEventSpy = sinon.spy();
326
+ inputter.addEventListener('change', changeEventSpy);
327
+ const inputElement = inputter.querySelectorAll('input');
328
+
329
+ // eslint-disable-next-line no-unused-expressions
330
+ expect(inputElement[0].checked).to.false;
331
+ // eslint-disable-next-line no-unused-expressions
332
+ expect(inputElement[1].checked).to.false;
333
+
334
+ await inputElement[1].focus();
335
+ await inputElement[1].blur();
336
+
337
+ await inputter.updateComplete;
338
+ let validation = shadowRoot.querySelector('.validation');
339
+ expect(validation).to.not.be.null; // eslint-disable-line no-unused-expressions
340
+ expect(getComputedStyle(validation).color).to.equal('rgb(227, 102, 14)', 'validation has correct color');
341
+
342
+ const validationMessage = shadowRoot.querySelector('.validation .message');
343
+ expect(validationMessage).to.not.be.null; // eslint-disable-line no-unused-expressions
344
+ expect(validationMessage.textContent.trim()).to.equal('This field is required.', 'validation message has correct value');
345
+
346
+ const validationIcon = shadowRoot.querySelector('.validation .icon');
347
+ expect(validationIcon).to.not.be.null; // eslint-disable-line no-unused-expressions
348
+ expect(validationIcon.name).to.equal('exclamation-circle', 'validation icon has correct value');
349
+ inputElement[1].click();
350
+
351
+ await inputter.updateComplete;
352
+ // eslint-disable-next-line no-unused-expressions
353
+ expect(inputElement[0].checked).to.false;
354
+ // eslint-disable-next-line no-unused-expressions
355
+ expect(inputElement[1].checked).to.true;
356
+ expect(inputter.value).to.equal('electricity', '`value` property has value `electricity`');
357
+ expect(changeEventSpy.callCount).to.equal(1, '`change` event fired');
358
+ expect(changeEventSpy.lastCall.args[0].detail.value).to.equal('electricity', '`change` event has value `electricity`');
359
+ expect(shadowRoot.querySelector('.input-mask')).to.be.null; // eslint-disable-line no-unused-expressions
360
+ validation = shadowRoot.querySelector('.validation');
361
+ expect(validation).to.be.null; // eslint-disable-line no-unused-expressions
362
+ });
363
+ });
364
+
365
+ describe('select', async () => {
366
+ it('standard select', async () => {
367
+ const inputter = await fixture(html`
368
+ <${tag}>
369
+ <label slot="label">Select</label>
370
+ <select name="select">
371
+ <option value="">Please select</option>
372
+ <option value="value-01">Value one</option>
373
+ <option value="value-02">Value two</option>
374
+ <option value="value-03">Value three</option>
375
+ <option value="value-04">Value four</option>
376
+ </select>
377
+ </${tag}>`);
378
+ const shadowRoot = inputter.shadowRoot;
379
+
380
+ await defaultChecks(inputter);
381
+ expect(inputter.type).to.equal('standard', 'default type is set');
382
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
383
+
384
+ expect(shadowRoot.querySelector('.select')).to.not.be.null; // eslint-disable-line no-unused-expressions
385
+ expect(shadowRoot.querySelector('inputter-icon[name="chevron-circle-down"]')).to.not.be.null; // eslint-disable-line no-unused-expressions
386
+ expect(shadowRoot.querySelector('.input-mask')).to.be.null; // eslint-disable-line no-unused-expressions
387
+ });
388
+ });
389
+
390
+ describe('search', async () => {
391
+ it('standard search', async () => {
392
+ const inputter = await fixture(html`
393
+ <${tag}>
394
+ <label slot="label">Search</label>
395
+ <input type="search">
396
+ </${tag}>`);
397
+ const shadowRoot = inputter.shadowRoot;
398
+
399
+ await defaultChecks(inputter);
400
+ expect(inputter.type).to.equal('standard', 'default type is set');
401
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
402
+
403
+ expect(shadowRoot.querySelector('.search')).to.not.be.null; // eslint-disable-line no-unused-expressions
404
+ expect(shadowRoot.querySelector('inputter-icon[name="search"]')).to.not.be.null; // eslint-disable-line no-unused-expressions
405
+ expect(shadowRoot.querySelector('.input-mask')).to.be.null; // eslint-disable-line no-unused-expressions
406
+ });
407
+ });
408
+
409
+ describe('date', async () => {
410
+ it('standard date', async () => {
411
+ const inputter = await fixture(html`
412
+ <${tag}>
413
+ <label slot="label">Date</label>
414
+ <input type="date">
415
+ </${tag}>`);
416
+ const shadowRoot = inputter.shadowRoot;
417
+
418
+ await defaultChecks(inputter);
419
+ expect(inputter.type).to.equal('standard', 'default type is set');
420
+ expect(inputter.id).to.not.be.null; // eslint-disable-line no-unused-expressions
421
+
422
+ expect(shadowRoot.querySelector('.date')).to.not.be.null; // eslint-disable-line no-unused-expressions
423
+ expect(shadowRoot.querySelector('inputter-icon[name="calendar"]')).to.not.be.null; // eslint-disable-line no-unused-expressions
424
+ expect(shadowRoot.querySelector('.input-mask')).to.be.null; // eslint-disable-line no-unused-expressions
425
+ });
426
+ });
427
+ });
@@ -0,0 +1,30 @@
1
+ import { expect } from '@open-wc/testing';
2
+ import { executeServerCommand } from '@web/test-runner-commands';
3
+
4
+ export const defaultChecks = async (el) => {
5
+ const snapshotOptions = await executeServerCommand('run-snapshots');
6
+ if (snapshotOptions?.run === true) {
7
+ await expect(el).shadowDom.to.equalSnapshot();
8
+ }
9
+
10
+ await expect(el).to.be.accessible();
11
+ };
12
+
13
+ export const fireEvent = async (element, event) => {
14
+ const customEvent = new CustomEvent(event, { bubbles: true });
15
+ await element.dispatchEvent(customEvent);
16
+ };
17
+
18
+ const fireChangeEvent = async (element) => {
19
+ await fireEvent(element, 'change');
20
+ };
21
+
22
+ export const fillIn = async (element, content, event = 'change') => {
23
+ element.value = content;
24
+ await fireEvent(element, event);
25
+ };
26
+
27
+ export const selectEvent = async (element, value) => {
28
+ element.value = value;
29
+ await fireChangeEvent(element);
30
+ };
@@ -0,0 +1,35 @@
1
+ /* @web/test-runner snapshot v1 */
2
+ export const snapshots = {};
3
+
4
+ snapshots["card standard"] =
5
+ `<div class="header">
6
+ <slot name="header">
7
+ </slot>
8
+ </div>
9
+ <div class="content">
10
+ <slot>
11
+ </slot>
12
+ </div>
13
+ <div class="footer">
14
+ <slot name="footer">
15
+ </slot>
16
+ </div>
17
+ `;
18
+ /* end snapshot card standard */
19
+
20
+ snapshots["card default"] =
21
+ `<div class="header">
22
+ <slot name="header">
23
+ </slot>
24
+ </div>
25
+ <div class="content">
26
+ <slot>
27
+ </slot>
28
+ </div>
29
+ <div class="footer">
30
+ <slot name="footer">
31
+ </slot>
32
+ </div>
33
+ `;
34
+ /* end snapshot card default */
35
+