@spectrum-web-components/slider 1.0.2 → 1.0.3

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.
@@ -0,0 +1,1522 @@
1
+ "use strict";
2
+ import "@spectrum-web-components/slider/sp-slider.js";
3
+ import "@spectrum-web-components/slider/sp-slider-handle.js";
4
+ import "@spectrum-web-components/button/sp-button.js";
5
+ import "@spectrum-web-components/overlay/sp-overlay.js";
6
+ import "@spectrum-web-components/popover/sp-popover.js";
7
+ import { tick } from "../stories/slider.stories.js";
8
+ import {
9
+ elementUpdated,
10
+ expect,
11
+ fixture,
12
+ html,
13
+ nextFrame,
14
+ oneEvent,
15
+ waitUntil
16
+ } from "@open-wc/testing";
17
+ import { sendKeys } from "@web/test-runner-commands";
18
+ import { sendMouse } from "../../../test/plugins/browser.js";
19
+ import { spy, stub } from "sinon";
20
+ import { createLanguageContext } from "../../../tools/reactive-controllers/test/helpers.js";
21
+ import { testForLitDevWarnings } from "../../../test/testing-helpers.js";
22
+ describe("Slider", () => {
23
+ testForLitDevWarnings(
24
+ async () => await fixture(html`
25
+ <sp-slider label="Slider"></sp-slider>
26
+ `)
27
+ );
28
+ it("loads", async () => {
29
+ const el = await fixture(html`
30
+ <sp-slider label="Slider"></sp-slider>
31
+ `);
32
+ await elementUpdated(el);
33
+ await expect(el).to.be.accessible();
34
+ });
35
+ it('loads - [variant="tick"]', async () => {
36
+ const el = await fixture(html`
37
+ <sp-slider
38
+ label="Ticked Slider"
39
+ min="-100"
40
+ max="100"
41
+ value="0"
42
+ tick-labels
43
+ variant="tick"
44
+ ></sp-slider>
45
+ `);
46
+ await elementUpdated(el);
47
+ await expect(el).to.be.accessible();
48
+ });
49
+ it('loads - [variant="tick"] irregularly', async () => {
50
+ const el = await fixture(html`
51
+ <sp-slider label="Slider"></sp-slider>
52
+ `);
53
+ await elementUpdated(el);
54
+ await expect(el).to.be.accessible();
55
+ });
56
+ it("receives value from the outside", async () => {
57
+ const el = await fixture(html`
58
+ <sp-slider max="20"></sp-slider>
59
+ `);
60
+ await elementUpdated(el);
61
+ expect(el.value).to.equal(10);
62
+ el.value = 10;
63
+ await elementUpdated(el);
64
+ expect(el.value).to.equal(10);
65
+ el.value = 50;
66
+ await elementUpdated(el);
67
+ expect(el.value).to.equal(20);
68
+ });
69
+ it("accepts keyboard events", async () => {
70
+ const el = await fixture(
71
+ tick({
72
+ variant: "tick",
73
+ tickStep: 5
74
+ })
75
+ );
76
+ await elementUpdated(el);
77
+ expect(el.value).to.equal(46);
78
+ expect(el.highlight).to.be.false;
79
+ el.focus();
80
+ await sendKeys({
81
+ press: "ArrowDown"
82
+ });
83
+ await elementUpdated(el);
84
+ expect(el.value).to.equal(45);
85
+ expect(el.highlight).to.be.true;
86
+ await sendKeys({
87
+ press: "ArrowUp"
88
+ });
89
+ await elementUpdated(el);
90
+ expect(el.value).to.equal(46);
91
+ expect(el.highlight).to.be.true;
92
+ });
93
+ it("accepts pointer events", async () => {
94
+ let pointerId = -1;
95
+ const el = await fixture(html`
96
+ <sp-slider></sp-slider>
97
+ `);
98
+ await elementUpdated(el);
99
+ expect(el.dragging).to.be.false;
100
+ expect(el.highlight).to.be.false;
101
+ expect(pointerId).to.equal(-1);
102
+ const handle = el.shadowRoot.querySelector(".handle");
103
+ el.track.setPointerCapture = (id) => pointerId = id;
104
+ el.track.releasePointerCapture = (id) => pointerId = id;
105
+ handle.dispatchEvent(
106
+ new PointerEvent("pointerdown", {
107
+ button: 1,
108
+ pointerId: 1,
109
+ cancelable: true,
110
+ bubbles: true,
111
+ composed: true
112
+ })
113
+ );
114
+ await elementUpdated(el);
115
+ expect(el.dragging).to.be.false;
116
+ expect(pointerId, "1").to.equal(-1);
117
+ handle.dispatchEvent(
118
+ new PointerEvent("pointerdown", {
119
+ button: 0,
120
+ pointerId: 1,
121
+ cancelable: true,
122
+ bubbles: true,
123
+ composed: true
124
+ })
125
+ );
126
+ await elementUpdated(el);
127
+ expect(el.dragging, "it is dragging 1").to.be.true;
128
+ expect(pointerId, "2").to.equal(1);
129
+ handle.dispatchEvent(
130
+ new PointerEvent("pointerup", {
131
+ pointerId: 2,
132
+ cancelable: true,
133
+ bubbles: true,
134
+ composed: true
135
+ })
136
+ );
137
+ await elementUpdated(el);
138
+ expect(el.dragging).to.be.false;
139
+ expect(el.highlight).to.be.false;
140
+ expect(pointerId, "3").to.equal(2);
141
+ handle.dispatchEvent(
142
+ new PointerEvent("pointerdown", {
143
+ button: 0,
144
+ pointerId: 1,
145
+ cancelable: true,
146
+ bubbles: true,
147
+ composed: true
148
+ })
149
+ );
150
+ await elementUpdated(el);
151
+ expect(el.dragging, "it is dragging 2").to.be.true;
152
+ expect(pointerId, "4").to.equal(1);
153
+ handle.dispatchEvent(
154
+ new PointerEvent("pointercancel", {
155
+ pointerId: 3,
156
+ cancelable: true,
157
+ bubbles: true,
158
+ composed: true
159
+ })
160
+ );
161
+ await elementUpdated(el);
162
+ expect(el.dragging).to.be.false;
163
+ expect(pointerId, "5").to.equal(3);
164
+ });
165
+ it("will `trackPointerDown` on `#controls`", async () => {
166
+ let pointerId = -1;
167
+ const el = await fixture(html`
168
+ <sp-slider style="width: 500px" max="70"></sp-slider>
169
+ `);
170
+ await elementUpdated(el);
171
+ expect(el.value).to.equal(35);
172
+ const controls = el.shadowRoot.querySelector(
173
+ "#controls"
174
+ );
175
+ const handle = el.shadowRoot.querySelector(".handle");
176
+ el.track.setPointerCapture = (id) => pointerId = id;
177
+ el.track.releasePointerCapture = (id) => pointerId = id;
178
+ controls.dispatchEvent(
179
+ new PointerEvent("pointerdown", {
180
+ button: 1,
181
+ // account for 8px <body> margin by default
182
+ clientX: 9,
183
+ pointerId: 4,
184
+ bubbles: true,
185
+ cancelable: true
186
+ })
187
+ );
188
+ await elementUpdated(el);
189
+ expect(pointerId).to.equal(-1);
190
+ expect(el.value).to.equal(35);
191
+ expect(el.dragging, "handle is not yet being dragged").to.be.false;
192
+ controls.dispatchEvent(
193
+ new PointerEvent("pointerdown", {
194
+ button: 0,
195
+ // account for 8px <body> margin by default
196
+ clientX: 9,
197
+ pointerId: 4,
198
+ bubbles: true,
199
+ cancelable: true
200
+ })
201
+ );
202
+ await elementUpdated(el);
203
+ expect(pointerId).to.equal(4);
204
+ expect(el.value).to.equal(0);
205
+ expect(el.dragging, "handle is being dragged").to.be.true;
206
+ handle.dispatchEvent(
207
+ new PointerEvent("pointermove", {
208
+ button: 0,
209
+ // account for 8px <body> margin by default
210
+ clientX: 508,
211
+ pointerId: 4,
212
+ bubbles: true,
213
+ cancelable: true
214
+ })
215
+ );
216
+ await elementUpdated(el);
217
+ expect(el.dragging, "handle is still being dragged").to.be.true;
218
+ expect(pointerId).to.equal(4);
219
+ expect(el.value).to.equal(70);
220
+ handle.dispatchEvent(
221
+ new PointerEvent("pointerup", {
222
+ button: 0,
223
+ // account for 8px <body> margin by default
224
+ clientX: 9,
225
+ pointerId: 4,
226
+ bubbles: true,
227
+ cancelable: true
228
+ })
229
+ );
230
+ await elementUpdated(el);
231
+ expect(pointerId).to.equal(4);
232
+ expect(el.value).to.equal(70);
233
+ expect(el.dragging, "handle is no longer being dragged").to.be.false;
234
+ });
235
+ it("can be disabled", async () => {
236
+ let pointerId = -1;
237
+ const el = await fixture(html`
238
+ <sp-slider disabled></sp-slider>
239
+ `);
240
+ await elementUpdated(el);
241
+ expect(el.dragging).to.be.false;
242
+ expect(pointerId).to.equal(-1);
243
+ expect(el.value).to.equal(50);
244
+ const handle = el.shadowRoot.querySelector(".handle");
245
+ handle.setPointerCapture = (id) => pointerId = id;
246
+ handle.dispatchEvent(
247
+ new PointerEvent("pointerdown", {
248
+ button: 0,
249
+ pointerId: 1,
250
+ cancelable: true
251
+ })
252
+ );
253
+ await elementUpdated(el);
254
+ expect(el.dragging).to.be.false;
255
+ expect(pointerId).to.equal(-1);
256
+ const controls = el.shadowRoot.querySelector(
257
+ "#controls"
258
+ );
259
+ controls.dispatchEvent(
260
+ new PointerEvent("pointerdown", {
261
+ button: 0,
262
+ clientX: 50,
263
+ pointerId: 1,
264
+ cancelable: true
265
+ })
266
+ );
267
+ await elementUpdated(el);
268
+ expect(pointerId).to.equal(-1);
269
+ expect(el.value).to.equal(50);
270
+ });
271
+ it("accepts pointermove events", async () => {
272
+ const el = await fixture(html`
273
+ <sp-slider></sp-slider>
274
+ `);
275
+ await elementUpdated(el);
276
+ expect(el.value).to.equal(50);
277
+ const handle = el.shadowRoot.querySelector(".handle");
278
+ const handleBoundingRect = handle.getBoundingClientRect();
279
+ await sendMouse({
280
+ steps: [
281
+ {
282
+ type: "move",
283
+ position: [
284
+ handleBoundingRect.x + handleBoundingRect.width / 2,
285
+ handleBoundingRect.y + handleBoundingRect.height / 2
286
+ ]
287
+ },
288
+ {
289
+ type: "down"
290
+ }
291
+ ]
292
+ });
293
+ await elementUpdated(el);
294
+ expect(el.dragging, "is dragging").to.be.true;
295
+ expect(el.highlight, "not highlighted").to.be.false;
296
+ handle.dispatchEvent(
297
+ new PointerEvent("pointermove", {
298
+ clientX: 0,
299
+ cancelable: true,
300
+ bubbles: true,
301
+ composed: true
302
+ })
303
+ );
304
+ await elementUpdated(el);
305
+ expect(el.value).to.equal(0);
306
+ });
307
+ it("changes value when clicking on the track", async () => {
308
+ const el = await fixture(html`
309
+ <sp-slider style="width: 100px"></sp-slider>
310
+ `);
311
+ await elementUpdated(el);
312
+ expect(el.value).to.equal(50);
313
+ const track = el.shadowRoot.querySelector("#track");
314
+ const trackBoundingRect = track.getBoundingClientRect();
315
+ let pointerId = -1;
316
+ el.track.setPointerCapture = (id) => pointerId = id;
317
+ el.track.releasePointerCapture = (id) => pointerId = id;
318
+ track.dispatchEvent(
319
+ new PointerEvent("pointerdown", {
320
+ clientX: trackBoundingRect.x + trackBoundingRect.width / 2 + 10,
321
+ clientY: trackBoundingRect.y + trackBoundingRect.height / 2,
322
+ pointerId: 1,
323
+ cancelable: true,
324
+ bubbles: true,
325
+ composed: true,
326
+ button: 0
327
+ })
328
+ );
329
+ await elementUpdated(el);
330
+ track.dispatchEvent(
331
+ new PointerEvent("pointerup", {
332
+ pointerId: 1,
333
+ cancelable: true,
334
+ bubbles: true,
335
+ composed: true
336
+ })
337
+ );
338
+ await elementUpdated(el);
339
+ expect(el.value).to.equal(60);
340
+ expect(pointerId, "1").to.equal(1);
341
+ track.dispatchEvent(
342
+ new PointerEvent("pointerdown", {
343
+ clientX: trackBoundingRect.x + trackBoundingRect.width / 2 + 10,
344
+ clientY: trackBoundingRect.y + trackBoundingRect.height / 2,
345
+ pointerId: 2,
346
+ cancelable: true,
347
+ bubbles: true,
348
+ composed: true,
349
+ button: 0
350
+ })
351
+ );
352
+ track.dispatchEvent(
353
+ new PointerEvent("pointermove", {
354
+ clientX: trackBoundingRect.x + trackBoundingRect.width / 2 + 25,
355
+ clientY: trackBoundingRect.y + trackBoundingRect.height / 2,
356
+ pointerId: 2,
357
+ cancelable: true,
358
+ bubbles: true,
359
+ composed: true
360
+ })
361
+ );
362
+ await elementUpdated(el);
363
+ track.dispatchEvent(
364
+ new PointerEvent("pointerup", {
365
+ pointerId: 2,
366
+ cancelable: true,
367
+ bubbles: true,
368
+ composed: true
369
+ })
370
+ );
371
+ await elementUpdated(el);
372
+ expect(el.value).to.equal(75);
373
+ });
374
+ it("dispatches `input` of the animation frame", async () => {
375
+ const inputSpy = spy();
376
+ const changeSpy = spy();
377
+ const el = await fixture(html`
378
+ <sp-slider
379
+ value="50"
380
+ style="width: 100px"
381
+ @input=${(event) => {
382
+ inputSpy(event.target.value);
383
+ }}
384
+ @change=${(event) => {
385
+ changeSpy(event.target.value);
386
+ }}
387
+ ></sp-slider>
388
+ `);
389
+ await elementUpdated(el);
390
+ const handle = el.shadowRoot.querySelector(".handle");
391
+ const handleBoundingRect = handle.getBoundingClientRect();
392
+ expect(inputSpy.callCount, "start clean").to.equal(0);
393
+ expect(changeSpy.callCount, "start clean").to.equal(0);
394
+ let frames = 0;
395
+ let shouldCountFrames = true;
396
+ const countFrames = () => {
397
+ if (!shouldCountFrames) return;
398
+ frames += 1;
399
+ requestAnimationFrame(countFrames);
400
+ };
401
+ countFrames();
402
+ const toRight = [...Array(51).keys()].map((i) => ({
403
+ type: "move",
404
+ position: [9 + i, 30]
405
+ }));
406
+ const toLeft = toRight.slice(0, -1).reverse();
407
+ await sendMouse({
408
+ steps: [
409
+ {
410
+ type: "move",
411
+ position: [
412
+ handleBoundingRect.x + handleBoundingRect.width / 2,
413
+ handleBoundingRect.y + handleBoundingRect.height / 2
414
+ ]
415
+ },
416
+ {
417
+ type: "down"
418
+ },
419
+ ...toRight,
420
+ ...toLeft,
421
+ {
422
+ type: "up"
423
+ }
424
+ ]
425
+ });
426
+ shouldCountFrames = false;
427
+ expect(
428
+ inputSpy.callCount,
429
+ 'should not have more "input"s than frames'
430
+ ).to.lte(frames);
431
+ expect(changeSpy.callCount, "only one change").to.equal(1);
432
+ });
433
+ it("manages RTL when min != 0", async () => {
434
+ const el = await fixture(html`
435
+ <sp-slider min="1" max="11" dir="rtl"></sp-slider>
436
+ `);
437
+ await elementUpdated(el);
438
+ expect(el.value).to.equal(6);
439
+ const handle = el.shadowRoot.querySelector(".handle");
440
+ const handleBoundingRect = handle.getBoundingClientRect();
441
+ await sendMouse({
442
+ steps: [
443
+ {
444
+ type: "move",
445
+ position: [
446
+ handleBoundingRect.x + handleBoundingRect.width / 2,
447
+ handleBoundingRect.y + handleBoundingRect.height / 2
448
+ ]
449
+ },
450
+ {
451
+ type: "down"
452
+ }
453
+ ]
454
+ });
455
+ await elementUpdated(el);
456
+ expect(el.dragging, "is dragging").to.be.true;
457
+ expect(el.highlight, "not highlighted").to.be.false;
458
+ handle.dispatchEvent(
459
+ new PointerEvent("pointermove", {
460
+ clientX: 0,
461
+ cancelable: true,
462
+ bubbles: true,
463
+ composed: true
464
+ })
465
+ );
466
+ await elementUpdated(el);
467
+ expect(el.value).to.equal(11);
468
+ });
469
+ it("goes [disabled] while dragging", async () => {
470
+ const el = await fixture(html`
471
+ <sp-slider></sp-slider>
472
+ `);
473
+ await elementUpdated(el);
474
+ expect(el.value).to.equal(50);
475
+ const handle = el.shadowRoot.querySelector(".handle");
476
+ const handleBoundingRect = handle.getBoundingClientRect();
477
+ await sendMouse({
478
+ steps: [
479
+ {
480
+ type: "move",
481
+ position: [
482
+ handleBoundingRect.x + handleBoundingRect.width / 2,
483
+ handleBoundingRect.y + handleBoundingRect.height / 2
484
+ ]
485
+ },
486
+ {
487
+ type: "down"
488
+ }
489
+ ]
490
+ });
491
+ await elementUpdated(el);
492
+ expect(el.dragging, "is dragging").to.be.true;
493
+ expect(el.highlight, "not highlighted").to.be.false;
494
+ expect(el.value).to.equal(50);
495
+ const inputEvent = oneEvent(el, "input");
496
+ await sendMouse({
497
+ steps: [
498
+ {
499
+ type: "move",
500
+ position: [
501
+ handleBoundingRect.x + handleBoundingRect.width / 2 + 100,
502
+ handleBoundingRect.y + handleBoundingRect.height / 2
503
+ ]
504
+ }
505
+ ]
506
+ });
507
+ await inputEvent;
508
+ expect(el.value).to.equal(63);
509
+ el.disabled = true;
510
+ await elementUpdated(el);
511
+ expect(el.dragging, "is dragging").to.be.false;
512
+ expect(el.highlight, "not highlighted").to.be.false;
513
+ await sendMouse({
514
+ steps: [
515
+ {
516
+ type: "move",
517
+ position: [
518
+ 0,
519
+ handleBoundingRect.top + handleBoundingRect.height / 2
520
+ ]
521
+ }
522
+ ]
523
+ });
524
+ expect(el.value).to.equal(63);
525
+ });
526
+ it("accepts pointermove events in separate interactions", async () => {
527
+ let pointerId = -1;
528
+ const el = await fixture(html`
529
+ <sp-slider style="width: 100px"></sp-slider>
530
+ `);
531
+ await elementUpdated(el);
532
+ expect(el.value, "initial").to.equal(50);
533
+ const handle = el.shadowRoot.querySelector(".handle");
534
+ el.track.setPointerCapture = (id) => pointerId = id;
535
+ el.track.releasePointerCapture = (id) => pointerId = id;
536
+ handle.dispatchEvent(
537
+ new PointerEvent("pointerdown", {
538
+ clientX: 58,
539
+ cancelable: true,
540
+ button: 0,
541
+ pointerId: 100,
542
+ composed: true,
543
+ bubbles: true
544
+ })
545
+ );
546
+ await elementUpdated(el);
547
+ await nextFrame();
548
+ handle.dispatchEvent(
549
+ new PointerEvent("pointermove", {
550
+ clientX: 58,
551
+ cancelable: true,
552
+ composed: true,
553
+ bubbles: true
554
+ })
555
+ );
556
+ await elementUpdated(el);
557
+ await nextFrame();
558
+ expect(el.value, "first pointerdown").to.equal(50);
559
+ expect(el.dragging, "is dragging").to.be.true;
560
+ expect(el.classList.contains("handle-highlight"), "not highlighted").to.be.false;
561
+ expect(pointerId).to.equal(100);
562
+ handle.dispatchEvent(
563
+ new PointerEvent("pointermove", {
564
+ clientX: 0,
565
+ cancelable: true,
566
+ composed: true,
567
+ bubbles: true
568
+ })
569
+ );
570
+ await elementUpdated(el);
571
+ await nextFrame();
572
+ expect(el.value, "first pointermove").to.equal(0);
573
+ handle.dispatchEvent(
574
+ new PointerEvent("pointerup", {
575
+ clientX: 0,
576
+ cancelable: true,
577
+ composed: true,
578
+ bubbles: true
579
+ })
580
+ );
581
+ await elementUpdated(el);
582
+ expect(el.value, "first pointerup").to.equal(0);
583
+ expect(el.dragging, "is dragging").to.be.false;
584
+ handle.dispatchEvent(
585
+ new PointerEvent("pointerdown", {
586
+ clientX: 58,
587
+ cancelable: true,
588
+ button: 0,
589
+ composed: true,
590
+ bubbles: true
591
+ })
592
+ );
593
+ await elementUpdated(el);
594
+ handle.dispatchEvent(
595
+ new PointerEvent("pointermove", {
596
+ clientX: 58,
597
+ cancelable: true,
598
+ composed: true,
599
+ bubbles: true
600
+ })
601
+ );
602
+ await elementUpdated(el);
603
+ await nextFrame();
604
+ expect(el.value, "second pointerdown").to.equal(50);
605
+ expect(el.dragging, "is dragging").to.be.true;
606
+ expect(el.classList.contains("handle-highlight"), "not highlighted").to.be.false;
607
+ handle.dispatchEvent(
608
+ new PointerEvent("pointermove", {
609
+ clientX: 0,
610
+ cancelable: true,
611
+ composed: true,
612
+ bubbles: true
613
+ })
614
+ );
615
+ await elementUpdated(el);
616
+ await nextFrame();
617
+ expect(el.value, "second pointermove").to.equal(0);
618
+ handle.dispatchEvent(
619
+ new PointerEvent("pointerup", {
620
+ clientX: 0,
621
+ cancelable: true,
622
+ composed: true,
623
+ bubbles: true
624
+ })
625
+ );
626
+ await elementUpdated(el);
627
+ expect(el.value, "second pointerup").to.equal(0);
628
+ expect(el.dragging, "is dragging").to.be.false;
629
+ });
630
+ it("accepts pointermove events - [step=0]", async () => {
631
+ const el = await fixture(html`
632
+ <sp-slider step="0" max="20" style="width: 500px; float: left;">
633
+ Step = 0
634
+ </sp-slider>
635
+ `);
636
+ await elementUpdated(el);
637
+ await nextFrame();
638
+ await nextFrame();
639
+ expect(el.value).to.equal(10);
640
+ const handle = el.shadowRoot.querySelector(".handle");
641
+ const handleBoundingRect = handle.getBoundingClientRect();
642
+ const position = [
643
+ handleBoundingRect.x + handleBoundingRect.width / 2,
644
+ handleBoundingRect.y + handleBoundingRect.height / 2
645
+ ];
646
+ await sendMouse({
647
+ steps: [
648
+ {
649
+ type: "move",
650
+ position
651
+ },
652
+ {
653
+ type: "down"
654
+ }
655
+ ]
656
+ });
657
+ await elementUpdated(el);
658
+ expect(el.highlight, "with no highlight").to.be.false;
659
+ expect(el.dragging, "dragging").to.be.true;
660
+ let inputEvent = oneEvent(el, "input");
661
+ await sendMouse({
662
+ steps: [
663
+ {
664
+ type: "move",
665
+ position: [
666
+ 200,
667
+ handleBoundingRect.y + handleBoundingRect.height + 100
668
+ ]
669
+ }
670
+ ]
671
+ });
672
+ await inputEvent;
673
+ await nextFrame();
674
+ expect(el.value).to.equal(8);
675
+ inputEvent = oneEvent(el, "input");
676
+ await sendMouse({
677
+ steps: [
678
+ {
679
+ type: "move",
680
+ position: [125, position[1]]
681
+ }
682
+ ]
683
+ });
684
+ await inputEvent;
685
+ expect(el.value).to.equal(5);
686
+ });
687
+ it("will not pointermove unless `pointerdown`", async () => {
688
+ const el = await fixture(html`
689
+ <sp-slider></sp-slider>
690
+ `);
691
+ await elementUpdated(el);
692
+ expect(el.value).to.equal(50);
693
+ expect(el.dragging).to.be.false;
694
+ const handle = el.shadowRoot.querySelector(".handle");
695
+ handle.dispatchEvent(
696
+ new PointerEvent("pointermove", {
697
+ clientX: 0,
698
+ cancelable: true
699
+ })
700
+ );
701
+ await nextFrame();
702
+ expect(el.value).to.equal(50);
703
+ });
704
+ it("responds to input events on the <input/> element", async () => {
705
+ const el = await fixture(html`
706
+ <sp-slider></sp-slider>
707
+ `);
708
+ await elementUpdated(el);
709
+ expect(el.value).to.equal(50);
710
+ const input = el.shadowRoot.querySelector(".input");
711
+ input.value = "0";
712
+ input.dispatchEvent(new Event("change"));
713
+ expect(el.value).to.equal(0);
714
+ });
715
+ it("accepts variants", async () => {
716
+ const el = await fixture(html`
717
+ <sp-slider variant="tick"></sp-slider>
718
+ `);
719
+ await elementUpdated(el);
720
+ expect(el.variant).to.equal("tick");
721
+ expect(el.getAttribute("variant")).to.equal("tick");
722
+ el.variant = "ramp";
723
+ await elementUpdated(el);
724
+ expect(el.variant).to.equal("ramp");
725
+ expect(el.getAttribute("variant")).to.equal("ramp");
726
+ el.setAttribute("variant", "filled");
727
+ await elementUpdated(el);
728
+ expect(el.variant).to.equal("filled");
729
+ expect(el.getAttribute("variant")).to.equal("filled");
730
+ el.removeAttribute("variant");
731
+ await elementUpdated(el);
732
+ expect(el.variant).to.equal("");
733
+ expect(el.hasAttribute("variant")).to.be.false;
734
+ });
735
+ it("validates variants", async () => {
736
+ const el = await fixture(html`
737
+ <sp-slider variant="other"></sp-slider>
738
+ `);
739
+ await elementUpdated(el);
740
+ expect(el.variant).to.equal("");
741
+ expect(el.hasAttribute("variant")).to.be.false;
742
+ el.variant = "tick";
743
+ await elementUpdated(el);
744
+ expect(el.variant).to.equal("tick");
745
+ expect(el.getAttribute("variant")).to.equal("tick");
746
+ el.variant = "tick";
747
+ await elementUpdated(el);
748
+ expect(el.variant).to.equal("tick");
749
+ expect(el.getAttribute("variant")).to.equal("tick");
750
+ });
751
+ it("renders fill from the centerPoint of the track when fill-start has no value", async () => {
752
+ const el = await fixture(html`
753
+ <sp-slider
754
+ max="20"
755
+ variant="filled"
756
+ fill-start
757
+ min="0"
758
+ value="10"
759
+ step="1"
760
+ ></sp-slider>
761
+ `);
762
+ await elementUpdated(el);
763
+ await nextFrame();
764
+ await nextFrame();
765
+ const fillElement = el.shadowRoot.querySelector(
766
+ ".fill"
767
+ );
768
+ expect(fillElement).to.exist;
769
+ expect(fillElement.style.left).to.equal("50%");
770
+ expect(fillElement.style.width).to.equal("0%");
771
+ expect(el.values).to.deep.equal({ value: 10 });
772
+ });
773
+ it("renders fill from value when fill-start has value=0", async () => {
774
+ const el = await fixture(html`
775
+ <sp-slider
776
+ max="150"
777
+ variant="filled"
778
+ fill-start="0"
779
+ min="-50"
780
+ value="25"
781
+ step="1"
782
+ ></sp-slider>
783
+ `);
784
+ await elementUpdated(el);
785
+ await nextFrame();
786
+ await nextFrame();
787
+ const fillElement = el.shadowRoot.querySelector(
788
+ ".fill"
789
+ );
790
+ expect(fillElement).to.exist;
791
+ expect(fillElement.style.left).to.equal("25%");
792
+ expect(fillElement.style.width).to.equal("12.5%");
793
+ expect(el.values).to.deep.equal({ value: 25 });
794
+ });
795
+ it("renders fill from fill-start point", async () => {
796
+ const el = await fixture(html`
797
+ <sp-slider max="100" fill-start="15" min="0" value="10"></sp-slider>
798
+ `);
799
+ await elementUpdated(el);
800
+ await nextFrame();
801
+ await nextFrame();
802
+ const fillElement = el.shadowRoot.querySelector(
803
+ ".fill"
804
+ );
805
+ expect(fillElement).to.exist;
806
+ expect(fillElement.style.left).to.equal("10%");
807
+ expect(fillElement.style.width).to.equal("5%");
808
+ expect(el.values).to.deep.equal({ value: 10 });
809
+ const handle = el.shadowRoot.querySelector(".handle");
810
+ const handleBoundingRect = handle.getBoundingClientRect();
811
+ const position = [
812
+ handleBoundingRect.x + handleBoundingRect.width / 2,
813
+ handleBoundingRect.y + handleBoundingRect.height / 2
814
+ ];
815
+ await sendMouse({
816
+ steps: [
817
+ {
818
+ type: "move",
819
+ position
820
+ },
821
+ {
822
+ type: "down"
823
+ }
824
+ ]
825
+ });
826
+ await elementUpdated(el);
827
+ await sendMouse({
828
+ steps: [
829
+ {
830
+ type: "move",
831
+ position: [
832
+ 200,
833
+ handleBoundingRect.y + handleBoundingRect.height + 100
834
+ ]
835
+ }
836
+ ]
837
+ });
838
+ await nextFrame();
839
+ expect(el.value).to.equal(24);
840
+ });
841
+ it("renders fill from fill-start point with given normalization function", async () => {
842
+ const el = await fixture(html`
843
+ <sp-slider
844
+ max="100"
845
+ fill-start="0"
846
+ min="-50"
847
+ value="-25"
848
+ .normalization=${{
849
+ toNormalized: (value) => {
850
+ if (value === 0) return 0.5;
851
+ return value < 0 ? 0.5 - value / -50 * 0.5 : 0.5 + value / 100 * 0.5;
852
+ },
853
+ fromNormalized: (value) => {
854
+ if (value === 0.5) return 0;
855
+ return value < 0.5 ? (1 - value / 0.5) * -50 : (value - 0.5) / 0.5 * 100;
856
+ }
857
+ }}
858
+ ></sp-slider>
859
+ `);
860
+ await elementUpdated(el);
861
+ await nextFrame();
862
+ await nextFrame();
863
+ const fillElement = el.shadowRoot.querySelector(
864
+ ".fill"
865
+ );
866
+ expect(fillElement).to.exist;
867
+ expect(fillElement.style.left).to.equal("25%");
868
+ expect(fillElement.style.width).to.equal("25%");
869
+ expect(el.values).to.deep.equal({ value: -25 });
870
+ });
871
+ it("has a `focusElement`", async () => {
872
+ const el = await fixture(html`
873
+ <sp-slider></sp-slider>
874
+ `);
875
+ await elementUpdated(el);
876
+ const input = el.focusElement;
877
+ expect(input).to.not.be.undefined;
878
+ expect(input.type).to.equal("range");
879
+ });
880
+ it("displays result of getAriaValueText", async () => {
881
+ const el = await fixture(html`
882
+ <sp-slider
883
+ value="50"
884
+ min="0"
885
+ max="100"
886
+ .getAriaHandleText=${(value) => `${value}%`}
887
+ ></sp-slider>
888
+ `);
889
+ await elementUpdated(el);
890
+ const input = el.focusElement;
891
+ expect(input.getAttribute("aria-valuetext")).to.equal("50%");
892
+ el.value = 100;
893
+ await elementUpdated(el);
894
+ expect(input.getAttribute("aria-valuetext")).to.equal("100%");
895
+ });
896
+ it("displays Intl.formatNumber results", async () => {
897
+ const el = await fixture(html`
898
+ <sp-slider
899
+ value=".5"
900
+ min="0"
901
+ max="1"
902
+ .formatOptions=${{ style: "percent" }}
903
+ ></sp-slider>
904
+ `);
905
+ await elementUpdated(el);
906
+ const input = el.focusElement;
907
+ expect(input.getAttribute("aria-valuetext")).to.equal("50%");
908
+ el.value = 100;
909
+ await elementUpdated(el);
910
+ expect(input.getAttribute("aria-valuetext")).to.equal("100%");
911
+ });
912
+ it("obeys language property", async () => {
913
+ const [languageContext, updateLanguage] = createLanguageContext("de");
914
+ let el = await fixture(html`
915
+ <sp-slider
916
+ value="2.44"
917
+ min="0"
918
+ max="10"
919
+ step="0.01"
920
+ @sp-language-context=${languageContext}
921
+ .formatOptions=${{ maximumFractionDigits: 2 }}
922
+ ></sp-slider>
923
+ `);
924
+ await elementUpdated(el);
925
+ let input = el.focusElement;
926
+ expect(
927
+ input.getAttribute("aria-valuetext"),
928
+ "First German number"
929
+ ).to.equal("2,44");
930
+ updateLanguage("en");
931
+ await elementUpdated(el);
932
+ expect(
933
+ input.getAttribute("aria-valuetext"),
934
+ "First English number"
935
+ ).to.equal("2.44");
936
+ updateLanguage("de");
937
+ el = await fixture(html`
938
+ <sp-slider min="0" max="10" @sp-language-context=${languageContext}>
939
+ <sp-slider-handle
940
+ slot="handle"
941
+ step="0.01"
942
+ value="2.44"
943
+ .formatOptions=${{ maximumFractionDigits: 2 }}
944
+ @sp-language-context=${languageContext}
945
+ ></sp-slider-handle>
946
+ </sp-slider>
947
+ `);
948
+ await elementUpdated(el);
949
+ input = el.focusElement;
950
+ expect(
951
+ input.getAttribute("aria-valuetext"),
952
+ "Second German number"
953
+ ).to.equal("2,44");
954
+ updateLanguage("en");
955
+ await elementUpdated(el);
956
+ expect(
957
+ input.getAttribute("aria-valuetext"),
958
+ "Second English number"
959
+ ).to.equal("2.44");
960
+ });
961
+ it("uses fallback ariaValueText", async () => {
962
+ const el = await fixture(html`
963
+ <sp-slider value="50" min="0" max="100"></sp-slider>
964
+ `);
965
+ await elementUpdated(el);
966
+ el.getAriaValueText = false;
967
+ const input = el.focusElement;
968
+ await elementUpdated(el);
969
+ expect(input.getAttribute("aria-valuetext")).to.equal("50");
970
+ });
971
+ it("supports units not included in Intl.NumberFormatOptions", async () => {
972
+ let el = await fixture(html`
973
+ <sp-slider
974
+ value="50"
975
+ min="0"
976
+ max="100"
977
+ format-options='{"style": "unit", "unit": "px"}'
978
+ ></sp-slider>
979
+ `);
980
+ await elementUpdated(el);
981
+ const input = el.focusElement;
982
+ await elementUpdated(el);
983
+ expect(input.getAttribute("aria-valuetext")).to.equal("50px");
984
+ el = await fixture(html`
985
+ <sp-slider
986
+ value="5"
987
+ step="1"
988
+ min="0"
989
+ max="255"
990
+ format-options='{"style": "unit", "unit": "px"}'
991
+ >
992
+ <sp-slider-handle
993
+ slot="handle"
994
+ name="min"
995
+ label="Minimum"
996
+ value="5"
997
+ ></sp-slider-handle>
998
+ <sp-slider-handle
999
+ slot="handle"
1000
+ name="max"
1001
+ label="Maximum"
1002
+ value="250"
1003
+ ></sp-slider-handle>
1004
+ </sp-slider>
1005
+ `);
1006
+ await elementUpdated(el);
1007
+ let shadowRoot = el.shadowRoot;
1008
+ expect(shadowRoot.querySelector('input#input-0[aria-valuetext="5px"]')).to.exist;
1009
+ expect(
1010
+ shadowRoot.querySelector('input#input-1[aria-valuetext="250px"]')
1011
+ ).to.exist;
1012
+ el = await fixture(html`
1013
+ <sp-slider value="5" step="1" min="0" max="255">
1014
+ <sp-slider-handle
1015
+ slot="handle"
1016
+ name="min"
1017
+ label="Minimum"
1018
+ value="5"
1019
+ format-options='{"style": "unit", "unit": "px"}'
1020
+ ></sp-slider-handle>
1021
+ <sp-slider-handle
1022
+ slot="handle"
1023
+ name="max"
1024
+ label="Maximum"
1025
+ value="250"
1026
+ format-options='{"style": "unit", "unit": "px"}'
1027
+ ></sp-slider-handle>
1028
+ </sp-slider>
1029
+ `);
1030
+ await elementUpdated(el);
1031
+ shadowRoot = el.shadowRoot;
1032
+ expect(shadowRoot.querySelector('input#input-0[aria-valuetext="5px"]')).to.exist;
1033
+ expect(
1034
+ shadowRoot.querySelector('input#input-1[aria-valuetext="250px"]')
1035
+ ).to.exist;
1036
+ });
1037
+ it("accepts min/max/value in the same timing", async () => {
1038
+ const el = await fixture(html`
1039
+ <sp-slider></sp-slider>
1040
+ `);
1041
+ await elementUpdated(el);
1042
+ expect(el.value).to.equal(50);
1043
+ el.min = 0;
1044
+ el.max = 200;
1045
+ el.value = 200;
1046
+ await elementUpdated(el);
1047
+ expect(el.value).to.equal(200);
1048
+ el.value = 500;
1049
+ el.min = 0;
1050
+ el.max = 500;
1051
+ await elementUpdated(el);
1052
+ expect(el.value).to.equal(500);
1053
+ el.value = -100;
1054
+ el.min = -100;
1055
+ el.max = 500;
1056
+ await elementUpdated(el);
1057
+ expect(el.value).to.equal(-100);
1058
+ });
1059
+ it("returns values for handles", async () => {
1060
+ let el = await fixture(html`
1061
+ <sp-slider>
1062
+ <sp-slider-handle
1063
+ slot="handle"
1064
+ name="a"
1065
+ min="0"
1066
+ value="10"
1067
+ ></sp-slider-handle>
1068
+ <sp-slider-handle
1069
+ id="middle-handle"
1070
+ slot="handle"
1071
+ name="b"
1072
+ value="20"
1073
+ ></sp-slider-handle>
1074
+ <sp-slider-handle
1075
+ slot="handle"
1076
+ name="c"
1077
+ value="30"
1078
+ max="100"
1079
+ ></sp-slider-handle>
1080
+ </sp-slider>
1081
+ `);
1082
+ await elementUpdated(el);
1083
+ expect(el.values).to.deep.equal({ a: 10, b: 20, c: 30 });
1084
+ const middleHandle = el.querySelector("#middle-handle");
1085
+ middleHandle.value = 22;
1086
+ await elementUpdated(el);
1087
+ expect(el.values).to.deep.equal({ a: 10, b: 22, c: 30 });
1088
+ el = await fixture(html`
1089
+ <sp-slider value="10" min="0" max="100"></sp-slider>
1090
+ `);
1091
+ expect(el.values).to.deep.equal({ value: 10 });
1092
+ el = await fixture(html`
1093
+ <sp-slider min="0" max="100">
1094
+ <sp-slider-handle slot="handle" value="10"></sp-slider-handle>
1095
+ </sp-slider>
1096
+ `);
1097
+ expect(el.values).to.deep.equal({ handle1: 10 });
1098
+ });
1099
+ it("clamps values for multi-handle slider", async () => {
1100
+ const el = await fixture(html`
1101
+ <sp-slider min="0" max="100">
1102
+ <sp-slider-handle
1103
+ id="first-handle"
1104
+ max="next"
1105
+ slot="handle"
1106
+ name="a"
1107
+ value="10"
1108
+ ></sp-slider-handle>
1109
+ <sp-slider-handle
1110
+ id="middle-handle"
1111
+ min="previous"
1112
+ max="next"
1113
+ slot="handle"
1114
+ name="b"
1115
+ value="20"
1116
+ ></sp-slider-handle>
1117
+ <sp-slider-handle
1118
+ id="last-handle"
1119
+ min="previous"
1120
+ slot="handle"
1121
+ name="c"
1122
+ value="30"
1123
+ ></sp-slider-handle>
1124
+ </sp-slider>
1125
+ `);
1126
+ await elementUpdated(el);
1127
+ expect(el.values).to.deep.equal({ a: 10, b: 20, c: 30 });
1128
+ const firstHandle = el.querySelector("#first-handle");
1129
+ const middleHandle = el.querySelector("#middle-handle");
1130
+ const lastHandle = el.querySelector("#last-handle");
1131
+ firstHandle.value = 25;
1132
+ await elementUpdated(el);
1133
+ expect(el.values).to.deep.equal({ a: 20, b: 20, c: 30 });
1134
+ firstHandle.value = 10;
1135
+ await elementUpdated(el);
1136
+ middleHandle.value = 5;
1137
+ await elementUpdated(el);
1138
+ expect(el.values).to.deep.equal({ a: 10, b: 10, c: 30 });
1139
+ lastHandle.value = 11;
1140
+ await elementUpdated(el);
1141
+ expect(el.values).to.deep.equal({ a: 10, b: 10, c: 11 });
1142
+ lastHandle.value = 7;
1143
+ await elementUpdated(el);
1144
+ expect(el.values).to.deep.equal({ a: 10, b: 10, c: 10 });
1145
+ });
1146
+ it('warns in Dev Mode when `min="previous"` is leveraged on first handle', async () => {
1147
+ const consoleWarnStub = stub(console, "warn");
1148
+ window.__swc.issuedWarnings = /* @__PURE__ */ new Set();
1149
+ const el = await fixture(html`
1150
+ <sp-slider min="0" max="100">
1151
+ <sp-slider-handle
1152
+ id="first-handle"
1153
+ min="previous"
1154
+ max="next"
1155
+ slot="handle"
1156
+ name="a"
1157
+ value="10"
1158
+ ></sp-slider-handle>
1159
+ <sp-slider-handle
1160
+ id="middle-handle"
1161
+ min="previous"
1162
+ max="next"
1163
+ slot="handle"
1164
+ name="b"
1165
+ value="20"
1166
+ ></sp-slider-handle>
1167
+ <sp-slider-handle
1168
+ id="last-handle"
1169
+ min="previous"
1170
+ slot="handle"
1171
+ name="c"
1172
+ value="30"
1173
+ ></sp-slider-handle>
1174
+ </sp-slider>
1175
+ `);
1176
+ await elementUpdated(el);
1177
+ expect(consoleWarnStub.called).to.be.true;
1178
+ const spyCall = consoleWarnStub.getCall(0);
1179
+ expect(
1180
+ spyCall.args.at(0).includes("previous"),
1181
+ 'confirm "previous" in message'
1182
+ ).to.be.true;
1183
+ expect(spyCall.args.at(-1), "confirm `data` shape").to.deep.equal({
1184
+ data: {
1185
+ localName: "sp-slider",
1186
+ type: "api",
1187
+ level: "default"
1188
+ }
1189
+ });
1190
+ consoleWarnStub.restore();
1191
+ });
1192
+ it('warns in Dev Mode when `max="next"` is leveraged on last handle', async () => {
1193
+ const consoleWarnStub = stub(console, "warn");
1194
+ window.__swc.issuedWarnings = /* @__PURE__ */ new Set();
1195
+ const el = await fixture(html`
1196
+ <sp-slider min="0" max="100">
1197
+ <sp-slider-handle
1198
+ id="first-handle"
1199
+ max="next"
1200
+ slot="handle"
1201
+ name="a"
1202
+ value="10"
1203
+ ></sp-slider-handle>
1204
+ <sp-slider-handle
1205
+ id="middle-handle"
1206
+ min="previous"
1207
+ max="next"
1208
+ slot="handle"
1209
+ name="b"
1210
+ value="20"
1211
+ ></sp-slider-handle>
1212
+ <sp-slider-handle
1213
+ id="last-handle"
1214
+ min="previous"
1215
+ max="next"
1216
+ slot="handle"
1217
+ name="c"
1218
+ value="30"
1219
+ ></sp-slider-handle>
1220
+ </sp-slider>
1221
+ `);
1222
+ await elementUpdated(el);
1223
+ expect(consoleWarnStub.called).to.be.true;
1224
+ const spyCall = consoleWarnStub.getCall(0);
1225
+ expect(spyCall.args.at(0).includes("next"), 'confirm "next" in message').to.be.true;
1226
+ expect(spyCall.args.at(-1), "confirm `data` shape").to.deep.equal({
1227
+ data: {
1228
+ localName: "sp-slider",
1229
+ type: "api",
1230
+ level: "default"
1231
+ }
1232
+ });
1233
+ consoleWarnStub.restore();
1234
+ });
1235
+ it("builds both handles from a <template>", async () => {
1236
+ var _a;
1237
+ const template = document.createElement("template");
1238
+ template.innerHTML = `
1239
+ <sp-slider variant="range" step="1" id="price" name="price" label="Max Price" min="35425" max="86610">
1240
+ <sp-slider-handle slot="handle" name="min" label="Minimum" max="next" value="35425"></sp-slider-handle>
1241
+ <sp-slider-handle slot="handle" name="max" label="Maximum" min="previous" value="86610"></sp-slider-handle>
1242
+ </sp-slider>
1243
+ `;
1244
+ const el = await fixture(html`
1245
+ <div></div>
1246
+ `);
1247
+ el.appendChild(template.content.cloneNode(true));
1248
+ await waitUntil(() => {
1249
+ var _a2;
1250
+ return ((_a2 = el.querySelector("sp-slider")) == null ? void 0 : _a2.shadowRoot) != null;
1251
+ });
1252
+ await nextFrame();
1253
+ const createdHandles = ((_a = el.querySelector("sp-slider")) == null ? void 0 : _a.shadowRoot.querySelectorAll(".handle")) || [];
1254
+ expect(createdHandles).to.have.lengthOf(2);
1255
+ });
1256
+ it("enforces next/previous max/min", async () => {
1257
+ let el = await fixture(html`
1258
+ <sp-slider min="0" max="100">
1259
+ <sp-slider-handle
1260
+ id="first-handle"
1261
+ max="next"
1262
+ slot="handle"
1263
+ name="a"
1264
+ value="10"
1265
+ ></sp-slider-handle>
1266
+ <sp-slider-handle
1267
+ id="middle-handle"
1268
+ min="previous"
1269
+ max="next"
1270
+ slot="handle"
1271
+ name="b"
1272
+ value="20"
1273
+ ></sp-slider-handle>
1274
+ <sp-slider-handle
1275
+ id="last-handle"
1276
+ min="previous"
1277
+ slot="handle"
1278
+ name="c"
1279
+ value="30"
1280
+ ></sp-slider-handle>
1281
+ </sp-slider>
1282
+ `);
1283
+ await elementUpdated(el);
1284
+ expect(el.values).to.deep.equal({ a: 10, b: 20, c: 30 });
1285
+ let firstHandle = el.querySelector("#first-handle");
1286
+ let lastHandle = el.querySelector("#last-handle");
1287
+ let firstInput = el.shadowRoot.querySelector(
1288
+ '.handle[name="a"] > input'
1289
+ );
1290
+ let middleInput = el.shadowRoot.querySelector(
1291
+ '.handle[name="b"] > input'
1292
+ );
1293
+ let lastInput = el.shadowRoot.querySelector(
1294
+ '.handle[name="c"] > input'
1295
+ );
1296
+ expect(firstInput.min).to.equal("0");
1297
+ expect(firstInput.max).to.equal("20");
1298
+ expect(middleInput.min).to.equal("10");
1299
+ expect(middleInput.max).to.equal("30");
1300
+ expect(lastInput.min).to.equal("20");
1301
+ expect(lastInput.max).to.equal("100");
1302
+ firstHandle.value = 15;
1303
+ lastHandle.value = 85;
1304
+ await elementUpdated(el);
1305
+ await elementUpdated(el);
1306
+ expect(firstInput.min).to.equal("0");
1307
+ expect(firstInput.max).to.equal("20");
1308
+ expect(middleInput.min).to.equal("15");
1309
+ expect(middleInput.max).to.equal("85");
1310
+ expect(lastInput.min).to.equal("20");
1311
+ expect(lastInput.max).to.equal("100");
1312
+ el = await fixture(html`
1313
+ <sp-slider>
1314
+ <sp-slider-handle
1315
+ id="first-handle"
1316
+ min="0"
1317
+ max="next"
1318
+ slot="handle"
1319
+ name="a"
1320
+ value="10"
1321
+ ></sp-slider-handle>
1322
+ <sp-slider-handle
1323
+ id="middle-handle"
1324
+ min="previous"
1325
+ max="next"
1326
+ slot="handle"
1327
+ name="b"
1328
+ value="20"
1329
+ ></sp-slider-handle>
1330
+ <sp-slider-handle
1331
+ id="last-handle"
1332
+ min="previous"
1333
+ max="100"
1334
+ slot="handle"
1335
+ name="c"
1336
+ value="30"
1337
+ ></sp-slider-handle>
1338
+ </sp-slider>
1339
+ `);
1340
+ firstInput = el.shadowRoot.querySelector(
1341
+ '.handle[name="a"] > input'
1342
+ );
1343
+ middleInput = el.shadowRoot.querySelector(
1344
+ '.handle[name="b"] > input'
1345
+ );
1346
+ lastInput = el.shadowRoot.querySelector(
1347
+ '.handle[name="c"] > input'
1348
+ );
1349
+ expect(firstInput.min).to.equal("0");
1350
+ expect(firstInput.max).to.equal("20");
1351
+ expect(middleInput.min).to.equal("10");
1352
+ expect(middleInput.max).to.equal("30");
1353
+ expect(lastInput.min).to.equal("20");
1354
+ expect(lastInput.max).to.equal("100");
1355
+ firstHandle = el.querySelector("#first-handle");
1356
+ lastHandle = el.querySelector("#last-handle");
1357
+ firstHandle.min = 5;
1358
+ lastHandle.max = 95;
1359
+ await elementUpdated(el);
1360
+ await elementUpdated(el);
1361
+ expect(firstInput.min).to.equal("5");
1362
+ expect(firstInput.max).to.equal("20");
1363
+ expect(lastInput.min).to.equal("20");
1364
+ expect(lastInput.max).to.equal("95");
1365
+ });
1366
+ it("sends keyboard events to active handle", async () => {
1367
+ const el = await fixture(html`
1368
+ <sp-slider step="1" min="0" max="100">
1369
+ <sp-slider-handle
1370
+ id="first-handle"
1371
+ max="next"
1372
+ slot="handle"
1373
+ name="a"
1374
+ value="10"
1375
+ ></sp-slider-handle>
1376
+ <sp-slider-handle
1377
+ id="middle-handle"
1378
+ min="previous"
1379
+ max="next"
1380
+ slot="handle"
1381
+ name="b"
1382
+ value="20"
1383
+ ></sp-slider-handle>
1384
+ <sp-slider-handle
1385
+ id="last-handle"
1386
+ min="previous"
1387
+ slot="handle"
1388
+ name="c"
1389
+ value="30"
1390
+ ></sp-slider-handle>
1391
+ </sp-slider>
1392
+ `);
1393
+ await elementUpdated(el);
1394
+ expect(el.values).to.deep.equal({ a: 10, b: 20, c: 30 });
1395
+ const lastHandle = el.querySelector("#last-handle");
1396
+ lastHandle.focus();
1397
+ await sendKeys({
1398
+ press: "ArrowDown"
1399
+ });
1400
+ await elementUpdated(el);
1401
+ expect(el.values).to.deep.equal({ a: 10, b: 20, c: 29 });
1402
+ });
1403
+ it("resets to default value on double click after moving pointer", async () => {
1404
+ const inputSpy = spy();
1405
+ const changeSpy = spy();
1406
+ const el = await fixture(html`
1407
+ <sp-slider
1408
+ style="width: 100px"
1409
+ value="50"
1410
+ default-value="50"
1411
+ @input=${(event) => {
1412
+ inputSpy(event.target.value);
1413
+ }}
1414
+ @change=${(event) => {
1415
+ changeSpy(event.target.value);
1416
+ }}
1417
+ ></sp-slider>
1418
+ `);
1419
+ await elementUpdated(el);
1420
+ expect(el.value, "initial").to.equal(50);
1421
+ const handle = el.shadowRoot.querySelector(".handle");
1422
+ const handleBoundingRect = handle.getBoundingClientRect();
1423
+ const position = [
1424
+ handleBoundingRect.x + handleBoundingRect.width / 2,
1425
+ handleBoundingRect.y + handleBoundingRect.height / 2
1426
+ ];
1427
+ await sendMouse({
1428
+ steps: [
1429
+ {
1430
+ type: "move",
1431
+ position
1432
+ },
1433
+ {
1434
+ type: "down"
1435
+ }
1436
+ ]
1437
+ });
1438
+ await elementUpdated(el);
1439
+ await sendMouse({
1440
+ steps: [
1441
+ {
1442
+ type: "move",
1443
+ position: [
1444
+ 150,
1445
+ handleBoundingRect.y + handleBoundingRect.height + 100
1446
+ ]
1447
+ },
1448
+ {
1449
+ type: "up"
1450
+ }
1451
+ ]
1452
+ });
1453
+ await elementUpdated(el);
1454
+ expect(el.value).to.equal(100);
1455
+ inputSpy.resetHistory();
1456
+ changeSpy.resetHistory();
1457
+ handle.dispatchEvent(
1458
+ new PointerEvent("dblclick", {
1459
+ clientX: 0,
1460
+ cancelable: true,
1461
+ button: 0,
1462
+ composed: true,
1463
+ bubbles: true
1464
+ })
1465
+ );
1466
+ await elementUpdated(el);
1467
+ expect(
1468
+ el.value,
1469
+ "reset to default value on double click after moving pointer"
1470
+ ).to.equal(50);
1471
+ expect(inputSpy.callCount).to.equal(1);
1472
+ expect(changeSpy.callCount).to.equal(1);
1473
+ });
1474
+ it("manages escape key interactions correctly in an overlaid context", async () => {
1475
+ const inputSpy = spy();
1476
+ const changeSpy = spy();
1477
+ const el = await fixture(html`
1478
+ <div>
1479
+ <sp-button id="trigger">Overlay Trigger</sp-button>
1480
+ <sp-overlay trigger="trigger@click" placement="bottom">
1481
+ <sp-popover>
1482
+ <sp-slider
1483
+ style="width: 100px"
1484
+ value="70"
1485
+ default-value="50"
1486
+ @input=${(event) => {
1487
+ inputSpy(event.target.value);
1488
+ }}
1489
+ @change=${(event) => {
1490
+ changeSpy(event.target.value);
1491
+ }}
1492
+ ></sp-slider>
1493
+ </sp-popover>
1494
+ </sp-overlay>
1495
+ </div>
1496
+ `);
1497
+ await elementUpdated(el);
1498
+ const trigger = el.querySelector("#trigger");
1499
+ const opened = oneEvent(el, "sp-opened");
1500
+ trigger.click();
1501
+ await opened;
1502
+ const slider = el.querySelector("sp-slider");
1503
+ expect(slider.value).to.equal(70);
1504
+ slider.focus();
1505
+ await sendKeys({
1506
+ press: "Escape"
1507
+ });
1508
+ await elementUpdated(el);
1509
+ expect(slider.value).to.equal(50);
1510
+ expect(inputSpy.callCount).to.equal(1);
1511
+ expect(changeSpy.callCount).to.equal(1);
1512
+ const overlay = el.querySelector("sp-overlay");
1513
+ expect(overlay.open).to.be.true;
1514
+ const closed = oneEvent(el, "sp-closed");
1515
+ await sendKeys({
1516
+ press: "Escape"
1517
+ });
1518
+ await closed;
1519
+ expect(overlay.open).to.be.false;
1520
+ });
1521
+ });
1522
+ //# sourceMappingURL=slider.test.js.map