@kubex/zinc 1.1.115 → 1.1.116
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.
- package/dist/custom-elements.json +411 -175
- package/dist/vscode.html-custom-data.json +71 -26
- package/dist/web-types.json +171 -51
- package/dist/zn.d.ts +182 -48
- package/dist/zn.min.js +581 -588
- package/docs/pages/components/dialog.md +45 -16
- package/docs/pages/components/translation-group.md +102 -93
- package/docs/pages/components/translations.md +64 -114
- package/package.json +1 -1
- package/src/components/dialog/dialog.component.ts +2 -1
- package/src/components/dialog/dialog.scss +8 -0
- package/src/components/header/header.component.ts +2 -1
- package/src/components/select/select.component.ts +5 -0
- package/src/components/select/select.scss +11 -0
- package/src/components/translation-group/translation-group.component.ts +171 -198
- package/src/components/translation-group/translation-group.scss +124 -1
- package/src/components/translation-group/translation-group.test.ts +371 -2
- package/src/components/translations/translations.component.ts +249 -209
- package/src/components/translations/translations.scss +3 -25
- package/src/components/translations/translations.test.ts +214 -10
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import '../../../dist/zn.min.js';
|
|
2
2
|
import { expect, fixture, html } from '@open-wc/testing';
|
|
3
|
-
import type
|
|
3
|
+
import type ZnInput from '../input/input.component';
|
|
4
|
+
import type ZnSelect from '../select/select.component';
|
|
5
|
+
import type ZnTranslationGroup from './translation-group.component';
|
|
4
6
|
import type ZnTranslations from '../translations/translations.component';
|
|
5
7
|
|
|
6
8
|
describe('<zn-translation-group>', () => {
|
|
@@ -16,7 +18,374 @@ describe('<zn-translation-group>', () => {
|
|
|
16
18
|
await child.updateComplete;
|
|
17
19
|
|
|
18
20
|
expect(child.values).to.deep.equal({en: 'Chat to us'});
|
|
19
|
-
const input = child.shadowRoot!.querySelector<
|
|
21
|
+
const input = child.shadowRoot!.querySelector<ZnInput>('zn-input')!;
|
|
20
22
|
expect(input.value).to.equal('Chat to us');
|
|
21
23
|
});
|
|
24
|
+
|
|
25
|
+
describe('actions', () => {
|
|
26
|
+
async function actionsFixture() {
|
|
27
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
28
|
+
<zn-translation-group label="Content" .languages=${{en: 'English', fr: 'French'}}>
|
|
29
|
+
<zn-translations name="heading"></zn-translations>
|
|
30
|
+
<zn-button slot="actions" align="start" id="left">Auto translate</zn-button>
|
|
31
|
+
<zn-button slot="actions" id="cancel">Cancel</zn-button>
|
|
32
|
+
<zn-button slot="actions" id="save">Save</zn-button>
|
|
33
|
+
</zn-translation-group>`);
|
|
34
|
+
group.style.setProperty('--zn-spacing-small', '16px');
|
|
35
|
+
await group.updateComplete;
|
|
36
|
+
return group;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
it('is not rendered when nothing is slotted into it', async () => {
|
|
40
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
41
|
+
<zn-translation-group label="Content" .languages=${{en: 'English', fr: 'French'}}>
|
|
42
|
+
<zn-translations name="heading"></zn-translations>
|
|
43
|
+
</zn-translation-group>`);
|
|
44
|
+
await group.updateComplete;
|
|
45
|
+
|
|
46
|
+
expect(group.shadowRoot!.querySelector('.translation-group__actions')).to.be.null;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('sits at the bottom of the body, not in the footer', async () => {
|
|
50
|
+
const group = await actionsFixture();
|
|
51
|
+
|
|
52
|
+
const actions = group.shadowRoot!.querySelector<HTMLElement>('.translation-group__actions')!;
|
|
53
|
+
expect(actions.closest('.panel__body'), 'on the white body').to.exist;
|
|
54
|
+
expect(actions.closest('.panel__footer')).to.be.null;
|
|
55
|
+
|
|
56
|
+
const body = [...group.shadowRoot!.querySelectorAll('.panel__body > *')];
|
|
57
|
+
expect(body.indexOf(actions), 'last thing in the body').to.equal(body.length - 1);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('holds align="start" children left and the rest right, in one group each', async () => {
|
|
61
|
+
const group = await actionsFixture();
|
|
62
|
+
|
|
63
|
+
const left = group.querySelector<HTMLElement>('#left')!.getBoundingClientRect();
|
|
64
|
+
const cancel = group.querySelector<HTMLElement>('#cancel')!.getBoundingClientRect();
|
|
65
|
+
const save = group.querySelector<HTMLElement>('#save')!.getBoundingClientRect();
|
|
66
|
+
const row = group.shadowRoot!.querySelector<HTMLElement>('.translation-group__actions')!
|
|
67
|
+
.getBoundingClientRect();
|
|
68
|
+
|
|
69
|
+
expect(left.left).to.be.closeTo(row.left, 1);
|
|
70
|
+
expect(save.right).to.be.closeTo(row.right, 1);
|
|
71
|
+
// The right-hand pair stays together rather than spreading across the free space.
|
|
72
|
+
expect(cancel.right).to.be.closeTo(save.left - 16, 1);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('takes no border from the panel between the fields and the buttons', async () => {
|
|
76
|
+
const group = await actionsFixture();
|
|
77
|
+
|
|
78
|
+
const actions = group.shadowRoot!.querySelector<HTMLElement>('.translation-group__actions')!;
|
|
79
|
+
expect(getComputedStyle(actions).borderTopWidth).to.equal('0px');
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('inline', () => {
|
|
84
|
+
it('keeps the panel chrome by default', async () => {
|
|
85
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
86
|
+
<zn-translation-group label="Content" .languages=${{en: 'English', fr: 'French'}}>
|
|
87
|
+
<zn-translations name="heading"></zn-translations>
|
|
88
|
+
</zn-translation-group>`);
|
|
89
|
+
await group.updateComplete;
|
|
90
|
+
|
|
91
|
+
const panel = group.shadowRoot!.querySelector('.panel')!;
|
|
92
|
+
expect(panel.classList.contains('panel--transparent')).to.be.false;
|
|
93
|
+
expect(panel.classList.contains('panel--flush')).to.be.false;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('drops the border, background and padding so the fields align with the form', async () => {
|
|
97
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
98
|
+
<zn-translation-group inline label="Content" .languages=${{en: 'English', fr: 'French'}}>
|
|
99
|
+
<zn-translations name="heading"></zn-translations>
|
|
100
|
+
</zn-translation-group>`);
|
|
101
|
+
await group.updateComplete;
|
|
102
|
+
|
|
103
|
+
const panel = group.shadowRoot!.querySelector<HTMLElement>('.panel')!;
|
|
104
|
+
expect(panel.classList.contains('panel--transparent')).to.be.true;
|
|
105
|
+
expect(panel.classList.contains('panel--flush')).to.be.true;
|
|
106
|
+
|
|
107
|
+
const styles = getComputedStyle(panel);
|
|
108
|
+
expect(styles.borderTopWidth).to.equal('0px');
|
|
109
|
+
expect(styles.backgroundColor).to.equal('rgba(0, 0, 0, 0)');
|
|
110
|
+
|
|
111
|
+
const body = group.shadowRoot!.querySelector<HTMLElement>('.panel__body')!;
|
|
112
|
+
expect(getComputedStyle(body).paddingLeft).to.equal('0px');
|
|
113
|
+
expect(getComputedStyle(group.shadowRoot!.querySelector<HTMLElement>('.panel__header')!).paddingLeft)
|
|
114
|
+
.to.equal('0px');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('leaves the same gap under the caption as between the fields', async () => {
|
|
118
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
119
|
+
<zn-translation-group inline label="Content" .languages=${{en: 'English', fr: 'French'}}>
|
|
120
|
+
<zn-translations name="heading"></zn-translations>
|
|
121
|
+
</zn-translation-group>`);
|
|
122
|
+
// The spacing tokens live in the theme stylesheet, which the bundle under test does not carry.
|
|
123
|
+
group.style.setProperty('--zn-spacing-medium', '24px');
|
|
124
|
+
await group.updateComplete;
|
|
125
|
+
|
|
126
|
+
const header = group.shadowRoot!.querySelector<HTMLElement>('.panel__header')!;
|
|
127
|
+
const body = group.shadowRoot!.querySelector<HTMLElement>('.panel__body')!;
|
|
128
|
+
// zn-form-group's row gap between stacked controls. The header heads the same stack, so its gap matches.
|
|
129
|
+
expect(getComputedStyle(body).rowGap).to.equal('24px');
|
|
130
|
+
expect(getComputedStyle(header).paddingBottom).to.equal('24px');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
it("does not clip the language select's focus ring once the padding is gone", async () => {
|
|
135
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
136
|
+
<zn-translation-group inline .languages=${{en: 'English', fr: 'French'}}>
|
|
137
|
+
<zn-translations name="heading"></zn-translations>
|
|
138
|
+
</zn-translation-group>`);
|
|
139
|
+
await group.updateComplete;
|
|
140
|
+
|
|
141
|
+
['.panel__inner', '.panel__content', '.panel__body'].forEach(selector => {
|
|
142
|
+
const el = group.shadowRoot!.querySelector<HTMLElement>(selector)!;
|
|
143
|
+
expect(getComputedStyle(el).overflow, selector).to.equal('visible');
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('language select', () => {
|
|
149
|
+
function selectOf(group: ZnTranslationGroup) {
|
|
150
|
+
return group.shadowRoot!.querySelector<ZnSelect>('zn-select')!;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
it('sits in the header, opposite the caption', async () => {
|
|
154
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
155
|
+
<zn-translation-group label="Content" .languages=${{en: 'English', fr: 'French'}}>
|
|
156
|
+
<zn-translations name="heading"></zn-translations>
|
|
157
|
+
</zn-translation-group>`);
|
|
158
|
+
await group.updateComplete;
|
|
159
|
+
|
|
160
|
+
const field = group.shadowRoot!.querySelector<HTMLElement>('.translation-group__language-field')!;
|
|
161
|
+
expect(field.getAttribute('slot')).to.equal('actions');
|
|
162
|
+
expect(field.closest('zn-header')).to.exist;
|
|
163
|
+
expect(group.shadowRoot!.querySelector('.panel__body zn-select')).to.be.null;
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('leaves the caption to the label alone, with the count on the chip', async () => {
|
|
167
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
168
|
+
<zn-translation-group label="Content" .languages=${{en: 'English', fr: 'French'}}>
|
|
169
|
+
<zn-translations name="heading" value='{"en":"Hi","fr":"Salut"}'></zn-translations>
|
|
170
|
+
</zn-translation-group>`);
|
|
171
|
+
await group.updateComplete;
|
|
172
|
+
|
|
173
|
+
const header = group.shadowRoot!.querySelector('.panel__header')!;
|
|
174
|
+
expect(header.getAttribute('caption')).to.equal('Content');
|
|
175
|
+
expect(header.querySelector('[slot="caption"]'), 'nothing else rides the caption').to.be.null;
|
|
176
|
+
expect(group.shadowRoot!.querySelector('.translation-group__language-label')).to.be.null;
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('drops the fill and shadow but keeps the border, hover and focus', async () => {
|
|
180
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
181
|
+
<zn-translation-group label="Content" .languages=${{en: 'English', fr: 'French'}}>
|
|
182
|
+
<zn-translations name="heading"></zn-translations>
|
|
183
|
+
</zn-translation-group>`);
|
|
184
|
+
// The input tokens live in the theme stylesheet, which the bundle under test does not carry.
|
|
185
|
+
group.style.setProperty('--zn-input-border-width', '1px');
|
|
186
|
+
group.style.setProperty('--zn-input-border-color', 'rgb(9, 9, 9)');
|
|
187
|
+
group.style.setProperty('--zn-focus-ring-width', '3px');
|
|
188
|
+
group.style.setProperty('--zn-input-focus-ring-color', 'rgb(4, 5, 6)');
|
|
189
|
+
await group.updateComplete;
|
|
190
|
+
|
|
191
|
+
const select = selectOf(group);
|
|
192
|
+
await select.updateComplete;
|
|
193
|
+
const combobox = select.shadowRoot!.querySelector<HTMLElement>('[part~="combobox"]')!;
|
|
194
|
+
|
|
195
|
+
const styles = getComputedStyle(combobox);
|
|
196
|
+
expect(styles.backgroundColor).to.equal('rgba(0, 0, 0, 0)');
|
|
197
|
+
expect(styles.boxShadow).to.equal('none');
|
|
198
|
+
expect(styles.borderTopWidth, 'the border stays').to.equal('1px');
|
|
199
|
+
expect(styles.borderTopColor, 'the border stays').to.equal('rgb(9, 9, 9)');
|
|
200
|
+
|
|
201
|
+
select.focus();
|
|
202
|
+
await select.updateComplete;
|
|
203
|
+
expect(getComputedStyle(combobox).boxShadow, 'focus stays visible').to.not.equal('none');
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('sizes the trigger to its language and holds the listbox open wider', async () => {
|
|
207
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
208
|
+
<zn-translation-group label="Content" .languages=${{en: 'English', fr: 'French'}}>
|
|
209
|
+
<zn-translations name="heading"></zn-translations>
|
|
210
|
+
</zn-translation-group>`);
|
|
211
|
+
await group.updateComplete;
|
|
212
|
+
|
|
213
|
+
const select = selectOf(group);
|
|
214
|
+
await select.updateComplete;
|
|
215
|
+
|
|
216
|
+
// The whole point: the trigger is no longer pinned to the width the options need.
|
|
217
|
+
expect(select.getBoundingClientRect().width).to.be.lessThan(320);
|
|
218
|
+
|
|
219
|
+
const listbox = select.shadowRoot!.querySelector<HTMLElement>('[part~="listbox"]')!;
|
|
220
|
+
expect(getComputedStyle(listbox).minWidth).to.equal('320px');
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('names the select for a screen reader without showing the label', async () => {
|
|
224
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
225
|
+
<zn-translation-group label="Content" .languages=${{en: 'English', fr: 'French'}}>
|
|
226
|
+
<zn-translations name="heading"></zn-translations>
|
|
227
|
+
</zn-translation-group>`);
|
|
228
|
+
await group.updateComplete;
|
|
229
|
+
|
|
230
|
+
const select = selectOf(group);
|
|
231
|
+
expect(select.label).to.equal('Edit Languages');
|
|
232
|
+
await select.updateComplete;
|
|
233
|
+
const label = select.shadowRoot!.querySelector<HTMLElement>('[part~="form-control-label"]')!;
|
|
234
|
+
expect(label.getBoundingClientRect().width).to.be.lessThan(2);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('renders a header for the select even with no caption', async () => {
|
|
238
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
239
|
+
<zn-translation-group .languages=${{en: 'English', fr: 'French'}}>
|
|
240
|
+
<zn-translations name="heading"></zn-translations>
|
|
241
|
+
</zn-translation-group>`);
|
|
242
|
+
await group.updateComplete;
|
|
243
|
+
|
|
244
|
+
expect(group.shadowRoot!.querySelector('.panel__header')).to.exist;
|
|
245
|
+
expect(selectOf(group)).to.exist;
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('keeps the header to itself, with slotted actions going to the bottom', async () => {
|
|
249
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
250
|
+
<zn-translation-group label="Content" .languages=${{en: 'English', fr: 'French'}}>
|
|
251
|
+
<zn-button slot="actions">Auto translate</zn-button>
|
|
252
|
+
<zn-translations name="heading"></zn-translations>
|
|
253
|
+
</zn-translation-group>`);
|
|
254
|
+
await group.updateComplete;
|
|
255
|
+
|
|
256
|
+
const actionsSlot = group.shadowRoot!.querySelector('slot[name="actions"]')!;
|
|
257
|
+
expect(actionsSlot.closest('zn-header'), 'the header takes no actions').to.be.null;
|
|
258
|
+
expect(actionsSlot.closest('.panel__body'), 'they go to the body').to.exist;
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
function chipsOf(group: ZnTranslationGroup) {
|
|
262
|
+
return [...selectOf(group).querySelectorAll('zn-option zn-chip')]
|
|
263
|
+
.map(chip => chip.textContent?.trim());
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async function groupFixture(languages: Record<string, string>, values: string[]) {
|
|
267
|
+
const group = await fixture<ZnTranslationGroup>(html`
|
|
268
|
+
<zn-translation-group .languages=${languages}>
|
|
269
|
+
${values.map(value => html`<zn-translations name="f" value=${value}></zn-translations>`)}
|
|
270
|
+
</zn-translation-group>`);
|
|
271
|
+
await Promise.all([...group.querySelectorAll<ZnTranslations>('zn-translations')]
|
|
272
|
+
.map(child => child.updateComplete));
|
|
273
|
+
group.requestUpdate();
|
|
274
|
+
await group.updateComplete;
|
|
275
|
+
return group;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
it('marks a language translated only when every child has a value for it', async () => {
|
|
279
|
+
const group = await groupFixture(
|
|
280
|
+
{en: 'English', fr: 'French', de: 'German'},
|
|
281
|
+
['{"en":"Hello","fr":"Bonjour","de":"Hallo"}', '{"en":"Hi","fr":"Salut"}']);
|
|
282
|
+
|
|
283
|
+
expect(chipsOf(group)).to.deep.equal(['Translated', 'Translated', 'Partial']);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('summarises progress on the closed select, leaving the options their own states', async () => {
|
|
287
|
+
const group = await groupFixture(
|
|
288
|
+
{en: 'English', fr: 'French', de: 'German', es: 'Spanish'},
|
|
289
|
+
['{"en":"Hello","fr":"Bonjour","de":"Hallo"}', '{"en":"Hi","fr":"Salut"}']);
|
|
290
|
+
|
|
291
|
+
const summary = selectOf(group).querySelector('zn-chip[slot="suffix"]')!;
|
|
292
|
+
expect(summary.textContent?.trim()).to.equal('1/3');
|
|
293
|
+
expect(summary.getAttribute('type')).to.equal('warning');
|
|
294
|
+
|
|
295
|
+
expect(chipsOf(group)).to.deep.equal(['Translated', 'Translated', 'Partial', 'English']);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('marks the summary chip done once every target language is translated', async () => {
|
|
299
|
+
const group = await groupFixture(
|
|
300
|
+
{en: 'English', fr: 'French'},
|
|
301
|
+
['{"en":"Hello","fr":"Bonjour"}']);
|
|
302
|
+
|
|
303
|
+
const summary = selectOf(group).querySelector('zn-chip[slot="suffix"]')!;
|
|
304
|
+
expect(summary.textContent?.trim()).to.equal('1/1');
|
|
305
|
+
expect(summary.getAttribute('type')).to.equal('success');
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('falls back to English where no child has a value', async () => {
|
|
309
|
+
const group = await groupFixture(
|
|
310
|
+
{en: 'English', fr: 'French'},
|
|
311
|
+
['{"en":"Hello"}', '{"en":"Hi"}']);
|
|
312
|
+
|
|
313
|
+
expect(chipsOf(group)).to.deep.equal(['Translated', 'English']);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('counts the target languages, not English', async () => {
|
|
317
|
+
const group = await groupFixture(
|
|
318
|
+
{en: 'English', fr: 'French', de: 'German'},
|
|
319
|
+
['{"en":"Hello","fr":"Bonjour"}']);
|
|
320
|
+
|
|
321
|
+
const summary = selectOf(group).querySelector('zn-chip[slot="suffix"]')!;
|
|
322
|
+
expect(summary.textContent?.trim()).to.equal('1/2');
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
it('switches every child when the select changes', async () => {
|
|
326
|
+
const group = await groupFixture(
|
|
327
|
+
{en: 'English', fr: 'French'},
|
|
328
|
+
['{"en":"Hello","fr":"Bonjour"}', '{"en":"Hi","fr":"Salut"}']);
|
|
329
|
+
|
|
330
|
+
const select = selectOf(group);
|
|
331
|
+
select.value = 'fr';
|
|
332
|
+
select.dispatchEvent(new CustomEvent('zn-change', {bubbles: true, composed: true}));
|
|
333
|
+
await group.updateComplete;
|
|
334
|
+
|
|
335
|
+
const children = [...group.querySelectorAll<ZnTranslations>('zn-translations')];
|
|
336
|
+
await Promise.all(children.map(child => child.updateComplete));
|
|
337
|
+
expect(children.map(child => child.getActiveLanguage())).to.deep.equal(['fr', 'fr']);
|
|
338
|
+
expect(children.map(child => child.shadowRoot!.querySelector<ZnInput>('zn-input')!.value as string))
|
|
339
|
+
.to.deep.equal(['Bonjour', 'Salut']);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it('emits zn-language-change without reporting a value change', async () => {
|
|
343
|
+
const group = await groupFixture({en: 'English', fr: 'French'}, ['{"en":"Hello"}']);
|
|
344
|
+
|
|
345
|
+
let language = '';
|
|
346
|
+
let changes = 0;
|
|
347
|
+
group.addEventListener('zn-language-change', (e: Event) => {
|
|
348
|
+
language = (e as CustomEvent<{language: string}>).detail.language;
|
|
349
|
+
});
|
|
350
|
+
group.addEventListener('zn-change', () => changes++);
|
|
351
|
+
|
|
352
|
+
const select = selectOf(group);
|
|
353
|
+
select.value = 'fr';
|
|
354
|
+
select.dispatchEvent(new CustomEvent('zn-change', {bubbles: true, composed: true}));
|
|
355
|
+
await group.updateComplete;
|
|
356
|
+
|
|
357
|
+
expect(language).to.equal('fr');
|
|
358
|
+
expect(changes).to.equal(0);
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
describe('form reset', () => {
|
|
363
|
+
it('re-reads the children once the form has restored them', async () => {
|
|
364
|
+
const form = await fixture<HTMLFormElement>(html`
|
|
365
|
+
<form>
|
|
366
|
+
<zn-translation-group .languages=${{en: 'English', fr: 'French'}}>
|
|
367
|
+
<zn-translations name="a" value='{"en":"Hello","fr":"Bonjour"}'></zn-translations>
|
|
368
|
+
</zn-translation-group>
|
|
369
|
+
</form>`);
|
|
370
|
+
const group = form.querySelector<ZnTranslationGroup>('zn-translation-group')!;
|
|
371
|
+
const child = group.querySelector<ZnTranslations>('zn-translations')!;
|
|
372
|
+
await child.updateComplete;
|
|
373
|
+
group.requestUpdate();
|
|
374
|
+
await group.updateComplete;
|
|
375
|
+
|
|
376
|
+
child.values = {en: 'Hello', fr: ''};
|
|
377
|
+
child.dispatchEvent(new CustomEvent('zn-change', {bubbles: true, composed: true}));
|
|
378
|
+
await group.updateComplete;
|
|
379
|
+
|
|
380
|
+
const summary = () => group.shadowRoot!.querySelector('zn-select zn-chip[slot="suffix"]')!.textContent?.trim();
|
|
381
|
+
expect(summary()).to.equal('0/1');
|
|
382
|
+
|
|
383
|
+
form.reset();
|
|
384
|
+
await new Promise(resolve => requestAnimationFrame(() => resolve(null)));
|
|
385
|
+
await group.updateComplete;
|
|
386
|
+
|
|
387
|
+
expect(child.values).to.deep.equal({en: 'Hello', fr: 'Bonjour'});
|
|
388
|
+
expect(summary()).to.equal('1/1');
|
|
389
|
+
});
|
|
390
|
+
});
|
|
22
391
|
});
|