@aquera/nile-elements 2.0.18 → 2.0.19
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/README.md +5 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +404 -385
- package/dist/nile-breadcrumb/nile-breadcrumb.cjs.js +1 -1
- package/dist/nile-breadcrumb/nile-breadcrumb.cjs.js.map +1 -1
- package/dist/nile-breadcrumb/nile-breadcrumb.esm.js +2 -2
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.cjs.js +1 -1
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.cjs.js.map +1 -1
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.css.cjs.js +1 -1
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.css.cjs.js.map +1 -1
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.css.esm.js +14 -2
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.esm.js +4 -4
- package/dist/nile-select/index.cjs.js +1 -1
- package/dist/nile-select/index.esm.js +1 -1
- package/dist/nile-select/nile-select.cjs.js +2 -2
- package/dist/nile-select/nile-select.cjs.js.map +1 -1
- package/dist/nile-select/nile-select.esm.js +1 -1
- package/dist/nile-select/virtual-scroll-helper.cjs.js +1 -1
- package/dist/nile-select/virtual-scroll-helper.cjs.js.map +1 -1
- package/dist/nile-select/virtual-scroll-helper.esm.js +48 -47
- package/dist/nile-virtual-select/nile-virtual-select.cjs.js +4 -4
- package/dist/nile-virtual-select/nile-virtual-select.cjs.js.map +1 -1
- package/dist/nile-virtual-select/nile-virtual-select.esm.js +2 -2
- package/dist/src/nile-breadcrumb/nile-breadcrumb.d.ts +7 -0
- package/dist/src/nile-breadcrumb/nile-breadcrumb.js +24 -1
- package/dist/src/nile-breadcrumb/nile-breadcrumb.js.map +1 -1
- package/dist/src/nile-breadcrumb/nile-breadcrumb.test.js +51 -0
- package/dist/src/nile-breadcrumb/nile-breadcrumb.test.js.map +1 -1
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.css.js +12 -0
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.css.js.map +1 -1
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.d.ts +5 -0
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.js +9 -0
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.js.map +1 -1
- package/dist/src/nile-select/nile-select.d.ts +1 -0
- package/dist/src/nile-select/nile-select.js +16 -1
- package/dist/src/nile-select/nile-select.js.map +1 -1
- package/dist/src/nile-select/nile-select.test.js +430 -5
- package/dist/src/nile-select/nile-select.test.js.map +1 -1
- package/dist/src/nile-select/virtual-scroll-helper.js +7 -4
- package/dist/src/nile-select/virtual-scroll-helper.js.map +1 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.d.ts +3 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.js +14 -6
- package/dist/src/nile-virtual-select/nile-virtual-select.js.map +1 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.test.js +115 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.test.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/nile-breadcrumb/nile-breadcrumb.test.ts +57 -0
- package/src/nile-breadcrumb/nile-breadcrumb.ts +19 -0
- package/src/nile-breadcrumb-item/nile-breadcrumb-item.css.ts +12 -0
- package/src/nile-breadcrumb-item/nile-breadcrumb-item.ts +7 -0
- package/src/nile-select/nile-select.test.ts +560 -5
- package/src/nile-select/nile-select.ts +21 -1
- package/src/nile-select/virtual-scroll-helper.ts +7 -4
- package/src/nile-virtual-select/nile-virtual-select.test.ts +139 -1
- package/src/nile-virtual-select/nile-virtual-select.ts +17 -6
- package/vscode-html-custom-data.json +39 -14
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { aTimeout, expect, fixture, html, nextFrame, waitUntil } from '@open-wc/testing';
|
|
1
|
+
import { aTimeout, expect, fixture, html, nextFrame, oneEvent, waitUntil } from '@open-wc/testing';
|
|
2
2
|
import './nile-select';
|
|
3
3
|
import '../nile-option/nile-option';
|
|
4
4
|
import '../nile-input/nile-input';
|
|
@@ -507,12 +507,13 @@ describe('NileSelect chip fitting behaviour matrix', () => {
|
|
|
507
507
|
expect(el.shadowRoot.querySelector('button.select__tags-count')).to.not.exist;
|
|
508
508
|
});
|
|
509
509
|
});
|
|
510
|
-
describe('NileSelect enableVirtualScroll value sync', () => {
|
|
510
|
+
describe('NileSelect enableVirtualScroll value sync (showTooltip)', () => {
|
|
511
511
|
const ROLES = ['Administrators', 'Users', 'Guests', 'Print Operators'];
|
|
512
512
|
const DATA = ROLES.map(role => ({ label: role, value: role }));
|
|
513
513
|
async function virtualSelect(tpl = html `<nile-select
|
|
514
514
|
multiple
|
|
515
515
|
.enableVirtualScroll=${true}
|
|
516
|
+
.showTooltip=${true}
|
|
516
517
|
.data=${DATA}
|
|
517
518
|
.value=${[]}
|
|
518
519
|
></nile-select>`) {
|
|
@@ -546,6 +547,7 @@ describe('NileSelect enableVirtualScroll value sync', () => {
|
|
|
546
547
|
const { el, inner } = await virtualSelect(html `<nile-select
|
|
547
548
|
multiple
|
|
548
549
|
.enableVirtualScroll=${true}
|
|
550
|
+
.showTooltip=${true}
|
|
549
551
|
.data=${DATA}
|
|
550
552
|
.value=${['Administrators', 'Users', 'Guests']}
|
|
551
553
|
></nile-select>`);
|
|
@@ -569,6 +571,7 @@ describe('NileSelect enableVirtualScroll value sync', () => {
|
|
|
569
571
|
it('V5. single-select virtual mode keeps the wrapper value in sync', async () => {
|
|
570
572
|
const { el, inner } = await virtualSelect(html `<nile-select
|
|
571
573
|
.enableVirtualScroll=${true}
|
|
574
|
+
.showTooltip=${true}
|
|
572
575
|
.data=${DATA}
|
|
573
576
|
></nile-select>`);
|
|
574
577
|
inner.handleOptionSelection({ value: 'Users' });
|
|
@@ -580,7 +583,8 @@ describe('NileSelect enableVirtualScroll value sync', () => {
|
|
|
580
583
|
});
|
|
581
584
|
it('V6. resizing the host does not re-render the wrapper without autoResize', async () => {
|
|
582
585
|
const host = await fixture(html `<div style="width: 400px">
|
|
583
|
-
<nile-select multiple .enableVirtualScroll=${true}
|
|
586
|
+
<nile-select multiple .enableVirtualScroll=${true}
|
|
587
|
+
.showTooltip=${true} .data=${DATA}></nile-select>
|
|
584
588
|
</div>`);
|
|
585
589
|
const el = host.querySelector('nile-select');
|
|
586
590
|
await el.updateComplete;
|
|
@@ -599,7 +603,7 @@ describe('NileSelect enableVirtualScroll value sync', () => {
|
|
|
599
603
|
expect(updates).to.equal(0);
|
|
600
604
|
});
|
|
601
605
|
});
|
|
602
|
-
describe('NileSelect enableVirtualScroll + searchEnabled value sync', () => {
|
|
606
|
+
describe('NileSelect enableVirtualScroll + searchEnabled value sync (showTooltip)', () => {
|
|
603
607
|
const ROLES = ['Administrators', 'Users', 'Guests', 'Print Operators'];
|
|
604
608
|
const DATA = ROLES.map(role => ({ label: role, value: role }));
|
|
605
609
|
async function settle(el, inner) {
|
|
@@ -615,6 +619,7 @@ describe('NileSelect enableVirtualScroll + searchEnabled value sync', () => {
|
|
|
615
619
|
?multiple=${multiple}
|
|
616
620
|
.searchEnabled=${true}
|
|
617
621
|
.enableVirtualScroll=${true}
|
|
622
|
+
.showTooltip=${true}
|
|
618
623
|
.portal=${portal}
|
|
619
624
|
.data=${DATA}
|
|
620
625
|
.value=${value}
|
|
@@ -1251,7 +1256,7 @@ describe('NileSelect 2.0.8 compatibility matrix', () => {
|
|
|
1251
1256
|
expect(inner.value).to.deep.equal(['b']);
|
|
1252
1257
|
expect(inner.shadowRoot.querySelectorAll('.select__tags nile-tag').length).to.equal(1);
|
|
1253
1258
|
});
|
|
1254
|
-
it('C9. enableVirtualScroll: programmatic value
|
|
1259
|
+
it('C9. enableVirtualScroll: programmatic value reaches the inner select; clear-all leaves the outer value alone (pre-2.0.9)', async () => {
|
|
1255
1260
|
const el = await fixture(html `<nile-select multiple .enableVirtualScroll=${true} .data=${DATA}></nile-select>`);
|
|
1256
1261
|
await settle(el);
|
|
1257
1262
|
const inner = el.shadowRoot.querySelector('nile-virtual-select');
|
|
@@ -1263,6 +1268,21 @@ describe('NileSelect 2.0.8 compatibility matrix', () => {
|
|
|
1263
1268
|
await inner.updateComplete;
|
|
1264
1269
|
await settle(el);
|
|
1265
1270
|
expect(inner.value).to.deep.equal([]);
|
|
1271
|
+
// Without showTooltip the inner select owns the selection; the outer value is not written back.
|
|
1272
|
+
expect(el.value).to.deep.equal(['a', 'c']);
|
|
1273
|
+
});
|
|
1274
|
+
it('C9b. enableVirtualScroll + showTooltip: programmatic value and clear-all reach both selects', async () => {
|
|
1275
|
+
const el = await fixture(html `<nile-select multiple showTooltip .enableVirtualScroll=${true} .data=${DATA}></nile-select>`);
|
|
1276
|
+
await settle(el);
|
|
1277
|
+
const inner = el.shadowRoot.querySelector('nile-virtual-select');
|
|
1278
|
+
el.value = ['a', 'c'];
|
|
1279
|
+
await settle(el);
|
|
1280
|
+
await inner.updateComplete;
|
|
1281
|
+
expect(inner.value).to.deep.equal(['a', 'c']);
|
|
1282
|
+
inner.unSelectAll();
|
|
1283
|
+
await inner.updateComplete;
|
|
1284
|
+
await settle(el);
|
|
1285
|
+
expect(inner.value).to.deep.equal([]);
|
|
1266
1286
|
expect(el.value).to.deep.equal([]);
|
|
1267
1287
|
});
|
|
1268
1288
|
});
|
|
@@ -1325,4 +1345,409 @@ describe('NileSelect showtooltip tooltip on sub-pixel truncation', () => {
|
|
|
1325
1345
|
}
|
|
1326
1346
|
});
|
|
1327
1347
|
});
|
|
1348
|
+
const vsMounted = [];
|
|
1349
|
+
const VS_OPTIONS = Array.from({ length: 300 }, (_, i) => ({ value: `option-${i + 1}`, label: `Option ${i + 1}` }));
|
|
1350
|
+
function vsRoots(inner) {
|
|
1351
|
+
const portal = document.body.querySelector('.nile-virtual-select-portal-append');
|
|
1352
|
+
return [inner.shadowRoot, ...(portal ? [portal] : [])];
|
|
1353
|
+
}
|
|
1354
|
+
function vsAll(inner, selector) {
|
|
1355
|
+
return vsRoots(inner).flatMap(root => Array.from(root.querySelectorAll(selector)));
|
|
1356
|
+
}
|
|
1357
|
+
async function vsMount({ showTooltip = false, multiple = true, search = false, portal = false, value = undefined, data = VS_OPTIONS, } = {}) {
|
|
1358
|
+
const initial = value ?? (multiple ? [] : '');
|
|
1359
|
+
const el = await fixture(html `<nile-select
|
|
1360
|
+
?multiple=${multiple}
|
|
1361
|
+
?searchEnabled=${search}
|
|
1362
|
+
?showTooltip=${showTooltip}
|
|
1363
|
+
.enableVirtualScroll=${true}
|
|
1364
|
+
.portal=${portal}
|
|
1365
|
+
.data=${data}
|
|
1366
|
+
.value=${initial}
|
|
1367
|
+
></nile-select>`);
|
|
1368
|
+
await el.updateComplete;
|
|
1369
|
+
const inner = el.shadowRoot.querySelector('nile-virtual-select');
|
|
1370
|
+
await inner.updateComplete;
|
|
1371
|
+
vsMounted.push(inner);
|
|
1372
|
+
let updates = 0;
|
|
1373
|
+
const update = el.update;
|
|
1374
|
+
el.update = function (changed) {
|
|
1375
|
+
updates++;
|
|
1376
|
+
return update.call(this, changed);
|
|
1377
|
+
};
|
|
1378
|
+
return { el, inner, updates: () => updates, resetUpdates: () => (updates = 0) };
|
|
1379
|
+
}
|
|
1380
|
+
async function vsSettle(el, inner) {
|
|
1381
|
+
await inner.updateComplete;
|
|
1382
|
+
await el.updateComplete;
|
|
1383
|
+
await inner.updateComplete;
|
|
1384
|
+
await aTimeout(30);
|
|
1385
|
+
}
|
|
1386
|
+
async function vsOpen(inner) {
|
|
1387
|
+
const shown = oneEvent(inner, 'nile-after-show');
|
|
1388
|
+
inner.shadowRoot.querySelector('[part="combobox"]').dispatchEvent(new MouseEvent('mousedown', { bubbles: true, composed: true, button: 0 }));
|
|
1389
|
+
await shown;
|
|
1390
|
+
await aTimeout(50);
|
|
1391
|
+
}
|
|
1392
|
+
async function vsPick(el, inner, value) {
|
|
1393
|
+
await waitUntil(() => vsAll(inner, 'nile-option').find(o => o.value === value), `option ${value} was not rendered`);
|
|
1394
|
+
const option = vsAll(inner, 'nile-option').find(o => o.value === value);
|
|
1395
|
+
option.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, composed: true, button: 0 }));
|
|
1396
|
+
await vsSettle(el, inner);
|
|
1397
|
+
}
|
|
1398
|
+
async function vsToggleSelected(el, inner) {
|
|
1399
|
+
vsAll(inner, '.select__footer nile-checkbox')[0].click();
|
|
1400
|
+
await vsSettle(el, inner);
|
|
1401
|
+
}
|
|
1402
|
+
async function vsType(el, inner, text) {
|
|
1403
|
+
const input = vsAll(inner, '.select__search nile-input')[0].shadowRoot.querySelector('input');
|
|
1404
|
+
input.value = text;
|
|
1405
|
+
input.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
|
|
1406
|
+
await vsSettle(el, inner);
|
|
1407
|
+
}
|
|
1408
|
+
async function vsRemoveChip(el, inner, index = 0) {
|
|
1409
|
+
const tag = inner.shadowRoot.querySelectorAll('nile-tag')[index];
|
|
1410
|
+
const remove = tag.shadowRoot.querySelector('[part="remove-button"], nile-icon-button, button');
|
|
1411
|
+
(remove.shadowRoot?.querySelector('button') ?? remove).click();
|
|
1412
|
+
await vsSettle(el, inner);
|
|
1413
|
+
}
|
|
1414
|
+
const VS_SEARCH = 'Option 99';
|
|
1415
|
+
const VS_SEARCH_HITS = VS_OPTIONS.filter(o => o.label.includes(VS_SEARCH)).length;
|
|
1416
|
+
const vsDataValues = (inner) => inner.data.map(item => item.value);
|
|
1417
|
+
// Known, pre-existing noise from @lit-labs/virtualizer, unrelated to these tests: a "ResizeObserver loop" notice
|
|
1418
|
+
// while a list is laid out, and a detached-list error when the visible list swaps between a short and a long data
|
|
1419
|
+
// set (for example leaving the Selected view). The browser raises them as window errors, which would fail
|
|
1420
|
+
// whichever test happens to be running. Only the new virtual-scroll describes below install this filter; their
|
|
1421
|
+
// assertions still decide pass or fail.
|
|
1422
|
+
// The virtualizer-only errors are matched on message AND on a `virtualizer` frame in the stack, so the same message
|
|
1423
|
+
// thrown from anywhere else still fails the test. "ResizeObserver loop" is a browser notice with no stack.
|
|
1424
|
+
const VS_VIRTUALIZER_ERRORS = ['ChildPart` has no `parentNode`', "reading 'insertBefore'"];
|
|
1425
|
+
function vsIsKnownVirtualizerNoise(message, error) {
|
|
1426
|
+
if (typeof message !== 'string')
|
|
1427
|
+
return false;
|
|
1428
|
+
if (message.includes('ResizeObserver loop'))
|
|
1429
|
+
return true;
|
|
1430
|
+
return (VS_VIRTUALIZER_ERRORS.some(known => message.includes(known)) &&
|
|
1431
|
+
!!error?.stack &&
|
|
1432
|
+
error.stack.toLowerCase().includes('virtualizer'));
|
|
1433
|
+
}
|
|
1434
|
+
function vsIgnoreKnownVirtualizerErrors() {
|
|
1435
|
+
const previous = window.onerror;
|
|
1436
|
+
window.onerror = (message, source, lineno, colno, error) => {
|
|
1437
|
+
if (vsIsKnownVirtualizerNoise(message, error))
|
|
1438
|
+
return true;
|
|
1439
|
+
return previous ? previous.call(window, message, source, lineno, colno, error) : false;
|
|
1440
|
+
};
|
|
1441
|
+
return () => {
|
|
1442
|
+
window.onerror = previous;
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1445
|
+
// Close every dropdown and let it finish hiding before its fixture goes away, so the virtualizer is not
|
|
1446
|
+
// still laying out a list that has already been detached. Registered per describe below, not file-wide.
|
|
1447
|
+
async function vsCloseDropdowns() {
|
|
1448
|
+
const mounted = vsMounted.splice(0);
|
|
1449
|
+
for (const inner of mounted) {
|
|
1450
|
+
if (!inner.open)
|
|
1451
|
+
continue;
|
|
1452
|
+
const hidden = oneEvent(inner, 'nile-after-hide');
|
|
1453
|
+
inner.open = false;
|
|
1454
|
+
await Promise.race([hidden, aTimeout(1500)]);
|
|
1455
|
+
}
|
|
1456
|
+
if (mounted.length) {
|
|
1457
|
+
await nextFrame();
|
|
1458
|
+
await nextFrame();
|
|
1459
|
+
await aTimeout(250);
|
|
1460
|
+
}
|
|
1461
|
+
document.body.querySelectorAll('.nile-virtual-select-portal-append').forEach(n => n.remove());
|
|
1462
|
+
}
|
|
1463
|
+
describe('NileSelect enableVirtualScroll without showTooltip keeps the pre-2.0.9 behaviour', () => {
|
|
1464
|
+
let restoreOnError;
|
|
1465
|
+
before(() => {
|
|
1466
|
+
restoreOnError = vsIgnoreKnownVirtualizerErrors();
|
|
1467
|
+
});
|
|
1468
|
+
after(() => {
|
|
1469
|
+
restoreOnError();
|
|
1470
|
+
});
|
|
1471
|
+
afterEach(vsCloseDropdowns);
|
|
1472
|
+
it('L1. a pick does not write the outer value', async () => {
|
|
1473
|
+
const { el, inner } = await vsMount();
|
|
1474
|
+
await vsOpen(inner);
|
|
1475
|
+
await vsPick(el, inner, 'option-1');
|
|
1476
|
+
expect(inner.value).to.deep.equal(['option-1']);
|
|
1477
|
+
expect(el.value).to.deep.equal([]);
|
|
1478
|
+
});
|
|
1479
|
+
it('L2. a normal pick, uncheck and chip removal cause no outer update', async () => {
|
|
1480
|
+
const { el, inner, updates, resetUpdates } = await vsMount({ value: ['option-9'] });
|
|
1481
|
+
await vsOpen(inner);
|
|
1482
|
+
resetUpdates();
|
|
1483
|
+
await vsPick(el, inner, 'option-1');
|
|
1484
|
+
await vsPick(el, inner, 'option-1');
|
|
1485
|
+
await vsRemoveChip(el, inner, 0);
|
|
1486
|
+
expect(updates()).to.equal(0);
|
|
1487
|
+
});
|
|
1488
|
+
it('L3. a parent re-render pushes the stale outer value back over the selection', async () => {
|
|
1489
|
+
const { el, inner } = await vsMount();
|
|
1490
|
+
await vsOpen(inner);
|
|
1491
|
+
await vsPick(el, inner, 'option-1');
|
|
1492
|
+
expect(inner.value).to.deep.equal(['option-1']);
|
|
1493
|
+
el.requestUpdate();
|
|
1494
|
+
await vsSettle(el, inner);
|
|
1495
|
+
expect(inner.value).to.deep.equal([]);
|
|
1496
|
+
});
|
|
1497
|
+
it('L4. nile-input / nile-change from the inner select are not synced (no sync listeners)', async () => {
|
|
1498
|
+
const { el, inner } = await vsMount({ value: ['option-1'] });
|
|
1499
|
+
const fire = (name, value) => inner.dispatchEvent(new CustomEvent(name, { detail: { value }, bubbles: true, composed: true }));
|
|
1500
|
+
fire('nile-input', ['option-2']);
|
|
1501
|
+
fire('nile-change', ['option-3']);
|
|
1502
|
+
await vsSettle(el, inner);
|
|
1503
|
+
expect(el.value).to.deep.equal(['option-1']);
|
|
1504
|
+
});
|
|
1505
|
+
it('L5. a direct syncValueFromVirtualSelect call does not change the outer value', async () => {
|
|
1506
|
+
const { el, inner } = await vsMount({ value: ['option-1'] });
|
|
1507
|
+
const event = new CustomEvent('nile-change', { detail: { value: ['option-2'] } });
|
|
1508
|
+
Object.defineProperty(event, 'currentTarget', { value: inner });
|
|
1509
|
+
Object.defineProperty(event, 'composedPath', { value: () => [inner] });
|
|
1510
|
+
el.syncValueFromVirtualSelect(event);
|
|
1511
|
+
await vsSettle(el, inner);
|
|
1512
|
+
expect(el.value).to.deep.equal(['option-1']);
|
|
1513
|
+
});
|
|
1514
|
+
it('L6. Selected stays filtered through a normal uncheck', async () => {
|
|
1515
|
+
const { el, inner } = await vsMount();
|
|
1516
|
+
await vsOpen(inner);
|
|
1517
|
+
await vsPick(el, inner, 'option-1');
|
|
1518
|
+
await vsPick(el, inner, 'option-2');
|
|
1519
|
+
await vsPick(el, inner, 'option-3');
|
|
1520
|
+
await vsToggleSelected(el, inner);
|
|
1521
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2', 'option-3']);
|
|
1522
|
+
await vsPick(el, inner, 'option-2');
|
|
1523
|
+
expect(inner.showSelected).to.be.true;
|
|
1524
|
+
expect(inner.value).to.deep.equal(['option-1', 'option-3']);
|
|
1525
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2', 'option-3']);
|
|
1526
|
+
});
|
|
1527
|
+
it('L7. search stays filtered through a pick and an unpick', async () => {
|
|
1528
|
+
const { el, inner } = await vsMount({ search: true });
|
|
1529
|
+
await vsOpen(inner);
|
|
1530
|
+
await vsType(el, inner, VS_SEARCH);
|
|
1531
|
+
expect(inner.data.length).to.equal(VS_SEARCH_HITS);
|
|
1532
|
+
await vsPick(el, inner, 'option-99');
|
|
1533
|
+
expect(inner.data.length).to.equal(VS_SEARCH_HITS);
|
|
1534
|
+
expect(inner.searchValue).to.equal(VS_SEARCH);
|
|
1535
|
+
await vsPick(el, inner, 'option-99');
|
|
1536
|
+
expect(inner.data.length).to.equal(VS_SEARCH_HITS);
|
|
1537
|
+
expect(inner.value).to.deep.equal([]);
|
|
1538
|
+
});
|
|
1539
|
+
it('L9. the wrapper pushes maxOptionsVisible to the inner select (pre-2.0.9 binding)', async () => {
|
|
1540
|
+
const { el, inner } = await vsMount({ value: ['option-1'] });
|
|
1541
|
+
const writes = [];
|
|
1542
|
+
const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(inner), 'maxOptionsVisible');
|
|
1543
|
+
Object.defineProperty(inner, 'maxOptionsVisible', {
|
|
1544
|
+
configurable: true,
|
|
1545
|
+
get() {
|
|
1546
|
+
return descriptor.get.call(this);
|
|
1547
|
+
},
|
|
1548
|
+
set(value) {
|
|
1549
|
+
writes.push(value);
|
|
1550
|
+
descriptor.set.call(this, value);
|
|
1551
|
+
},
|
|
1552
|
+
});
|
|
1553
|
+
el.maxOptionsVisible = 5;
|
|
1554
|
+
await vsSettle(el, inner);
|
|
1555
|
+
expect(writes).to.include(5);
|
|
1556
|
+
});
|
|
1557
|
+
it('L10. the untouched default maxOptionsVisible is not pushed, so the inner select is not pinned as explicit', async () => {
|
|
1558
|
+
const { inner } = await vsMount();
|
|
1559
|
+
expect(inner.maxOptionsVisibleExplicit).to.be.false;
|
|
1560
|
+
});
|
|
1561
|
+
it('L8. data is re-applied on every wrapper render (plain binding, pre-2.0.9)', async () => {
|
|
1562
|
+
const { el, inner } = await vsMount({ value: ['option-1'] });
|
|
1563
|
+
await vsOpen(inner);
|
|
1564
|
+
// After opening, the inner select holds its own copy of the list.
|
|
1565
|
+
expect(inner.data).to.not.equal(el.data);
|
|
1566
|
+
el.requestUpdate();
|
|
1567
|
+
await vsSettle(el, inner);
|
|
1568
|
+
expect(inner.data).to.equal(el.data);
|
|
1569
|
+
});
|
|
1570
|
+
});
|
|
1571
|
+
describe('NileSelect enableVirtualScroll with showTooltip: guarded data and external value updates', () => {
|
|
1572
|
+
let restoreOnError;
|
|
1573
|
+
before(() => {
|
|
1574
|
+
restoreOnError = vsIgnoreKnownVirtualizerErrors();
|
|
1575
|
+
});
|
|
1576
|
+
after(() => {
|
|
1577
|
+
restoreOnError();
|
|
1578
|
+
});
|
|
1579
|
+
afterEach(vsCloseDropdowns);
|
|
1580
|
+
it('T1. Selected + uncheck stays filtered', async () => {
|
|
1581
|
+
const { el, inner } = await vsMount({ showTooltip: true });
|
|
1582
|
+
await vsOpen(inner);
|
|
1583
|
+
await vsPick(el, inner, 'option-1');
|
|
1584
|
+
await vsPick(el, inner, 'option-2');
|
|
1585
|
+
await vsPick(el, inner, 'option-3');
|
|
1586
|
+
await vsToggleSelected(el, inner);
|
|
1587
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2', 'option-3']);
|
|
1588
|
+
await vsPick(el, inner, 'option-2');
|
|
1589
|
+
expect(inner.showSelected).to.be.true;
|
|
1590
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2', 'option-3']);
|
|
1591
|
+
expect(el.value).to.deep.equal(['option-1', 'option-3']);
|
|
1592
|
+
});
|
|
1593
|
+
it('T2. search + pick/unpick stays filtered', async () => {
|
|
1594
|
+
const { el, inner } = await vsMount({ showTooltip: true, search: true });
|
|
1595
|
+
await vsOpen(inner);
|
|
1596
|
+
await vsType(el, inner, VS_SEARCH);
|
|
1597
|
+
expect(inner.data.length).to.equal(VS_SEARCH_HITS);
|
|
1598
|
+
await vsPick(el, inner, 'option-99');
|
|
1599
|
+
expect(inner.data.length).to.equal(VS_SEARCH_HITS);
|
|
1600
|
+
expect(inner.searchValue).to.equal(VS_SEARCH);
|
|
1601
|
+
expect(el.value).to.deep.equal(['option-99']);
|
|
1602
|
+
await vsPick(el, inner, 'option-99');
|
|
1603
|
+
expect(inner.data.length).to.equal(VS_SEARCH_HITS);
|
|
1604
|
+
expect(el.value).to.deep.equal([]);
|
|
1605
|
+
});
|
|
1606
|
+
it('T3. chip removal while Selected stays filtered', async () => {
|
|
1607
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2', 'option-3'] });
|
|
1608
|
+
await vsOpen(inner);
|
|
1609
|
+
await vsToggleSelected(el, inner);
|
|
1610
|
+
expect(inner.data.length).to.equal(3);
|
|
1611
|
+
await vsRemoveChip(el, inner, 0);
|
|
1612
|
+
expect(inner.showSelected).to.be.true;
|
|
1613
|
+
expect(inner.data.length).to.equal(3);
|
|
1614
|
+
expect(el.value).to.deep.equal(['option-2', 'option-3']);
|
|
1615
|
+
});
|
|
1616
|
+
it('T4. portal: Selected + uncheck stays filtered', async () => {
|
|
1617
|
+
const { el, inner } = await vsMount({ showTooltip: true, portal: true });
|
|
1618
|
+
await vsOpen(inner);
|
|
1619
|
+
await waitUntil(() => document.body.querySelector('.nile-virtual-select-portal-append #listbox'), 'listbox never portalled');
|
|
1620
|
+
await vsPick(el, inner, 'option-1');
|
|
1621
|
+
await vsPick(el, inner, 'option-2');
|
|
1622
|
+
await vsToggleSelected(el, inner);
|
|
1623
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2']);
|
|
1624
|
+
await vsPick(el, inner, 'option-2');
|
|
1625
|
+
expect(inner.showSelected).to.be.true;
|
|
1626
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2']);
|
|
1627
|
+
expect(el.value).to.deep.equal(['option-1']);
|
|
1628
|
+
});
|
|
1629
|
+
it('T5. picking, removing a chip and clearing sync the outer value; nile-change listeners see it', async () => {
|
|
1630
|
+
const { el, inner } = await vsMount({ showTooltip: true });
|
|
1631
|
+
const seen = [];
|
|
1632
|
+
el.addEventListener('nile-change', () => seen.push(el.value));
|
|
1633
|
+
await vsOpen(inner);
|
|
1634
|
+
await vsPick(el, inner, 'option-1');
|
|
1635
|
+
await vsPick(el, inner, 'option-2');
|
|
1636
|
+
expect(el.value).to.deep.equal(['option-1', 'option-2']);
|
|
1637
|
+
expect(seen[0]).to.deep.equal(['option-1']);
|
|
1638
|
+
await vsRemoveChip(el, inner, 0);
|
|
1639
|
+
expect(el.value).to.deep.equal(['option-2']);
|
|
1640
|
+
vsAll(inner, '.select__clear')[0].click();
|
|
1641
|
+
await vsSettle(el, inner);
|
|
1642
|
+
expect(el.value).to.deep.equal([]);
|
|
1643
|
+
});
|
|
1644
|
+
it('T6. an external value replace while Selected recomputes the list', async () => {
|
|
1645
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2'] });
|
|
1646
|
+
await vsOpen(inner);
|
|
1647
|
+
await vsToggleSelected(el, inner);
|
|
1648
|
+
el.value = ['option-5'];
|
|
1649
|
+
await vsSettle(el, inner);
|
|
1650
|
+
expect(inner.showSelected).to.be.true;
|
|
1651
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-5']);
|
|
1652
|
+
});
|
|
1653
|
+
it('T7. an external value that adds an item while Selected shows the new item', async () => {
|
|
1654
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2'] });
|
|
1655
|
+
await vsOpen(inner);
|
|
1656
|
+
await vsToggleSelected(el, inner);
|
|
1657
|
+
el.value = ['option-1', 'option-2', 'option-7'];
|
|
1658
|
+
await vsSettle(el, inner);
|
|
1659
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2', 'option-7']);
|
|
1660
|
+
});
|
|
1661
|
+
it('T8. an external value that removes an item while Selected drops it from the list', async () => {
|
|
1662
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2'] });
|
|
1663
|
+
await vsOpen(inner);
|
|
1664
|
+
await vsToggleSelected(el, inner);
|
|
1665
|
+
el.value = ['option-1'];
|
|
1666
|
+
await vsSettle(el, inner);
|
|
1667
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1']);
|
|
1668
|
+
});
|
|
1669
|
+
it('T9. an external empty value leaves the Selected view', async () => {
|
|
1670
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2'] });
|
|
1671
|
+
await vsOpen(inner);
|
|
1672
|
+
await vsToggleSelected(el, inner);
|
|
1673
|
+
el.value = [];
|
|
1674
|
+
await vsSettle(el, inner);
|
|
1675
|
+
expect(inner.showSelected).to.be.false;
|
|
1676
|
+
expect(inner.data.length).to.equal(VS_OPTIONS.length);
|
|
1677
|
+
});
|
|
1678
|
+
it('T10. a normal pick after an external value update still keeps the item listed', async () => {
|
|
1679
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2'] });
|
|
1680
|
+
await vsOpen(inner);
|
|
1681
|
+
await vsToggleSelected(el, inner);
|
|
1682
|
+
el.value = ['option-5', 'option-6'];
|
|
1683
|
+
await vsSettle(el, inner);
|
|
1684
|
+
await vsPick(el, inner, 'option-5');
|
|
1685
|
+
expect(inner.value).to.deep.equal(['option-6']);
|
|
1686
|
+
expect(el.value).to.deep.equal(['option-6']);
|
|
1687
|
+
expect(inner.showSelected).to.be.true;
|
|
1688
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-5', 'option-6']);
|
|
1689
|
+
});
|
|
1690
|
+
it('T11. a normal pick does not re-send the data array', async () => {
|
|
1691
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2'] });
|
|
1692
|
+
await vsOpen(inner);
|
|
1693
|
+
await vsToggleSelected(el, inner);
|
|
1694
|
+
const before = inner.data;
|
|
1695
|
+
await vsPick(el, inner, 'option-2');
|
|
1696
|
+
expect(inner.data).to.equal(before);
|
|
1697
|
+
});
|
|
1698
|
+
it('T12. turning showTooltip on at runtime keeps the selection', async () => {
|
|
1699
|
+
const { el, inner } = await vsMount({ showTooltip: false });
|
|
1700
|
+
await vsOpen(inner);
|
|
1701
|
+
await vsPick(el, inner, 'option-1');
|
|
1702
|
+
await vsPick(el, inner, 'option-2');
|
|
1703
|
+
expect(el.value).to.deep.equal([]);
|
|
1704
|
+
expect(inner.value).to.deep.equal(['option-1', 'option-2']);
|
|
1705
|
+
el.showTooltip = true;
|
|
1706
|
+
await vsSettle(el, inner);
|
|
1707
|
+
expect(el.value).to.deep.equal(['option-1', 'option-2']);
|
|
1708
|
+
expect(inner.value).to.deep.equal(['option-1', 'option-2']);
|
|
1709
|
+
});
|
|
1710
|
+
it('T15. turning showTooltip on at runtime engages the fitted chip row', async () => {
|
|
1711
|
+
const { el, inner } = await vsMount({
|
|
1712
|
+
showTooltip: false,
|
|
1713
|
+
value: ['option-1', 'option-2', 'option-3', 'option-4', 'option-5'],
|
|
1714
|
+
});
|
|
1715
|
+
const fitted = () => !!inner.shadowRoot.querySelector('.select__tags--fitted');
|
|
1716
|
+
expect(fitted()).to.be.false;
|
|
1717
|
+
el.showTooltip = true;
|
|
1718
|
+
await vsSettle(el, inner);
|
|
1719
|
+
await waitUntil(fitted, 'the fitted chip row never engaged');
|
|
1720
|
+
expect(el.value).to.deep.equal(['option-1', 'option-2', 'option-3', 'option-4', 'option-5']);
|
|
1721
|
+
});
|
|
1722
|
+
it('T16. changing showTooltip and value in the same update keeps the consumer value', async () => {
|
|
1723
|
+
const { el, inner } = await vsMount({ showTooltip: false });
|
|
1724
|
+
await vsOpen(inner);
|
|
1725
|
+
await vsPick(el, inner, 'option-1');
|
|
1726
|
+
expect(inner.value).to.deep.equal(['option-1']);
|
|
1727
|
+
expect(el.value).to.deep.equal([]);
|
|
1728
|
+
el.value = ['option-7'];
|
|
1729
|
+
el.showTooltip = true;
|
|
1730
|
+
await vsSettle(el, inner);
|
|
1731
|
+
expect(el.value).to.deep.equal(['option-7']);
|
|
1732
|
+
expect(inner.value).to.deep.equal(['option-7']);
|
|
1733
|
+
});
|
|
1734
|
+
it('T13. assigning a new data array propagates', async () => {
|
|
1735
|
+
const { el, inner } = await vsMount({ showTooltip: true });
|
|
1736
|
+
await vsOpen(inner);
|
|
1737
|
+
el.data = [...VS_OPTIONS.slice(0, 10), { value: 'extra', label: 'Extra' }];
|
|
1738
|
+
await vsSettle(el, inner);
|
|
1739
|
+
expect(inner.data.length).to.equal(11);
|
|
1740
|
+
expect(vsDataValues(inner)).to.include('extra');
|
|
1741
|
+
});
|
|
1742
|
+
it('T14. mutating data in place (data.push) is not propagated; assign a new array instead', async () => {
|
|
1743
|
+
const data = VS_OPTIONS.slice(0, 20);
|
|
1744
|
+
const { el, inner } = await vsMount({ showTooltip: true, data });
|
|
1745
|
+
await vsOpen(inner);
|
|
1746
|
+
data.push({ value: 'extra', label: 'Extra' });
|
|
1747
|
+
el.requestUpdate();
|
|
1748
|
+
await vsSettle(el, inner);
|
|
1749
|
+
expect(inner.data.length).to.equal(20);
|
|
1750
|
+
expect(vsDataValues(inner)).to.not.include('extra');
|
|
1751
|
+
});
|
|
1752
|
+
});
|
|
1328
1753
|
//# sourceMappingURL=nile-select.test.js.map
|