@descope-ui/descope-multi-select-combo-box 3.11.8 → 3.12.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.
- package/package.json +10 -6
- package/CHANGELOG.md +0 -38
- package/e2e/descope-multi-select-combo-box.spec.ts +0 -666
- package/project.json +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@descope-ui/descope-multi-select-combo-box",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.12.0",
|
|
4
|
+
"files": [
|
|
5
|
+
"src",
|
|
6
|
+
"stories"
|
|
7
|
+
],
|
|
4
8
|
"exports": {
|
|
5
9
|
".": {
|
|
6
10
|
"import": "./src/component/index.js"
|
|
@@ -14,14 +18,14 @@
|
|
|
14
18
|
},
|
|
15
19
|
"devDependencies": {
|
|
16
20
|
"@playwright/test": "1.58.2",
|
|
17
|
-
"test-drivers": "3.
|
|
18
|
-
"e2e-utils": "3.
|
|
21
|
+
"test-drivers": "3.12.0",
|
|
22
|
+
"e2e-utils": "3.12.0"
|
|
19
23
|
},
|
|
20
24
|
"dependencies": {
|
|
21
25
|
"@vaadin/multi-select-combo-box": "24.3.4",
|
|
22
|
-
"@descope-ui/
|
|
23
|
-
"@descope-ui/
|
|
24
|
-
"@descope-ui/theme-input-wrapper": "3.
|
|
26
|
+
"@descope-ui/common": "3.12.0",
|
|
27
|
+
"@descope-ui/theme-globals": "3.12.0",
|
|
28
|
+
"@descope-ui/theme-input-wrapper": "3.12.0"
|
|
25
29
|
},
|
|
26
30
|
"publishConfig": {
|
|
27
31
|
"link-workspace-packages": false
|
package/CHANGELOG.md
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
|
-
|
|
5
|
-
## [3.11.8](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.7...web-components-ui-3.11.8) (2026-05-25)
|
|
6
|
-
|
|
7
|
-
## [3.11.7](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.6...web-components-ui-3.11.7) (2026-05-25)
|
|
8
|
-
|
|
9
|
-
## [3.11.6](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.5...web-components-ui-3.11.6) (2026-05-24)
|
|
10
|
-
|
|
11
|
-
## [3.11.5](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.4...web-components-ui-3.11.5) (2026-05-21)
|
|
12
|
-
|
|
13
|
-
## [3.11.4](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.3...web-components-ui-3.11.4) (2026-05-20)
|
|
14
|
-
|
|
15
|
-
## [3.11.3](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.2...web-components-ui-3.11.3) (2026-05-19)
|
|
16
|
-
|
|
17
|
-
## [3.11.2](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.1...web-components-ui-3.11.2) (2026-05-19)
|
|
18
|
-
|
|
19
|
-
## [3.11.1](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.0...web-components-ui-3.11.1) (2026-05-19)
|
|
20
|
-
|
|
21
|
-
## [3.11.0](https://github.com/descope/web-components-ui/compare/web-components-ui-3.10.2...web-components-ui-3.11.0) (2026-05-19)
|
|
22
|
-
|
|
23
|
-
## [3.10.2](https://github.com/descope/web-components-ui/compare/web-components-ui-3.10.1...web-components-ui-3.10.2) (2026-05-19)
|
|
24
|
-
|
|
25
|
-
## [3.10.1](https://github.com/descope/web-components-ui/compare/web-components-ui-3.10.0...web-components-ui-3.10.1) (2026-05-18)
|
|
26
|
-
|
|
27
|
-
## [3.10.0](https://github.com/descope/web-components-ui/compare/web-components-ui-3.9.2...web-components-ui-3.10.0) (2026-05-17)
|
|
28
|
-
|
|
29
|
-
## [3.9.2](https://github.com/descope/web-components-ui/compare/web-components-ui-3.9.1...web-components-ui-3.9.2) (2026-05-17)
|
|
30
|
-
|
|
31
|
-
## [3.9.1](https://github.com/descope/web-components-ui/compare/web-components-ui-3.9.0...web-components-ui-3.9.1) (2026-05-17)
|
|
32
|
-
|
|
33
|
-
## [3.9.0](https://github.com/descope/web-components-ui/compare/web-components-ui-3.8.0...web-components-ui-3.9.0) (2026-05-17)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
### Features
|
|
37
|
-
|
|
38
|
-
* added multi line mappings component ([#978](https://github.com/descope/web-components-ui/issues/978)) ([544552f](https://github.com/descope/web-components-ui/commit/544552f474430f7a9317e268979fb94694f6249a))
|
|
@@ -1,666 +0,0 @@
|
|
|
1
|
-
import { expect, test } from '@playwright/test';
|
|
2
|
-
import { createComboBoxTestDriver } from 'test-drivers';
|
|
3
|
-
import { getStoryUrl, loopConfig, loopPresets } from 'e2e-utils';
|
|
4
|
-
|
|
5
|
-
const storyName = 'descope-multi-select-combo-box';
|
|
6
|
-
const componentName = 'descope-multi-select-combo-box';
|
|
7
|
-
|
|
8
|
-
const BooleanValues = ['true', 'false'];
|
|
9
|
-
|
|
10
|
-
const componentAttributesMulti = {
|
|
11
|
-
label: 'Number field label',
|
|
12
|
-
placeholder: 'Test placeholder',
|
|
13
|
-
size: ['xs', 'sm', 'md', 'lg'],
|
|
14
|
-
bordered: BooleanValues,
|
|
15
|
-
readonly: BooleanValues,
|
|
16
|
-
required: BooleanValues,
|
|
17
|
-
'full-width': BooleanValues,
|
|
18
|
-
disabled: 'true',
|
|
19
|
-
'default-values[0]': 'itemId2',
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const presetsMulti = {
|
|
23
|
-
'Render with alt item renderer': {
|
|
24
|
-
itemsSource: 'prop',
|
|
25
|
-
overrideRenderItem: 'true',
|
|
26
|
-
},
|
|
27
|
-
'Render with data property': { itemsSource: 'prop' },
|
|
28
|
-
'Render with data attribute': { itemsSource: 'attr' },
|
|
29
|
-
'Render with data property and default value': {
|
|
30
|
-
itemsSource: 'prop',
|
|
31
|
-
'default-values[0]': 'itemId2',
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const rtlPresets = {
|
|
36
|
-
'direction rtl': {
|
|
37
|
-
direction: 'rtl',
|
|
38
|
-
label: '-Test Label',
|
|
39
|
-
placeholder: '-Test Placeholder',
|
|
40
|
-
itemsSource: 'attr',
|
|
41
|
-
'data[0].displayName': '-Item 1',
|
|
42
|
-
'data[1].displayName': '-Item 2',
|
|
43
|
-
'data[1].label': '-Data Item 2',
|
|
44
|
-
},
|
|
45
|
-
'direction rtl required': {
|
|
46
|
-
direction: 'rtl',
|
|
47
|
-
label: '-Test Label',
|
|
48
|
-
placeholder: '-Test Placeholder',
|
|
49
|
-
itemsSource: 'attr',
|
|
50
|
-
'data[0].displayName': '-Item 1',
|
|
51
|
-
'data[1].displayName': '-Item 2',
|
|
52
|
-
'data[1].label': '-Data Item 2',
|
|
53
|
-
required: 'true',
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const floatingLabelProps = {
|
|
58
|
-
'label-type': 'floating',
|
|
59
|
-
label: 'label-',
|
|
60
|
-
placeholder: 'placeholder',
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const floatingLabelTypePresets = {
|
|
64
|
-
'floating label ltr': floatingLabelProps,
|
|
65
|
-
'floating label rtl': {
|
|
66
|
-
...floatingLabelProps,
|
|
67
|
-
direction: 'rtl',
|
|
68
|
-
},
|
|
69
|
-
'floating label ltr with value': {
|
|
70
|
-
...floatingLabelProps,
|
|
71
|
-
'default-value': 'itemId2',
|
|
72
|
-
direction: 'ltr',
|
|
73
|
-
},
|
|
74
|
-
'floating label rtl with value': {
|
|
75
|
-
...floatingLabelProps,
|
|
76
|
-
'default-value': 'itemId2',
|
|
77
|
-
direction: 'rtl',
|
|
78
|
-
},
|
|
79
|
-
'floating label with long tail letters': {
|
|
80
|
-
...floatingLabelProps,
|
|
81
|
-
label: 'gyqjp',
|
|
82
|
-
},
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const { placeholder, ...restConfig } = componentAttributesMulti;
|
|
86
|
-
|
|
87
|
-
test.describe('theme', () => {
|
|
88
|
-
test.describe('with placeholder', () => {
|
|
89
|
-
test.beforeEach(async ({ page }) => {
|
|
90
|
-
await page.goto(getStoryUrl(storyName, { placeholder }), {
|
|
91
|
-
waitUntil: 'networkidle',
|
|
92
|
-
});
|
|
93
|
-
await page.waitForSelector(componentName);
|
|
94
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
95
|
-
await component.clear();
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
test('hover', async ({ page }) => {
|
|
99
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
100
|
-
await component.hover();
|
|
101
|
-
expect(await component.screenshot()).toMatchSnapshot();
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test('focus', async ({ page }) => {
|
|
105
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
106
|
-
await component.focus();
|
|
107
|
-
expect(await component.screenshot()).toMatchSnapshot();
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
loopPresets(presetsMulti, (preset, name) => {
|
|
112
|
-
test.describe(name, () => {
|
|
113
|
-
test.beforeEach(async ({ page }) => {
|
|
114
|
-
await page.goto(getStoryUrl(storyName, preset), {
|
|
115
|
-
waitUntil: 'networkidle',
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
test('hover', async ({ page }) => {
|
|
120
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
121
|
-
await component.hover();
|
|
122
|
-
expect(
|
|
123
|
-
await component.screenshot({ animations: 'disabled' }),
|
|
124
|
-
).toMatchSnapshot();
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test('focus', async ({ page }) => {
|
|
128
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
129
|
-
await component.focus();
|
|
130
|
-
expect(
|
|
131
|
-
await component.screenshot({ animations: 'disabled' }),
|
|
132
|
-
).toMatchSnapshot();
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
test.describe('with value', () => {
|
|
138
|
-
loopConfig(restConfig, (attr, value) => {
|
|
139
|
-
test.describe(`${attr}: ${value}`, () => {
|
|
140
|
-
test.beforeEach(async ({ page }) => {
|
|
141
|
-
await page.goto(getStoryUrl(storyName, { [attr]: value }), {
|
|
142
|
-
waitUntil: 'networkidle',
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
const component = createComboBoxTestDriver(
|
|
146
|
-
page.locator(componentName),
|
|
147
|
-
);
|
|
148
|
-
component.setValue('itemId4');
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test('hover', async ({ page }) => {
|
|
152
|
-
const component = createComboBoxTestDriver(
|
|
153
|
-
page.locator(componentName),
|
|
154
|
-
);
|
|
155
|
-
await component.hover();
|
|
156
|
-
expect(await component.screenshot()).toMatchSnapshot();
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
test('focus', async ({ page }) => {
|
|
160
|
-
const component = createComboBoxTestDriver(
|
|
161
|
-
page.locator(componentName),
|
|
162
|
-
);
|
|
163
|
-
await component.focus();
|
|
164
|
-
expect(await component.screenshot()).toMatchSnapshot();
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
test.describe('dropDown', () => {
|
|
171
|
-
loopConfig(
|
|
172
|
-
{
|
|
173
|
-
size: componentAttributesMulti.size,
|
|
174
|
-
'full-width': componentAttributesMulti['full-width'],
|
|
175
|
-
},
|
|
176
|
-
(attr, value) => {
|
|
177
|
-
test.describe(`${attr}: ${value}`, () => {
|
|
178
|
-
test.beforeEach(async ({ page }) => {
|
|
179
|
-
await page.goto(getStoryUrl(storyName, { [attr]: value }), {
|
|
180
|
-
waitUntil: 'networkidle',
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
const component = createComboBoxTestDriver(
|
|
184
|
-
page.locator(componentName),
|
|
185
|
-
);
|
|
186
|
-
await component.openDropdown();
|
|
187
|
-
});
|
|
188
|
-
test('visible', async ({ page }) => {
|
|
189
|
-
const component = createComboBoxTestDriver(
|
|
190
|
-
page.locator(componentName),
|
|
191
|
-
);
|
|
192
|
-
await component.hover();
|
|
193
|
-
expect(await component.dropDown.screenshot()).toMatchSnapshot();
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
},
|
|
197
|
-
);
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
test.describe('direction rtl', () => {
|
|
201
|
-
loopPresets(rtlPresets, (preset, name) => {
|
|
202
|
-
test(name, async ({ page }) => {
|
|
203
|
-
await page.goto(getStoryUrl(storyName, preset));
|
|
204
|
-
await page.waitForSelector(componentName);
|
|
205
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
206
|
-
|
|
207
|
-
expect(
|
|
208
|
-
await component.screenshot({
|
|
209
|
-
animations: 'disabled',
|
|
210
|
-
timeout: 3000,
|
|
211
|
-
caret: 'hide',
|
|
212
|
-
}),
|
|
213
|
-
).toMatchSnapshot();
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
test('with error', async ({ page }) => {
|
|
217
|
-
await page.goto(getStoryUrl(storyName, Object.values(rtlPresets)[1]), {
|
|
218
|
-
waitUntil: 'networkidle',
|
|
219
|
-
});
|
|
220
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
221
|
-
await page.getByRole('button').getByText('Submit').click();
|
|
222
|
-
expect(await component.screenshot({ delay: 3000 })).toMatchSnapshot();
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
test('with open dropdown', async ({ page }) => {
|
|
226
|
-
await page.goto(getStoryUrl(storyName, Object.values(rtlPresets)[1]), {
|
|
227
|
-
waitUntil: 'networkidle',
|
|
228
|
-
});
|
|
229
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
230
|
-
await component.openDropdown();
|
|
231
|
-
await component.hover();
|
|
232
|
-
expect(await component.dropDown.screenshot()).toMatchSnapshot();
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
test('with open dropdown and value', async ({ page }) => {
|
|
236
|
-
await page.goto(getStoryUrl(storyName, Object.values(rtlPresets)[1]), {
|
|
237
|
-
waitUntil: 'networkidle',
|
|
238
|
-
});
|
|
239
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
240
|
-
await component.setValue('itemId2');
|
|
241
|
-
await component.openDropdown();
|
|
242
|
-
await component.hover();
|
|
243
|
-
expect(await component.dropDown.screenshot()).toMatchSnapshot();
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
test('with value', async ({ page }) => {
|
|
247
|
-
await page.goto(getStoryUrl(storyName, Object.values(rtlPresets)[1]), {
|
|
248
|
-
waitUntil: 'networkidle',
|
|
249
|
-
});
|
|
250
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
251
|
-
await component.setValue('itemId2');
|
|
252
|
-
expect(await component.screenshot()).toMatchSnapshot();
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
// The purpose of having snapshots with different values is to make sure that the overflow chip
|
|
258
|
-
// is displayed correctly in different scenarios (it stays the same after having 3 collapsed options).
|
|
259
|
-
const presets = {
|
|
260
|
-
'Render with 2 default values': {
|
|
261
|
-
'default-values[0]': 'itemId1',
|
|
262
|
-
'default-values[1]': 'itemId2',
|
|
263
|
-
},
|
|
264
|
-
'Render with 3 default values': {
|
|
265
|
-
'default-values[0]': 'itemId1',
|
|
266
|
-
'default-values[1]': 'itemId2',
|
|
267
|
-
'default-values[2]': 'itemId3',
|
|
268
|
-
},
|
|
269
|
-
'Render with many default values': {
|
|
270
|
-
'default-values[0]': 'itemId1',
|
|
271
|
-
'default-values[1]': 'itemId2',
|
|
272
|
-
'default-values[2]': 'itemId3',
|
|
273
|
-
'default-values[3]': 'itemId4',
|
|
274
|
-
},
|
|
275
|
-
'Render with many values and full width': {
|
|
276
|
-
'default-values[0]': 'itemId1',
|
|
277
|
-
'default-values[1]': 'itemId2',
|
|
278
|
-
'default-values[2]': 'itemId3',
|
|
279
|
-
'default-values[3]': 'itemId4',
|
|
280
|
-
'full-width': 'true',
|
|
281
|
-
},
|
|
282
|
-
'Placeholder and readonly': {
|
|
283
|
-
placeholder: '-Select items',
|
|
284
|
-
readonly: 'true',
|
|
285
|
-
},
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
['ltr', 'rtl'].forEach((dir) => {
|
|
289
|
-
test.describe(`direction ${dir}`, () => {
|
|
290
|
-
const presetsWithDirection = Object.entries(presets).reduce(
|
|
291
|
-
(acc, [presetName, presetValues]) => {
|
|
292
|
-
const presetWithDirection = { ...presetValues, direction: dir };
|
|
293
|
-
return { ...acc, [presetName]: presetWithDirection };
|
|
294
|
-
},
|
|
295
|
-
{},
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
loopPresets(presetsWithDirection, (preset, name) => {
|
|
299
|
-
test(name, async ({ page }) => {
|
|
300
|
-
await page.goto(getStoryUrl(storyName, preset));
|
|
301
|
-
await page.waitForSelector(componentName);
|
|
302
|
-
|
|
303
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
304
|
-
expect(
|
|
305
|
-
await component.screenshot({
|
|
306
|
-
animations: 'disabled',
|
|
307
|
-
timeout: 3000,
|
|
308
|
-
caret: 'hide',
|
|
309
|
-
}),
|
|
310
|
-
).toMatchSnapshot();
|
|
311
|
-
});
|
|
312
|
-
});
|
|
313
|
-
});
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
test.describe('logic', () => {
|
|
317
|
-
test('select multiple items', async ({ page }) => {
|
|
318
|
-
await page.goto(getStoryUrl(storyName, { 'full-width': true }), {
|
|
319
|
-
waitUntil: 'networkidle',
|
|
320
|
-
});
|
|
321
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
322
|
-
await component.openDropdown();
|
|
323
|
-
await component.selectItem("Achilles' Fateful Wrath");
|
|
324
|
-
await component.selectItem('Trojan Horse Deception');
|
|
325
|
-
|
|
326
|
-
expect(await component.getValue()).toStrictEqual(['itemId2', 'itemId5']);
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
test.describe('selection limit', () => {
|
|
330
|
-
test('required and minimum not met', async ({ page }) => {
|
|
331
|
-
await page.goto(
|
|
332
|
-
getStoryUrl(storyName, { required: true, minItemsSelection: 2 }),
|
|
333
|
-
{
|
|
334
|
-
waitUntil: 'networkidle',
|
|
335
|
-
},
|
|
336
|
-
);
|
|
337
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
338
|
-
await component.openDropdown();
|
|
339
|
-
await component.selectItem("Achilles' Fateful Wrath");
|
|
340
|
-
await component.closeDropdown();
|
|
341
|
-
await page.getByRole('button').getByText('Submit').click();
|
|
342
|
-
await component.blur();
|
|
343
|
-
await expect(
|
|
344
|
-
page.getByText('At least 2 items are required'),
|
|
345
|
-
).toBeVisible();
|
|
346
|
-
expect(
|
|
347
|
-
await component.screenshot({ timeout: 2000, animations: 'disabled' }),
|
|
348
|
-
).toMatchSnapshot();
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
test('required and minimum met', async ({ page }) => {
|
|
352
|
-
await page.goto(
|
|
353
|
-
getStoryUrl(storyName, { required: true, minItemsSelection: 2 }),
|
|
354
|
-
{
|
|
355
|
-
waitUntil: 'networkidle',
|
|
356
|
-
},
|
|
357
|
-
);
|
|
358
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
359
|
-
await component.openDropdown();
|
|
360
|
-
await component.selectItem("Achilles' Fateful Wrath");
|
|
361
|
-
await component.selectItem('Trojan Horse Deception');
|
|
362
|
-
await component.closeDropdown();
|
|
363
|
-
await page.getByRole('button').getByText('Submit').click();
|
|
364
|
-
await expect(
|
|
365
|
-
page.getByText('At least 2 items are required'),
|
|
366
|
-
).not.toBeVisible();
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
test('not required and minimum not enforced', async ({ page }) => {
|
|
370
|
-
await page.goto(getStoryUrl(storyName, { minItemsSelection: 2 }), {
|
|
371
|
-
waitUntil: 'networkidle',
|
|
372
|
-
});
|
|
373
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
374
|
-
await component.openDropdown();
|
|
375
|
-
await component.selectItem("Achilles' Fateful Wrath");
|
|
376
|
-
await component.closeDropdown();
|
|
377
|
-
await page.getByRole('button').getByText('Submit').click();
|
|
378
|
-
await expect(
|
|
379
|
-
page.getByText('At least 2 items are required'),
|
|
380
|
-
).not.toBeVisible();
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
test('maximum not met', async ({ page }) => {
|
|
384
|
-
await page.goto(getStoryUrl(storyName, { maxItemsSelection: 2 }), {
|
|
385
|
-
waitUntil: 'networkidle',
|
|
386
|
-
});
|
|
387
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
388
|
-
await component.openDropdown();
|
|
389
|
-
await component.selectItem("Achilles' Fateful Wrath");
|
|
390
|
-
await component.selectItem('Trojan Horse Deception');
|
|
391
|
-
await component.selectItem("Agamemnon's Royal Command");
|
|
392
|
-
component.closeDropdown();
|
|
393
|
-
await page.getByRole('button').getByText('Submit').click();
|
|
394
|
-
await component.blur();
|
|
395
|
-
await expect(page.getByText('At most 2 items are allowed')).toBeVisible();
|
|
396
|
-
expect(
|
|
397
|
-
await component.screenshot({ timeout: 2000, animations: 'disabled' }),
|
|
398
|
-
).toMatchSnapshot();
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
test('maximum met', async ({ page }) => {
|
|
402
|
-
await page.goto(getStoryUrl(storyName, { maxItemsSelection: 2 }), {
|
|
403
|
-
waitUntil: 'networkidle',
|
|
404
|
-
});
|
|
405
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
406
|
-
await component.openDropdown();
|
|
407
|
-
await component.selectItem("Achilles' Fateful Wrath");
|
|
408
|
-
await component.selectItem('Trojan Horse Deception');
|
|
409
|
-
component.closeDropdown();
|
|
410
|
-
await page.getByRole('button').getByText('Submit').click();
|
|
411
|
-
await expect(
|
|
412
|
-
page.getByText('At most 2 items are allowed'),
|
|
413
|
-
).not.toBeVisible();
|
|
414
|
-
});
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
test.describe('clear button', () => {
|
|
418
|
-
test('clear button visible when has value', async ({ page }) => {
|
|
419
|
-
await page.goto(
|
|
420
|
-
getStoryUrl(storyName, { 'default-values[0]': 'itemId2' }),
|
|
421
|
-
{
|
|
422
|
-
waitUntil: 'networkidle',
|
|
423
|
-
},
|
|
424
|
-
);
|
|
425
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
426
|
-
await component.clearSelection();
|
|
427
|
-
expect(await component.getValue()).toStrictEqual([]);
|
|
428
|
-
});
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
test.describe('custom value entry', () => {
|
|
432
|
-
test('on', async ({ page }) => {
|
|
433
|
-
await page.goto(
|
|
434
|
-
getStoryUrl(storyName, {
|
|
435
|
-
'allow-custom-value': true,
|
|
436
|
-
'full-width': true,
|
|
437
|
-
}),
|
|
438
|
-
{
|
|
439
|
-
waitUntil: 'networkidle',
|
|
440
|
-
},
|
|
441
|
-
);
|
|
442
|
-
const componentLocator = page.locator(componentName);
|
|
443
|
-
const component = createComboBoxTestDriver(componentLocator);
|
|
444
|
-
expect(
|
|
445
|
-
componentLocator.page().getByText('Custom Test Value'),
|
|
446
|
-
).not.toBeVisible();
|
|
447
|
-
await component.insertValue('Custom Test Value');
|
|
448
|
-
await componentLocator.page().keyboard.press('Enter');
|
|
449
|
-
await page.waitForTimeout(1000);
|
|
450
|
-
expect(await component.getValue()).toStrictEqual(['Custom Test Value']);
|
|
451
|
-
await component.blur();
|
|
452
|
-
await page.getByRole('button').getByText('Submit').click();
|
|
453
|
-
expect(await component.screenshot()).toMatchSnapshot();
|
|
454
|
-
await component.openDropdown();
|
|
455
|
-
expect(await component.dropDown.screenshot()).toMatchSnapshot();
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
test('off', async ({ page }) => {
|
|
459
|
-
await page.goto(getStoryUrl(storyName, { 'full-width': true }), {
|
|
460
|
-
waitUntil: 'networkidle',
|
|
461
|
-
});
|
|
462
|
-
const componentLocator = page.locator(componentName);
|
|
463
|
-
const component = createComboBoxTestDriver(componentLocator);
|
|
464
|
-
expect(
|
|
465
|
-
componentLocator.page().getByText('Custom Test Value'),
|
|
466
|
-
).not.toBeVisible();
|
|
467
|
-
await component.insertValue('Custom Test Value');
|
|
468
|
-
await componentLocator.page().keyboard.press('Enter');
|
|
469
|
-
await page.waitForTimeout(1000);
|
|
470
|
-
expect(await component.getValue()).toStrictEqual([]);
|
|
471
|
-
expect(
|
|
472
|
-
await componentLocator.page().getByText('Custom Test Value').count(),
|
|
473
|
-
).toEqual(0);
|
|
474
|
-
});
|
|
475
|
-
|
|
476
|
-
test('no provided options', async ({ page }) => {
|
|
477
|
-
await page.goto(
|
|
478
|
-
getStoryUrl(storyName, {
|
|
479
|
-
'allow-custom-value': true,
|
|
480
|
-
'ignore-data': true,
|
|
481
|
-
itemsSource: 'attr',
|
|
482
|
-
'full-width': true,
|
|
483
|
-
}),
|
|
484
|
-
);
|
|
485
|
-
const componentLocator = page.locator(componentName);
|
|
486
|
-
const component = createComboBoxTestDriver(componentLocator);
|
|
487
|
-
expect(await component.screenshot()).toMatchSnapshot();
|
|
488
|
-
await component.insertValue('Custom Test Value');
|
|
489
|
-
await componentLocator.page().keyboard.press('Enter');
|
|
490
|
-
await page.waitForTimeout(1000);
|
|
491
|
-
expect(await component.getValue()).toStrictEqual(['Custom Test Value']);
|
|
492
|
-
await component.insertValue('Custom Test Value2');
|
|
493
|
-
await componentLocator.page().keyboard.press('Enter');
|
|
494
|
-
await page.waitForTimeout(1000);
|
|
495
|
-
expect(await component.getValue()).toStrictEqual([
|
|
496
|
-
'Custom Test Value',
|
|
497
|
-
'Custom Test Value2',
|
|
498
|
-
]);
|
|
499
|
-
await component.blur();
|
|
500
|
-
await page.getByRole('button').getByText('Submit').click();
|
|
501
|
-
expect(await component.screenshot()).toMatchSnapshot();
|
|
502
|
-
await component.openDropdown();
|
|
503
|
-
expect(await component.dropDown.screenshot()).toMatchSnapshot();
|
|
504
|
-
});
|
|
505
|
-
|
|
506
|
-
test('no options and below limit', async ({ page }) => {
|
|
507
|
-
await page.goto(
|
|
508
|
-
getStoryUrl(storyName, {
|
|
509
|
-
'allow-custom-value': true,
|
|
510
|
-
'ignore-data': true,
|
|
511
|
-
itemsSource: 'attr',
|
|
512
|
-
'full-width': true,
|
|
513
|
-
required: true,
|
|
514
|
-
minItemsSelection: 2,
|
|
515
|
-
}),
|
|
516
|
-
);
|
|
517
|
-
const componentLocator = page.locator(componentName);
|
|
518
|
-
const component = createComboBoxTestDriver(componentLocator);
|
|
519
|
-
await component.insertValue('Custom Test Value');
|
|
520
|
-
await componentLocator.page().keyboard.press('Enter');
|
|
521
|
-
await page.waitForTimeout(1000);
|
|
522
|
-
expect(await component.getValue()).toStrictEqual(['Custom Test Value']);
|
|
523
|
-
component.closeDropdown();
|
|
524
|
-
await page.getByRole('button').getByText('Submit').click();
|
|
525
|
-
await component.blur();
|
|
526
|
-
expect(await component.screenshot()).toMatchSnapshot();
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
test('set value without predefined options', async ({ page }) => {
|
|
530
|
-
await page.goto(
|
|
531
|
-
getStoryUrl(storyName, {
|
|
532
|
-
'allow-custom-value': true,
|
|
533
|
-
'ignore-data': true,
|
|
534
|
-
itemsSource: 'attr',
|
|
535
|
-
'full-width': true,
|
|
536
|
-
}),
|
|
537
|
-
);
|
|
538
|
-
const componentLocator = page.locator(componentName);
|
|
539
|
-
const component = createComboBoxTestDriver(componentLocator);
|
|
540
|
-
await page.waitForSelector(componentName);
|
|
541
|
-
|
|
542
|
-
componentLocator.page().$eval(
|
|
543
|
-
componentName,
|
|
544
|
-
(node: any, arg) => {
|
|
545
|
-
node.value = arg;
|
|
546
|
-
},
|
|
547
|
-
['value1', 'value2'],
|
|
548
|
-
);
|
|
549
|
-
await page.waitForTimeout(1000);
|
|
550
|
-
expect(await component.screenshot()).toMatchSnapshot();
|
|
551
|
-
});
|
|
552
|
-
|
|
553
|
-
test('set repeated value without predefined options', async ({ page }) => {
|
|
554
|
-
await page.goto(
|
|
555
|
-
getStoryUrl(storyName, {
|
|
556
|
-
'allow-custom-value': true,
|
|
557
|
-
'ignore-data': true,
|
|
558
|
-
itemsSource: 'attr',
|
|
559
|
-
'full-width': true,
|
|
560
|
-
}),
|
|
561
|
-
);
|
|
562
|
-
const componentLocator = page.locator(componentName);
|
|
563
|
-
const component = createComboBoxTestDriver(componentLocator);
|
|
564
|
-
await page.waitForSelector(componentName);
|
|
565
|
-
|
|
566
|
-
componentLocator.page().$eval(
|
|
567
|
-
componentName,
|
|
568
|
-
(node: any, arg) => {
|
|
569
|
-
node.value = arg;
|
|
570
|
-
},
|
|
571
|
-
['value1', 'value2', 'value1'],
|
|
572
|
-
);
|
|
573
|
-
await page.waitForTimeout(1000);
|
|
574
|
-
expect(await component.screenshot()).toMatchSnapshot();
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
test('pattern do not match', async ({ page }) => {
|
|
578
|
-
await page.goto(
|
|
579
|
-
getStoryUrl(storyName, {
|
|
580
|
-
pattern: 'bla',
|
|
581
|
-
'data-errormessage-pattern-mismatch': 'wrong',
|
|
582
|
-
'allow-custom-value': 'true',
|
|
583
|
-
}),
|
|
584
|
-
);
|
|
585
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
586
|
-
await component.addItem('kuku');
|
|
587
|
-
await page.getByRole('button').getByText('Submit').click();
|
|
588
|
-
await expect(page.getByText('wrong')).toBeVisible();
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
test('error message with icon', async ({ page }) => {
|
|
592
|
-
await page.goto(
|
|
593
|
-
getStoryUrl(storyName, { required: true, errorMsgIcon: true }),
|
|
594
|
-
);
|
|
595
|
-
|
|
596
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
597
|
-
|
|
598
|
-
await page.getByRole('button').getByText('Submit').click();
|
|
599
|
-
|
|
600
|
-
expect(
|
|
601
|
-
await component.screenshot({
|
|
602
|
-
animations: 'disabled',
|
|
603
|
-
caret: 'hide',
|
|
604
|
-
delay: 3000,
|
|
605
|
-
}),
|
|
606
|
-
).toMatchSnapshot();
|
|
607
|
-
});
|
|
608
|
-
});
|
|
609
|
-
});
|
|
610
|
-
|
|
611
|
-
test.describe('variants', () => {
|
|
612
|
-
loopPresets(floatingLabelTypePresets, (preset, name) => {
|
|
613
|
-
test.describe(name, () => {
|
|
614
|
-
test.beforeEach(async ({ page }) => {
|
|
615
|
-
await page.goto(getStoryUrl(storyName, preset), {
|
|
616
|
-
waitUntil: 'networkidle',
|
|
617
|
-
});
|
|
618
|
-
});
|
|
619
|
-
|
|
620
|
-
test('hover', async ({ page }) => {
|
|
621
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
622
|
-
await component.setValue('itemId2');
|
|
623
|
-
await component.hover();
|
|
624
|
-
expect(
|
|
625
|
-
await component.screenshot({ animations: 'disabled' }),
|
|
626
|
-
).toMatchSnapshot();
|
|
627
|
-
});
|
|
628
|
-
test('focus', async ({ page }) => {
|
|
629
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
630
|
-
await component.focus();
|
|
631
|
-
expect(
|
|
632
|
-
await component.screenshot({ animations: 'disabled' }),
|
|
633
|
-
).toMatchSnapshot();
|
|
634
|
-
});
|
|
635
|
-
});
|
|
636
|
-
});
|
|
637
|
-
});
|
|
638
|
-
|
|
639
|
-
test.describe('custom error message', () => {
|
|
640
|
-
loopPresets(
|
|
641
|
-
{
|
|
642
|
-
'value missing: default': {
|
|
643
|
-
required: 'true',
|
|
644
|
-
defaultErrorMessageValueMissing: 'true',
|
|
645
|
-
},
|
|
646
|
-
'value missing: custom': {
|
|
647
|
-
required: 'true',
|
|
648
|
-
'data-errormessage-value-missing': 'custom message',
|
|
649
|
-
},
|
|
650
|
-
'value missing: empty': {
|
|
651
|
-
required: 'true',
|
|
652
|
-
'data-errormessage-value-missing': '',
|
|
653
|
-
},
|
|
654
|
-
},
|
|
655
|
-
(preset, name) => {
|
|
656
|
-
test(name, async ({ page }) => {
|
|
657
|
-
await page.goto(getStoryUrl(storyName, preset));
|
|
658
|
-
const component = createComboBoxTestDriver(page.locator(componentName));
|
|
659
|
-
await page.getByRole('button').getByText('Submit').click();
|
|
660
|
-
expect(
|
|
661
|
-
await component.screenshot({ animations: 'disabled', delay: 3000 }),
|
|
662
|
-
).toMatchSnapshot();
|
|
663
|
-
});
|
|
664
|
-
},
|
|
665
|
-
);
|
|
666
|
-
});
|
package/project.json
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@descope-ui/descope-multi-select-combo-box",
|
|
3
|
-
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
-
"sourceRoot": "packages/web-components/components/descope-multi-select-combo-box/src",
|
|
5
|
-
"projectType": "library",
|
|
6
|
-
"targets": {},
|
|
7
|
-
"tags": []
|
|
8
|
-
}
|