@internetarchive/histogram-date-range 1.3.1 → 1.3.2-alpha-webdev7713.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.
@@ -1,698 +1,699 @@
1
- import { html, fixture, expect, oneEvent, aTimeout } from '@open-wc/testing';
2
- import '../src/histogram-date-range';
3
- const SLIDER_WIDTH = 10;
4
- const WIDTH = 200;
5
- const subject = html `
6
- <histogram-date-range
7
- width="${WIDTH}"
8
- tooltipWidth="140"
9
- height="50"
10
- dateFormat="M/D/YYYY"
11
- minDate="1900"
12
- maxDate="12/4/2020"
13
- bins="[33, 1, 100]"
14
- >
15
- </histogram-date-range>
16
- `;
17
- async function createCustomElementInHTMLContainer() {
18
- document.head.insertAdjacentHTML('beforeend', `<style>
19
- html {
20
- font-size:10px;
21
- }
22
- .container {
23
- width: 400px;
24
- height: 400px;
25
- display: flex;
26
- background: #FFF6E1;
27
- justify-content: center;
28
- align-items: center;
29
- }
30
- </style>`);
31
- // https://open-wc.org/docs/testing/helpers/#customize-the-fixture-container
32
- const parentNode = document.createElement('div');
33
- parentNode.setAttribute('class', 'container');
34
- return fixture(subject, { parentNode });
35
- }
36
- describe('HistogramDateRange', () => {
37
- it('shows scaled histogram bars when provided with data', async () => {
38
- var _a;
39
- const el = await createCustomElementInHTMLContainer();
40
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
41
- const heights = Array.from(bars).map(b => b.height.baseVal.value);
42
- expect(heights).to.eql([38, 7, 50]);
43
- });
44
- it('changes the position of the sliders and standardizes date format when dates are entered', async () => {
45
- var _a, _b;
46
- const el = await createCustomElementInHTMLContainer();
47
- /* -------------------------- minimum (left) slider ------------------------- */
48
- expect(el.minSliderX).to.eq(SLIDER_WIDTH);
49
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
50
- const pressEnterEvent = new KeyboardEvent('keyup', {
51
- key: 'Enter',
52
- });
53
- // valid min date
54
- minDateInput.value = '1950';
55
- minDateInput.dispatchEvent(pressEnterEvent);
56
- expect(Math.floor(el.minSliderX)).to.eq(84);
57
- expect(el.minSelectedDate).to.eq('1/1/1950'); // set to correct format
58
- // attempt to set date earlier than first item
59
- minDateInput.value = '10/1/1850';
60
- minDateInput.dispatchEvent(new Event('blur'));
61
- expect(Math.floor(el.minSliderX)).to.eq(SLIDER_WIDTH); // leftmost valid position
62
- // allow date value less than slider range
63
- expect(el.minSelectedDate).to.eq('10/1/1850');
64
- /* -------------------------- maximum (right) slider ------------------------- */
65
- expect(el.maxSliderX).to.eq(WIDTH - SLIDER_WIDTH);
66
- const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
67
- // set valid max date
68
- maxDateInput.value = '3/12/1975';
69
- maxDateInput.dispatchEvent(pressEnterEvent);
70
- expect(Math.floor(el.maxSliderX)).to.eq(121);
71
- expect(maxDateInput.value).to.eq('3/12/1975');
72
- // attempt to set date later than last item
73
- maxDateInput.value = '12/31/2199';
74
- maxDateInput.dispatchEvent(new Event('blur'));
75
- await el.updateComplete;
76
- expect(el.maxSliderX).to.eq(WIDTH - SLIDER_WIDTH); // rightmost valid position
77
- // allow date value greater than slider range
78
- expect(maxDateInput.value).to.eq('12/31/2199');
79
- });
80
- it('when updateWhileFocused option is true, updates are fired upon changing input focus', async () => {
81
- var _a, _b;
82
- const el = await createCustomElementInHTMLContainer();
83
- el.updateWhileFocused = true;
84
- await el.updateComplete;
85
- let updateEventFired = false;
86
- el.addEventListener('histogramDateRangeUpdated', () => (updateEventFired = true));
87
- /* -------------------------- minimum (left) slider ------------------------- */
88
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
89
- /* -------------------------- maximum (right) slider ------------------------- */
90
- const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
91
- minDateInput.focus();
92
- // set valid min date, but don't hit Enter -- just switch focus to the max date input
93
- minDateInput.value = '1950';
94
- maxDateInput.focus();
95
- await el.updateComplete;
96
- await aTimeout(0);
97
- // update event should have fired, setting the minSelectedDate prop & slider position accordingly
98
- expect(updateEventFired).to.be.true;
99
- expect(Math.floor(el.minSliderX)).to.eq(84);
100
- expect(el.minSelectedDate).to.eq('1/1/1950');
101
- updateEventFired = false;
102
- await el.updateComplete;
103
- // set valid max date, but don't hit Enter -- just switch focus to the min date input
104
- maxDateInput.value = '3/12/1975';
105
- minDateInput.focus();
106
- await el.updateComplete;
107
- await aTimeout(0);
108
- // update event should have fired, setting the maxSelectedDate prop & slider position accordingly
109
- expect(updateEventFired).to.be.true;
110
- expect(Math.floor(el.maxSliderX)).to.eq(121);
111
- expect(el.maxSelectedDate).to.eq('3/12/1975');
112
- });
113
- it('when updateWhileFocused option is false (default), updates are not fired while one of the inputs remains focused', async () => {
114
- var _a, _b;
115
- const el = await createCustomElementInHTMLContainer();
116
- let updateEventFired = false;
117
- el.addEventListener('histogramDateRangeUpdated', () => (updateEventFired = true));
118
- /* -------------------------- minimum (left) slider ------------------------- */
119
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
120
- /* -------------------------- maximum (right) slider ------------------------- */
121
- const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
122
- minDateInput.focus();
123
- // set valid min date, but don't hit Enter -- just switch focus to the max date input
124
- minDateInput.value = '1950';
125
- maxDateInput.focus();
126
- await el.updateComplete;
127
- await aTimeout(0);
128
- // update event should NOT have fired, because focus remains within the inputs
129
- expect(updateEventFired).to.be.false;
130
- // set valid max date, but don't hit Enter -- just switch focus to the min date input
131
- maxDateInput.value = '3/12/1975';
132
- minDateInput.focus();
133
- await el.updateComplete;
134
- await aTimeout(0);
135
- // update event should NOT have fired, because focus remains within the inputs
136
- expect(updateEventFired).to.be.false;
137
- });
138
- it('handles invalid date inputs', async () => {
139
- var _a, _b;
140
- const el = await createCustomElementInHTMLContainer();
141
- /* -------------------------- minimum (left) slider ------------------------- */
142
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
143
- minDateInput.value = '5/17/1961';
144
- minDateInput.dispatchEvent(new Event('blur'));
145
- await el.updateComplete;
146
- expect(Math.floor(el.minSliderX)).to.eq(101);
147
- expect(minDateInput.value).to.eq('5/17/1961');
148
- // enter invalid value
149
- minDateInput.value = 'invalid';
150
- minDateInput.dispatchEvent(new Event('blur'));
151
- await el.updateComplete;
152
- expect(Math.floor(el.minSliderX)).to.eq(101); // does not move
153
- expect(minDateInput.value).to.eq('5/17/1961'); // resets back to previous date
154
- /* -------------------------- maximum (right) slider ------------------------- */
155
- const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
156
- // initial values
157
- expect(el.maxSliderX).to.eq(WIDTH - SLIDER_WIDTH);
158
- expect(maxDateInput.value).to.eq('12/4/2020');
159
- // enter invalid value
160
- maxDateInput.value = 'Abc 12, 1YYY';
161
- maxDateInput.dispatchEvent(new Event('blur'));
162
- await el.updateComplete;
163
- expect(Math.floor(el.maxSliderX)).to.eq(WIDTH - SLIDER_WIDTH); // does not move
164
- expect(maxDateInput.value).to.eq('12/4/2020'); // resets back to previous date
165
- });
166
- it('updates the date inputs when the sliders are moved', async () => {
167
- var _a, _b, _c, _d, _e;
168
- const el = await createCustomElementInHTMLContainer();
169
- /* -------------------------- minimum (left) slider ------------------------- */
170
- const minSlider = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#slider-min');
171
- const container = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#container');
172
- const minDateInput = (_c = el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#date-min');
173
- // initial state
174
- expect(minSlider.getBoundingClientRect().x).to.eq(108);
175
- expect(minSlider.classList.contains('draggable')).to.be.true;
176
- // pointer down
177
- minSlider.dispatchEvent(new PointerEvent('pointerdown'));
178
- await el.updateComplete;
179
- // cursor changes to 'grab'
180
- const classList = minSlider.classList;
181
- expect(classList.contains('draggable')).to.be.true;
182
- expect(classList.contains('dragging')).to.be.true;
183
- // slide to right
184
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: 60 }));
185
- await el.updateComplete;
186
- // slider has moved
187
- expect(Math.round(minSlider.getBoundingClientRect().x)).to.eq(168);
188
- // min date is updated
189
- expect(minDateInput.value).to.eq('4/23/1940');
190
- // stop dragging
191
- window.dispatchEvent(new PointerEvent('pointerup'));
192
- await el.updateComplete;
193
- // cursor returns to normal
194
- expect(Array.from(container.classList)).not.to.include('dragging');
195
- /* -------------------------- maximum (right) slider ------------------------- */
196
- const maxSlider = (_d = el.shadowRoot) === null || _d === void 0 ? void 0 : _d.querySelector('#slider-max');
197
- const maxDateInput = (_e = el.shadowRoot) === null || _e === void 0 ? void 0 : _e.querySelector('#date-max');
198
- // initial state
199
- expect(maxSlider.getBoundingClientRect().x).to.eq(298);
200
- // slide to left
201
- maxSlider.dispatchEvent(new PointerEvent('pointerdown', { clientX: 195 }));
202
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: 165 }));
203
- await el.updateComplete;
204
- // slider has moved
205
- expect(Math.round(maxSlider.getBoundingClientRect().x)).to.eq(268);
206
- // max date is updated
207
- expect(maxDateInput.value).to.eq('10/8/2000');
208
- await el.updateComplete;
209
- // try to slide min slider past max slider
210
- minSlider.dispatchEvent(new PointerEvent('pointerdown', { clientX: 62 }));
211
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: 190 }));
212
- await el.updateComplete;
213
- // slider moves all the way to meet the right slider
214
- expect(Math.round(minSlider.getBoundingClientRect().x)).to.eq(258);
215
- // try to slide max slider past min slider
216
- maxSlider.dispatchEvent(new PointerEvent('pointerdown', { clientX: 120 }));
217
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: 50 }));
218
- await el.updateComplete;
219
- expect(Math.round(maxSlider.getBoundingClientRect().x)).to.eq(268); // max slider didn't move
220
- // try to slide max slider off the right edge
221
- maxSlider.dispatchEvent(new PointerEvent('pointerdown', { clientX: 120 }));
222
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: 300 }));
223
- await el.updateComplete;
224
- expect(maxSlider.getBoundingClientRect().x).to.eq(298); // back to its initial position
225
- expect(el.maxSelectedDate).to.equal('12/4/2020');
226
- });
227
- it('does not permit sliders to select dates outside the allowed range', async () => {
228
- var _a, _b, _c, _d;
229
- const el = await createCustomElementInHTMLContainer();
230
- el.binSnapping = 'month';
231
- el.dateFormat = 'YYYY-MM';
232
- el.minDate = '2020-01';
233
- el.maxDate = '2021-12';
234
- el.minSelectedDate = '2020-01';
235
- el.maxSelectedDate = '2021-12';
236
- el.bins = [10, 20, 30, 40, 50, 60, 70, 80];
237
- await el.updateComplete;
238
- const minSlider = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#slider-min');
239
- const maxSlider = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#slider-max');
240
- const minDateInput = (_c = el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#date-min');
241
- const maxDateInput = (_d = el.shadowRoot) === null || _d === void 0 ? void 0 : _d.querySelector('#date-max');
242
- // initial state
243
- expect(minSlider.getBoundingClientRect().x).to.eq(108, 'initial');
244
- expect(maxSlider.getBoundingClientRect().x).to.eq(298, 'initial');
245
- expect(minDateInput.value).to.eq('2020-01', 'initial');
246
- expect(maxDateInput.value).to.eq('2021-12', 'initial');
247
- // try dragging the min slider too far to the left
248
- minSlider.dispatchEvent(new PointerEvent('pointerdown', { clientX: 0 }));
249
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: -50 }));
250
- await el.updateComplete;
251
- expect(minSlider.getBoundingClientRect().x).to.eq(108); // slider didn't move
252
- expect(minDateInput.value).to.eq('2020-01'); // value unchanged
253
- // try dragging the max slider too far to the right
254
- maxSlider.dispatchEvent(new PointerEvent('pointerdown', { clientX: 195 }));
255
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: 250 }));
256
- await el.updateComplete;
257
- expect(maxSlider.getBoundingClientRect().x).to.eq(298); // slider didn't move
258
- expect(maxDateInput.value).to.eq('2021-12'); // value unchanged
259
- });
260
- it("emits a custom event when the element's date range changes", async () => {
261
- var _a;
262
- const el = await createCustomElementInHTMLContainer();
263
- el.updateDelay = 30; // set debounce delay of 30ms
264
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
265
- const updateEventPromise = oneEvent(el, 'histogramDateRangeUpdated');
266
- // simulate typing a new value into input
267
- minDateInput.value = '1955';
268
- minDateInput.dispatchEvent(new Event('blur'));
269
- // will wait longer than debounce delay
270
- const { detail } = await updateEventPromise;
271
- // verify that event is emitted
272
- expect(detail.minDate).to.equal('1/1/1955');
273
- expect(detail.maxDate).to.equal('12/4/2020');
274
- let eventCount = 0;
275
- el.addEventListener('histogramDateRangeUpdated', () => (eventCount += 1));
276
- // events are not sent if no change since the last event that was sent
277
- minDateInput.value = '1955';
278
- minDateInput.dispatchEvent(new Event('blur'));
279
- await aTimeout(60); // wait longer than debounce delay
280
- expect(eventCount).to.equal(0);
281
- const updateEventPromise2 = oneEvent(el, 'histogramDateRangeUpdated');
282
- // with the debounce, multiple quick changes only result in one event sent
283
- minDateInput.value = '1965';
284
- minDateInput.dispatchEvent(new Event('blur'));
285
- await aTimeout(10); // wait less than the debounce delay
286
- minDateInput.dispatchEvent(new Event('focus'));
287
- minDateInput.value = '1975';
288
- minDateInput.dispatchEvent(new Event('blur'));
289
- await aTimeout(10);
290
- minDateInput.dispatchEvent(new Event('focus'));
291
- minDateInput.value = '1985';
292
- minDateInput.dispatchEvent(new Event('blur'));
293
- await aTimeout(10);
294
- const event2 = await updateEventPromise2;
295
- expect(event2.detail.minDate).to.equal('1/1/1985');
296
- expect(eventCount).to.equal(1); // only one event was fired
297
- });
298
- it('shows/hides tooltip when hovering over (or pointing at) a bar', async () => {
299
- var _a, _b;
300
- const el = await createCustomElementInHTMLContainer();
301
- // include a number which will require commas (1,000,000)
302
- el.bins = [1000000, 1, 100];
303
- await aTimeout(10);
304
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
305
- const tooltip = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#tooltip');
306
- expect(tooltip.innerText).to.eq('');
307
- // hover
308
- bars[0].dispatchEvent(new PointerEvent('pointerenter'));
309
- await el.updateComplete;
310
- expect(tooltip.innerText).to.match(/^1,000,000 items\n1\/1\/1900 - 4\/23\/1940/);
311
- expect(getComputedStyle(tooltip).display).to.eq('block');
312
- // leave
313
- bars[0].dispatchEvent(new PointerEvent('pointerleave'));
314
- await el.updateComplete;
315
- expect(getComputedStyle(tooltip).display).to.eq('none');
316
- expect(tooltip.innerText).to.eq('');
317
- // ensure singular item is not pluralized
318
- bars[1].dispatchEvent(new PointerEvent('pointerenter'));
319
- await el.updateComplete;
320
- expect(tooltip.innerText).to.match(/^1 item\n4\/23\/1940 - 8\/13\/1980/);
321
- });
322
- it('does not show tooltip while dragging', async () => {
323
- var _a, _b, _c;
324
- const el = await createCustomElementInHTMLContainer();
325
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
326
- const tooltip = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#tooltip');
327
- expect(tooltip.innerText).to.eq('');
328
- const minSlider = (_c = el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#slider-min');
329
- // pointer down and slide right
330
- minSlider.dispatchEvent(new PointerEvent('pointerdown'));
331
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: 100 }));
332
- await el.updateComplete;
333
- // hover over bar
334
- bars[0].dispatchEvent(new PointerEvent('pointerenter'));
335
- await el.updateComplete;
336
- // tooltip display is suppressed while dragging
337
- expect(tooltip.style.display).to.eq('');
338
- });
339
- it('passes the a11y audit', async () => {
340
- await fixture(subject).then(el => expect(el).shadowDom.to.be.accessible());
341
- });
342
- it('allows range to be pre-selected', async () => {
343
- var _a, _b;
344
- const el = await fixture(html `
345
- <histogram-date-range
346
- minDate="1900"
347
- maxDate="Dec 4, 2020"
348
- minSelectedDate="2012"
349
- maxSelectedDate="2019"
350
- bins="[33, 1, 100]"
351
- >
352
- </histogram-date-range>
353
- `);
354
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
355
- expect(minDateInput.value).to.eq('2012');
356
- const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
357
- expect(maxDateInput.value).to.eq('2019');
358
- });
359
- it('extends the selected range when the histogram is clicked outside of the current range', async () => {
360
- var _a, _b;
361
- const el = await fixture(html `
362
- <histogram-date-range
363
- minDate="1900"
364
- maxDate="2020"
365
- minSelectedDate="1950"
366
- maxSelectedDate="1955"
367
- bins="[33, 1, 1, 1, 10, 10, 1, 1, 1, 50, 100]"
368
- >
369
- </histogram-date-range>
370
- `);
371
- const leftBarToClick = Array.from((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar'))[1]; // click on second bar to the left
372
- leftBarToClick.dispatchEvent(new Event('click'));
373
- await el.updateComplete;
374
- expect(el.minSelectedDate).to.eq('1910'); // range was extended to left
375
- const rightBarToClick = Array.from((_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelectorAll('.bar'))[8]; // click on second bar from the right
376
- rightBarToClick.dispatchEvent(new Event('click'));
377
- expect(el.maxSelectedDate).to.eq('1998'); // range was extended to right
378
- });
379
- it('narrows the selected range when the histogram is clicked inside of the current range', async () => {
380
- var _a, _b;
381
- const el = await fixture(html `
382
- <histogram-date-range
383
- minDate="1900"
384
- maxDate="2020"
385
- minSelectedDate="1900"
386
- maxSelectedDate="2020"
387
- bins="[33, 1, 1, 1, 10, 10, 1, 1, 1, 50, 100]"
388
- >
389
- </histogram-date-range>
390
- `);
391
- ///////////////////////////////////////////////
392
- // NB: the slider nearest the clicked bar moves
393
- ///////////////////////////////////////////////
394
- const leftBarToClick = Array.from((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar'))[3]; // click on fourth bar to the left
395
- leftBarToClick.dispatchEvent(new Event('click'));
396
- expect(el.minSelectedDate).to.eq('1932'); // range was extended to the right
397
- const rightBarToClick = Array.from((_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelectorAll('.bar'))[8]; // click on second bar from the right
398
- rightBarToClick.dispatchEvent(new Event('click'));
399
- expect(el.maxSelectedDate).to.eq('1998'); // range was extended to the left
400
- });
401
- it('handles invalid pre-selected range by defaulting to overall max and min', async () => {
402
- var _a, _b;
403
- const el = await fixture(html `
404
- <histogram-date-range
405
- minDate="1900"
406
- maxDate="2020"
407
- minSelectedDate="2000xyz"
408
- maxSelectedDate="5000"
409
- bins="[33, 1, 100]"
410
- >
411
- </histogram-date-range>
412
- `);
413
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
414
- // malformed min date defaults to overall min
415
- expect(minDateInput.value).to.eq('1900');
416
- const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
417
- // well-formed max date is allowed
418
- expect(maxDateInput.value).to.eq('5000');
419
- });
420
- it('handles year values less than 1000 correctly', async () => {
421
- var _a, _b;
422
- const el = await fixture(html `
423
- <histogram-date-range
424
- dateFormat="M/D/YYYY"
425
- minDate="-2000"
426
- maxDate="2000"
427
- minSelectedDate="-500"
428
- maxSelectedDate="500"
429
- bins="[33, 1, 100]"
430
- >
431
- </histogram-date-range>
432
- `);
433
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
434
- expect(minDateInput.value).to.eq('1/1/-500');
435
- const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
436
- expect(maxDateInput.value).to.eq('1/1/500');
437
- });
438
- it('handles missing data', async () => {
439
- var _a, _b;
440
- let el = await fixture(html `<histogram-date-range>
441
- minDate="1900" maxDate="2020" bins=""
442
- </histogram-date-range>`);
443
- expect((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.innerHTML).to.contain('no data');
444
- el = await fixture(html `<histogram-date-range
445
- minDate="1900"
446
- maxDate="2020"
447
- bins="[]"
448
- missingDataMessage="no data available"
449
- ></histogram-date-range>`);
450
- expect((_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.innerHTML).to.contain('no data available');
451
- });
452
- it('correctly displays data consisting of a single bin', async () => {
453
- var _a;
454
- const el = await fixture(html `
455
- <histogram-date-range minDate="2020" maxDate="2020" bins="[50]">
456
- </histogram-date-range>
457
- `);
458
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
459
- const heights = Array.from(bars).map(b => b.height.baseVal.value);
460
- expect(heights).to.eql([157]);
461
- });
462
- it('correctly displays small diff between max and min values', async () => {
463
- var _a;
464
- const el = await fixture(html `
465
- <histogram-date-range bins="[1519,2643,1880,2041,1638,1441]">
466
- </histogram-date-range>
467
- `);
468
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
469
- const heights = Array.from(bars).map(b => b.height.baseVal.value);
470
- expect(heights).to.eql([37, 40, 38, 38, 37, 36]);
471
- });
472
- it('correctly aligns bins to exact month boundaries when binSnapping=month', async () => {
473
- var _a;
474
- const el = await fixture(html `
475
- <histogram-date-range
476
- binSnapping="month"
477
- dateFormat="YYYY-MM"
478
- tooltipDateFormat="MMM YYYY"
479
- minDate="2020-01"
480
- maxDate="2021-12"
481
- bins="[10,20,30,40,50,60,70,80]"
482
- ></histogram-date-range>
483
- `);
484
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
485
- const tooltips = Array.from(bars).map(b => b.dataset.tooltip);
486
- expect(tooltips).to.eql([
487
- 'Jan 2020 - Mar 2020',
488
- 'Apr 2020 - Jun 2020',
489
- 'Jul 2020 - Sep 2020',
490
- 'Oct 2020 - Dec 2020',
491
- 'Jan 2021 - Mar 2021',
492
- 'Apr 2021 - Jun 2021',
493
- 'Jul 2021 - Sep 2021',
494
- 'Oct 2021 - Dec 2021',
495
- ]);
496
- });
497
- it('correctly handles month snapping for years 0-99', async () => {
498
- var _a;
499
- const el = await fixture(html `
500
- <histogram-date-range
501
- binSnapping="month"
502
- dateFormat="YYYY-MM"
503
- tooltipDateFormat="MMM YYYY"
504
- minDate="0050-01"
505
- maxDate="0065-12"
506
- bins="[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32]"
507
- ></histogram-date-range>
508
- `);
509
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
510
- const tooltips = Array.from(bars).map(b => b.dataset.tooltip);
511
- expect(tooltips).to.eql([
512
- 'Jan 50 - Jun 50',
513
- 'Jul 50 - Dec 50',
514
- 'Jan 51 - Jun 51',
515
- 'Jul 51 - Dec 51',
516
- 'Jan 52 - Jun 52',
517
- 'Jul 52 - Dec 52',
518
- 'Jan 53 - Jun 53',
519
- 'Jul 53 - Dec 53',
520
- 'Jan 54 - Jun 54',
521
- 'Jul 54 - Dec 54',
522
- 'Jan 55 - Jun 55',
523
- 'Jul 55 - Dec 55',
524
- 'Jan 56 - Jun 56',
525
- 'Jul 56 - Dec 56',
526
- 'Jan 57 - Jun 57',
527
- 'Jul 57 - Dec 57',
528
- 'Jan 58 - Jun 58',
529
- 'Jul 58 - Dec 58',
530
- 'Jan 59 - Jun 59',
531
- 'Jul 59 - Dec 59',
532
- 'Jan 60 - Jun 60',
533
- 'Jul 60 - Dec 60',
534
- 'Jan 61 - Jun 61',
535
- 'Jul 61 - Dec 61',
536
- 'Jan 62 - Jun 62',
537
- 'Jul 62 - Dec 62',
538
- 'Jan 63 - Jun 63',
539
- 'Jul 63 - Dec 63',
540
- 'Jan 64 - Jun 64',
541
- 'Jul 64 - Dec 64',
542
- 'Jan 65 - Jun 65',
543
- 'Jul 65 - Dec 65',
544
- ]);
545
- });
546
- it('correctly aligns bins to exact year boundaries when binSnapping=year', async () => {
547
- var _a;
548
- const el = await fixture(html `
549
- <histogram-date-range
550
- binSnapping="year"
551
- minDate="2000"
552
- maxDate="2019"
553
- bins="[10,20,30,40,50,60,70,80,90,100]"
554
- ></histogram-date-range>
555
- `);
556
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
557
- const tooltips = Array.from(bars).map(b => b.dataset.tooltip);
558
- expect(tooltips).to.eql([
559
- '2000 - 2001',
560
- '2002 - 2003',
561
- '2004 - 2005',
562
- '2006 - 2007',
563
- '2008 - 2009',
564
- '2010 - 2011',
565
- '2012 - 2013',
566
- '2014 - 2015',
567
- '2016 - 2017',
568
- '2018 - 2019',
569
- ]);
570
- });
571
- it('correctly handles year snapping for years 0-99', async () => {
572
- var _a;
573
- const el = await fixture(html `
574
- <histogram-date-range
575
- binSnapping="year"
576
- dateFormat="YYYY"
577
- minDate="0020"
578
- maxDate="0025"
579
- bins="[1,2,3,4,5,6]"
580
- ></histogram-date-range>
581
- `);
582
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
583
- const tooltips = Array.from(bars).map(b => b.dataset.tooltip);
584
- expect(tooltips).to.eql(['20', '21', '22', '23', '24', '25']);
585
- });
586
- it('does not duplicate start/end date in tooltips when representing a single year', async () => {
587
- var _a;
588
- const el = await fixture(html `
589
- <histogram-date-range
590
- binSnapping="year"
591
- dateFormat="YYYY"
592
- minDate="2001"
593
- maxDate="2005"
594
- bins="[10,20,30,40,50]"
595
- ></histogram-date-range>
596
- `);
597
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
598
- const tooltips = Array.from(bars).map(b => b.dataset.tooltip);
599
- expect(tooltips).to.eql(['2001', '2002', '2003', '2004', '2005']);
600
- });
601
- it('falls back to default date format for tooltips if no tooltip date format provided', async () => {
602
- var _a;
603
- const el = await fixture(html `
604
- <histogram-date-range
605
- binSnapping="year"
606
- minDate="2001"
607
- maxDate="2005"
608
- bins="[10,20,30,40,50]"
609
- ></histogram-date-range>
610
- `);
611
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
612
- let tooltips = Array.from(bars).map(b => b.dataset.tooltip);
613
- expect(tooltips).to.eql(['2001', '2002', '2003', '2004', '2005']); // default YYYY date format
614
- el.dateFormat = 'YYYY/MM';
615
- el.minDate = '2001/01';
616
- el.maxDate = '2005/01';
617
- await el.updateComplete;
618
- // Should use dateFormat fallback for tooltips
619
- tooltips = Array.from(bars).map(b => b.dataset.tooltip);
620
- expect(tooltips).to.eql([
621
- '2001/01 - 2001/12',
622
- '2002/01 - 2002/12',
623
- '2003/01 - 2003/12',
624
- '2004/01 - 2004/12',
625
- '2005/01 - 2005/12',
626
- ]);
627
- el.dateFormat = 'YYYY';
628
- el.tooltipDateFormat = 'MMMM YYYY';
629
- el.minDate = '2001';
630
- el.maxDate = '2005';
631
- await el.updateComplete;
632
- // Should use defined tooltipDateFormat for tooltips
633
- tooltips = Array.from(bars).map(b => b.dataset.tooltip);
634
- expect(tooltips).to.eql([
635
- 'January 2001 - December 2001',
636
- 'January 2002 - December 2002',
637
- 'January 2003 - December 2003',
638
- 'January 2004 - December 2004',
639
- 'January 2005 - December 2005',
640
- ]);
641
- });
642
- it('has a disabled state', async () => {
643
- var _a, _b, _c;
644
- const el = await fixture(html `
645
- <histogram-date-range
646
- minDate="1900"
647
- maxDate="2020"
648
- disabled
649
- bins="[33, 1, 100]"
650
- >
651
- </histogram-date-range>
652
- `);
653
- expect((_b = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.inner-container')) === null || _b === void 0 ? void 0 : _b.classList.contains('disabled')).to.eq(true);
654
- const minSlider = (_c = el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#slider-min');
655
- expect(Math.round(minSlider.getBoundingClientRect().x)).to.eq(8); // initial state
656
- // attempt to slide to right
657
- minSlider.dispatchEvent(new PointerEvent('pointerdown'));
658
- await el.updateComplete;
659
- // cursor is not draggable if disabled
660
- expect(minSlider.classList.contains('draggable')).to.be.false;
661
- // attempt to slide to right
662
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: 70 }));
663
- await el.updateComplete;
664
- // slider does not moved if element disabled
665
- expect(Math.round(minSlider.getBoundingClientRect().x)).to.eq(8);
666
- });
667
- it('has a loading state with an activity indicator', async () => {
668
- var _a, _b, _c, _d;
669
- const el = await fixture(html `
670
- <histogram-date-range
671
- minDate="1900"
672
- maxDate="2020"
673
- loading
674
- bins="[33, 1, 100]"
675
- >
676
- </histogram-date-range>
677
- `);
678
- expect((_d = (_c = (_b = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('ia-activity-indicator')) === null || _b === void 0 ? void 0 : _b.attributes) === null || _c === void 0 ? void 0 : _c.getNamedItem('mode')) === null || _d === void 0 ? void 0 : _d.value).to.eq('processing');
679
- });
680
- it('can use LitElement bound properties', async () => {
681
- var _a, _b;
682
- const el = await fixture(html `
683
- <histogram-date-range
684
- .minDate=${1900}
685
- .maxDate=${'Dec 4, 2020'}
686
- .minSelectedDate=${2012}
687
- .maxSelectedDate=${2019}
688
- .bins=${[33, 1, 100]}
689
- >
690
- </histogram-date-range>
691
- `);
692
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
693
- expect(minDateInput.value).to.eq('2012');
694
- const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
695
- expect(maxDateInput.value).to.eq('2019');
696
- });
697
- });
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
2
+ import { html, fixture, expect, oneEvent, aTimeout } from '@open-wc/testing';
3
+ import '../src/histogram-date-range';
4
+ const SLIDER_WIDTH = 10;
5
+ const WIDTH = 200;
6
+ const subject = html `
7
+ <histogram-date-range
8
+ width="${WIDTH}"
9
+ tooltipWidth="140"
10
+ height="50"
11
+ dateFormat="M/D/YYYY"
12
+ minDate="1900"
13
+ maxDate="12/4/2020"
14
+ bins="[33, 1, 100]"
15
+ >
16
+ </histogram-date-range>
17
+ `;
18
+ async function createCustomElementInHTMLContainer() {
19
+ document.head.insertAdjacentHTML('beforeend', `<style>
20
+ html {
21
+ font-size:10px;
22
+ }
23
+ .container {
24
+ width: 400px;
25
+ height: 400px;
26
+ display: flex;
27
+ background: #FFF6E1;
28
+ justify-content: center;
29
+ align-items: center;
30
+ }
31
+ </style>`);
32
+ // https://open-wc.org/docs/testing/helpers/#customize-the-fixture-container
33
+ const parentNode = document.createElement('div');
34
+ parentNode.setAttribute('class', 'container');
35
+ return fixture(subject, { parentNode });
36
+ }
37
+ describe('HistogramDateRange', () => {
38
+ it('shows scaled histogram bars when provided with data', async () => {
39
+ var _a;
40
+ const el = await createCustomElementInHTMLContainer();
41
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
42
+ const heights = Array.from(bars).map(b => b.height.baseVal.value);
43
+ expect(heights).to.eql([38, 7, 50]);
44
+ });
45
+ it('changes the position of the sliders and standardizes date format when dates are entered', async () => {
46
+ var _a, _b;
47
+ const el = await createCustomElementInHTMLContainer();
48
+ /* -------------------------- minimum (left) slider ------------------------- */
49
+ expect(el.minSliderX).to.eq(SLIDER_WIDTH);
50
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
51
+ const pressEnterEvent = new KeyboardEvent('keyup', {
52
+ key: 'Enter',
53
+ });
54
+ // valid min date
55
+ minDateInput.value = '1950';
56
+ minDateInput.dispatchEvent(pressEnterEvent);
57
+ expect(Math.floor(el.minSliderX)).to.eq(84);
58
+ expect(el.minSelectedDate).to.eq('1/1/1950'); // set to correct format
59
+ // attempt to set date earlier than first item
60
+ minDateInput.value = '10/1/1850';
61
+ minDateInput.dispatchEvent(new Event('blur'));
62
+ expect(Math.floor(el.minSliderX)).to.eq(SLIDER_WIDTH); // leftmost valid position
63
+ // allow date value less than slider range
64
+ expect(el.minSelectedDate).to.eq('10/1/1850');
65
+ /* -------------------------- maximum (right) slider ------------------------- */
66
+ expect(el.maxSliderX).to.eq(WIDTH - SLIDER_WIDTH);
67
+ const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
68
+ // set valid max date
69
+ maxDateInput.value = '3/12/1975';
70
+ maxDateInput.dispatchEvent(pressEnterEvent);
71
+ expect(Math.floor(el.maxSliderX)).to.eq(121);
72
+ expect(maxDateInput.value).to.eq('3/12/1975');
73
+ // attempt to set date later than last item
74
+ maxDateInput.value = '12/31/2199';
75
+ maxDateInput.dispatchEvent(new Event('blur'));
76
+ await el.updateComplete;
77
+ expect(el.maxSliderX).to.eq(WIDTH - SLIDER_WIDTH); // rightmost valid position
78
+ // allow date value greater than slider range
79
+ expect(maxDateInput.value).to.eq('12/31/2199');
80
+ });
81
+ it('when updateWhileFocused option is true, updates are fired upon changing input focus', async () => {
82
+ var _a, _b;
83
+ const el = await createCustomElementInHTMLContainer();
84
+ el.updateWhileFocused = true;
85
+ await el.updateComplete;
86
+ let updateEventFired = false;
87
+ el.addEventListener('histogramDateRangeUpdated', () => (updateEventFired = true));
88
+ /* -------------------------- minimum (left) slider ------------------------- */
89
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
90
+ /* -------------------------- maximum (right) slider ------------------------- */
91
+ const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
92
+ minDateInput.focus();
93
+ // set valid min date, but don't hit Enter -- just switch focus to the max date input
94
+ minDateInput.value = '1950';
95
+ maxDateInput.focus();
96
+ await el.updateComplete;
97
+ await aTimeout(0);
98
+ // update event should have fired, setting the minSelectedDate prop & slider position accordingly
99
+ expect(updateEventFired).to.be.true;
100
+ expect(Math.floor(el.minSliderX)).to.eq(84);
101
+ expect(el.minSelectedDate).to.eq('1/1/1950');
102
+ updateEventFired = false;
103
+ await el.updateComplete;
104
+ // set valid max date, but don't hit Enter -- just switch focus to the min date input
105
+ maxDateInput.value = '3/12/1975';
106
+ minDateInput.focus();
107
+ await el.updateComplete;
108
+ await aTimeout(0);
109
+ // update event should have fired, setting the maxSelectedDate prop & slider position accordingly
110
+ expect(updateEventFired).to.be.true;
111
+ expect(Math.floor(el.maxSliderX)).to.eq(121);
112
+ expect(el.maxSelectedDate).to.eq('3/12/1975');
113
+ });
114
+ it('when updateWhileFocused option is false (default), updates are not fired while one of the inputs remains focused', async () => {
115
+ var _a, _b;
116
+ const el = await createCustomElementInHTMLContainer();
117
+ let updateEventFired = false;
118
+ el.addEventListener('histogramDateRangeUpdated', () => (updateEventFired = true));
119
+ /* -------------------------- minimum (left) slider ------------------------- */
120
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
121
+ /* -------------------------- maximum (right) slider ------------------------- */
122
+ const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
123
+ minDateInput.focus();
124
+ // set valid min date, but don't hit Enter -- just switch focus to the max date input
125
+ minDateInput.value = '1950';
126
+ maxDateInput.focus();
127
+ await el.updateComplete;
128
+ await aTimeout(0);
129
+ // update event should NOT have fired, because focus remains within the inputs
130
+ expect(updateEventFired).to.be.false;
131
+ // set valid max date, but don't hit Enter -- just switch focus to the min date input
132
+ maxDateInput.value = '3/12/1975';
133
+ minDateInput.focus();
134
+ await el.updateComplete;
135
+ await aTimeout(0);
136
+ // update event should NOT have fired, because focus remains within the inputs
137
+ expect(updateEventFired).to.be.false;
138
+ });
139
+ it('handles invalid date inputs', async () => {
140
+ var _a, _b;
141
+ const el = await createCustomElementInHTMLContainer();
142
+ /* -------------------------- minimum (left) slider ------------------------- */
143
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
144
+ minDateInput.value = '5/17/1961';
145
+ minDateInput.dispatchEvent(new Event('blur'));
146
+ await el.updateComplete;
147
+ expect(Math.floor(el.minSliderX)).to.eq(101);
148
+ expect(minDateInput.value).to.eq('5/17/1961');
149
+ // enter invalid value
150
+ minDateInput.value = 'invalid';
151
+ minDateInput.dispatchEvent(new Event('blur'));
152
+ await el.updateComplete;
153
+ expect(Math.floor(el.minSliderX)).to.eq(101); // does not move
154
+ expect(minDateInput.value).to.eq('5/17/1961'); // resets back to previous date
155
+ /* -------------------------- maximum (right) slider ------------------------- */
156
+ const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
157
+ // initial values
158
+ expect(el.maxSliderX).to.eq(WIDTH - SLIDER_WIDTH);
159
+ expect(maxDateInput.value).to.eq('12/4/2020');
160
+ // enter invalid value
161
+ maxDateInput.value = 'Abc 12, 1YYY';
162
+ maxDateInput.dispatchEvent(new Event('blur'));
163
+ await el.updateComplete;
164
+ expect(Math.floor(el.maxSliderX)).to.eq(WIDTH - SLIDER_WIDTH); // does not move
165
+ expect(maxDateInput.value).to.eq('12/4/2020'); // resets back to previous date
166
+ });
167
+ it('updates the date inputs when the sliders are moved', async () => {
168
+ var _a, _b, _c, _d, _e;
169
+ const el = await createCustomElementInHTMLContainer();
170
+ /* -------------------------- minimum (left) slider ------------------------- */
171
+ const minSlider = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#slider-min');
172
+ const container = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#container');
173
+ const minDateInput = (_c = el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#date-min');
174
+ // initial state
175
+ expect(minSlider.getBoundingClientRect().x).to.eq(108);
176
+ expect(minSlider.classList.contains('draggable')).to.be.true;
177
+ // pointer down
178
+ minSlider.dispatchEvent(new PointerEvent('pointerdown'));
179
+ await el.updateComplete;
180
+ // cursor changes to 'grab'
181
+ const classList = minSlider.classList;
182
+ expect(classList.contains('draggable')).to.be.true;
183
+ expect(classList.contains('dragging')).to.be.true;
184
+ // slide to right
185
+ window.dispatchEvent(new PointerEvent('pointermove', { clientX: 60 }));
186
+ await el.updateComplete;
187
+ // slider has moved
188
+ expect(Math.round(minSlider.getBoundingClientRect().x)).to.eq(168);
189
+ // min date is updated
190
+ expect(minDateInput.value).to.eq('4/23/1940');
191
+ // stop dragging
192
+ window.dispatchEvent(new PointerEvent('pointerup'));
193
+ await el.updateComplete;
194
+ // cursor returns to normal
195
+ expect(Array.from(container.classList)).not.to.include('dragging');
196
+ /* -------------------------- maximum (right) slider ------------------------- */
197
+ const maxSlider = (_d = el.shadowRoot) === null || _d === void 0 ? void 0 : _d.querySelector('#slider-max');
198
+ const maxDateInput = (_e = el.shadowRoot) === null || _e === void 0 ? void 0 : _e.querySelector('#date-max');
199
+ // initial state
200
+ expect(maxSlider.getBoundingClientRect().x).to.eq(298);
201
+ // slide to left
202
+ maxSlider.dispatchEvent(new PointerEvent('pointerdown', { clientX: 195 }));
203
+ window.dispatchEvent(new PointerEvent('pointermove', { clientX: 165 }));
204
+ await el.updateComplete;
205
+ // slider has moved
206
+ expect(Math.round(maxSlider.getBoundingClientRect().x)).to.eq(268);
207
+ // max date is updated
208
+ expect(maxDateInput.value).to.eq('10/8/2000');
209
+ await el.updateComplete;
210
+ // try to slide min slider past max slider
211
+ minSlider.dispatchEvent(new PointerEvent('pointerdown', { clientX: 62 }));
212
+ window.dispatchEvent(new PointerEvent('pointermove', { clientX: 190 }));
213
+ await el.updateComplete;
214
+ // slider moves all the way to meet the right slider
215
+ expect(Math.round(minSlider.getBoundingClientRect().x)).to.eq(258);
216
+ // try to slide max slider past min slider
217
+ maxSlider.dispatchEvent(new PointerEvent('pointerdown', { clientX: 120 }));
218
+ window.dispatchEvent(new PointerEvent('pointermove', { clientX: 50 }));
219
+ await el.updateComplete;
220
+ expect(Math.round(maxSlider.getBoundingClientRect().x)).to.eq(268); // max slider didn't move
221
+ // try to slide max slider off the right edge
222
+ maxSlider.dispatchEvent(new PointerEvent('pointerdown', { clientX: 120 }));
223
+ window.dispatchEvent(new PointerEvent('pointermove', { clientX: 300 }));
224
+ await el.updateComplete;
225
+ expect(maxSlider.getBoundingClientRect().x).to.eq(298); // back to its initial position
226
+ expect(el.maxSelectedDate).to.equal('12/4/2020');
227
+ });
228
+ it('does not permit sliders to select dates outside the allowed range', async () => {
229
+ var _a, _b, _c, _d;
230
+ const el = await createCustomElementInHTMLContainer();
231
+ el.binSnapping = 'month';
232
+ el.dateFormat = 'YYYY-MM';
233
+ el.minDate = '2020-01';
234
+ el.maxDate = '2021-12';
235
+ el.minSelectedDate = '2020-01';
236
+ el.maxSelectedDate = '2021-12';
237
+ el.bins = [10, 20, 30, 40, 50, 60, 70, 80];
238
+ await el.updateComplete;
239
+ const minSlider = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#slider-min');
240
+ const maxSlider = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#slider-max');
241
+ const minDateInput = (_c = el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#date-min');
242
+ const maxDateInput = (_d = el.shadowRoot) === null || _d === void 0 ? void 0 : _d.querySelector('#date-max');
243
+ // initial state
244
+ expect(minSlider.getBoundingClientRect().x).to.eq(108, 'initial');
245
+ expect(maxSlider.getBoundingClientRect().x).to.eq(298, 'initial');
246
+ expect(minDateInput.value).to.eq('2020-01', 'initial');
247
+ expect(maxDateInput.value).to.eq('2021-12', 'initial');
248
+ // try dragging the min slider too far to the left
249
+ minSlider.dispatchEvent(new PointerEvent('pointerdown', { clientX: 0 }));
250
+ window.dispatchEvent(new PointerEvent('pointermove', { clientX: -50 }));
251
+ await el.updateComplete;
252
+ expect(minSlider.getBoundingClientRect().x).to.eq(108); // slider didn't move
253
+ expect(minDateInput.value).to.eq('2020-01'); // value unchanged
254
+ // try dragging the max slider too far to the right
255
+ maxSlider.dispatchEvent(new PointerEvent('pointerdown', { clientX: 195 }));
256
+ window.dispatchEvent(new PointerEvent('pointermove', { clientX: 250 }));
257
+ await el.updateComplete;
258
+ expect(maxSlider.getBoundingClientRect().x).to.eq(298); // slider didn't move
259
+ expect(maxDateInput.value).to.eq('2021-12'); // value unchanged
260
+ });
261
+ it("emits a custom event when the element's date range changes", async () => {
262
+ var _a;
263
+ const el = await createCustomElementInHTMLContainer();
264
+ el.updateDelay = 30; // set debounce delay of 30ms
265
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
266
+ const updateEventPromise = oneEvent(el, 'histogramDateRangeUpdated');
267
+ // simulate typing a new value into input
268
+ minDateInput.value = '1955';
269
+ minDateInput.dispatchEvent(new Event('blur'));
270
+ // will wait longer than debounce delay
271
+ const { detail } = await updateEventPromise;
272
+ // verify that event is emitted
273
+ expect(detail.minDate).to.equal('1/1/1955');
274
+ expect(detail.maxDate).to.equal('12/4/2020');
275
+ let eventCount = 0;
276
+ el.addEventListener('histogramDateRangeUpdated', () => (eventCount += 1));
277
+ // events are not sent if no change since the last event that was sent
278
+ minDateInput.value = '1955';
279
+ minDateInput.dispatchEvent(new Event('blur'));
280
+ await aTimeout(60); // wait longer than debounce delay
281
+ expect(eventCount).to.equal(0);
282
+ const updateEventPromise2 = oneEvent(el, 'histogramDateRangeUpdated');
283
+ // with the debounce, multiple quick changes only result in one event sent
284
+ minDateInput.value = '1965';
285
+ minDateInput.dispatchEvent(new Event('blur'));
286
+ await aTimeout(10); // wait less than the debounce delay
287
+ minDateInput.dispatchEvent(new Event('focus'));
288
+ minDateInput.value = '1975';
289
+ minDateInput.dispatchEvent(new Event('blur'));
290
+ await aTimeout(10);
291
+ minDateInput.dispatchEvent(new Event('focus'));
292
+ minDateInput.value = '1985';
293
+ minDateInput.dispatchEvent(new Event('blur'));
294
+ await aTimeout(10);
295
+ const event2 = await updateEventPromise2;
296
+ expect(event2.detail.minDate).to.equal('1/1/1985');
297
+ expect(eventCount).to.equal(1); // only one event was fired
298
+ });
299
+ it('shows/hides tooltip when hovering over (or pointing at) a bar', async () => {
300
+ var _a, _b;
301
+ const el = await createCustomElementInHTMLContainer();
302
+ // include a number which will require commas (1,000,000)
303
+ el.bins = [1000000, 1, 100];
304
+ await aTimeout(10);
305
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
306
+ const tooltip = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#tooltip');
307
+ expect(tooltip.innerText).to.eq('');
308
+ // hover
309
+ bars[0].dispatchEvent(new PointerEvent('pointerenter'));
310
+ await el.updateComplete;
311
+ expect(tooltip.innerText).to.match(/^1,000,000 items\n1\/1\/1900 - 4\/23\/1940/);
312
+ expect(getComputedStyle(tooltip).display).to.eq('block');
313
+ // leave
314
+ bars[0].dispatchEvent(new PointerEvent('pointerleave'));
315
+ await el.updateComplete;
316
+ expect(getComputedStyle(tooltip).display).to.eq('none');
317
+ expect(tooltip.innerText).to.eq('');
318
+ // ensure singular item is not pluralized
319
+ bars[1].dispatchEvent(new PointerEvent('pointerenter'));
320
+ await el.updateComplete;
321
+ expect(tooltip.innerText).to.match(/^1 item\n4\/23\/1940 - 8\/13\/1980/);
322
+ });
323
+ it('does not show tooltip while dragging', async () => {
324
+ var _a, _b, _c;
325
+ const el = await createCustomElementInHTMLContainer();
326
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
327
+ const tooltip = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#tooltip');
328
+ expect(tooltip.innerText).to.eq('');
329
+ const minSlider = (_c = el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#slider-min');
330
+ // pointer down and slide right
331
+ minSlider.dispatchEvent(new PointerEvent('pointerdown'));
332
+ window.dispatchEvent(new PointerEvent('pointermove', { clientX: 100 }));
333
+ await el.updateComplete;
334
+ // hover over bar
335
+ bars[0].dispatchEvent(new PointerEvent('pointerenter'));
336
+ await el.updateComplete;
337
+ // tooltip display is suppressed while dragging
338
+ expect(tooltip.style.display).to.eq('');
339
+ });
340
+ it('passes the a11y audit', async () => {
341
+ await fixture(subject).then(el => expect(el).shadowDom.to.be.accessible());
342
+ });
343
+ it('allows range to be pre-selected', async () => {
344
+ var _a, _b;
345
+ const el = await fixture(html `
346
+ <histogram-date-range
347
+ minDate="1900"
348
+ maxDate="Dec 4, 2020"
349
+ minSelectedDate="2012"
350
+ maxSelectedDate="2019"
351
+ bins="[33, 1, 100]"
352
+ >
353
+ </histogram-date-range>
354
+ `);
355
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
356
+ expect(minDateInput.value).to.eq('2012');
357
+ const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
358
+ expect(maxDateInput.value).to.eq('2019');
359
+ });
360
+ it('extends the selected range when the histogram is clicked outside of the current range', async () => {
361
+ var _a, _b;
362
+ const el = await fixture(html `
363
+ <histogram-date-range
364
+ minDate="1900"
365
+ maxDate="2020"
366
+ minSelectedDate="1950"
367
+ maxSelectedDate="1955"
368
+ bins="[33, 1, 1, 1, 10, 10, 1, 1, 1, 50, 100]"
369
+ >
370
+ </histogram-date-range>
371
+ `);
372
+ const leftBarToClick = Array.from((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar'))[1]; // click on second bar to the left
373
+ leftBarToClick.dispatchEvent(new Event('click'));
374
+ await el.updateComplete;
375
+ expect(el.minSelectedDate).to.eq('1910'); // range was extended to left
376
+ const rightBarToClick = Array.from((_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelectorAll('.bar'))[8]; // click on second bar from the right
377
+ rightBarToClick.dispatchEvent(new Event('click'));
378
+ expect(el.maxSelectedDate).to.eq('1998'); // range was extended to right
379
+ });
380
+ it('narrows the selected range when the histogram is clicked inside of the current range', async () => {
381
+ var _a, _b;
382
+ const el = await fixture(html `
383
+ <histogram-date-range
384
+ minDate="1900"
385
+ maxDate="2020"
386
+ minSelectedDate="1900"
387
+ maxSelectedDate="2020"
388
+ bins="[33, 1, 1, 1, 10, 10, 1, 1, 1, 50, 100]"
389
+ >
390
+ </histogram-date-range>
391
+ `);
392
+ ///////////////////////////////////////////////
393
+ // NB: the slider nearest the clicked bar moves
394
+ ///////////////////////////////////////////////
395
+ const leftBarToClick = Array.from((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar'))[3]; // click on fourth bar to the left
396
+ leftBarToClick.dispatchEvent(new Event('click'));
397
+ expect(el.minSelectedDate).to.eq('1932'); // range was extended to the right
398
+ const rightBarToClick = Array.from((_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelectorAll('.bar'))[8]; // click on second bar from the right
399
+ rightBarToClick.dispatchEvent(new Event('click'));
400
+ expect(el.maxSelectedDate).to.eq('1998'); // range was extended to the left
401
+ });
402
+ it('handles invalid pre-selected range by defaulting to overall max and min', async () => {
403
+ var _a, _b;
404
+ const el = await fixture(html `
405
+ <histogram-date-range
406
+ minDate="1900"
407
+ maxDate="2020"
408
+ minSelectedDate="2000xyz"
409
+ maxSelectedDate="5000"
410
+ bins="[33, 1, 100]"
411
+ >
412
+ </histogram-date-range>
413
+ `);
414
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
415
+ // malformed min date defaults to overall min
416
+ expect(minDateInput.value).to.eq('1900');
417
+ const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
418
+ // well-formed max date is allowed
419
+ expect(maxDateInput.value).to.eq('5000');
420
+ });
421
+ it('handles year values less than 1000 correctly', async () => {
422
+ var _a, _b;
423
+ const el = await fixture(html `
424
+ <histogram-date-range
425
+ dateFormat="M/D/YYYY"
426
+ minDate="-2000"
427
+ maxDate="2000"
428
+ minSelectedDate="-500"
429
+ maxSelectedDate="500"
430
+ bins="[33, 1, 100]"
431
+ >
432
+ </histogram-date-range>
433
+ `);
434
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
435
+ expect(minDateInput.value).to.eq('1/1/-500');
436
+ const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
437
+ expect(maxDateInput.value).to.eq('1/1/500');
438
+ });
439
+ it('handles missing data', async () => {
440
+ var _a, _b;
441
+ let el = await fixture(html `<histogram-date-range>
442
+ minDate="1900" maxDate="2020" bins=""
443
+ </histogram-date-range>`);
444
+ expect((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.innerHTML).to.contain('no data');
445
+ el = await fixture(html `<histogram-date-range
446
+ minDate="1900"
447
+ maxDate="2020"
448
+ bins="[]"
449
+ missingDataMessage="no data available"
450
+ ></histogram-date-range>`);
451
+ expect((_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.innerHTML).to.contain('no data available');
452
+ });
453
+ it('correctly displays data consisting of a single bin', async () => {
454
+ var _a;
455
+ const el = await fixture(html `
456
+ <histogram-date-range minDate="2020" maxDate="2020" bins="[50]">
457
+ </histogram-date-range>
458
+ `);
459
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
460
+ const heights = Array.from(bars).map(b => b.height.baseVal.value);
461
+ expect(heights).to.eql([157]);
462
+ });
463
+ it('correctly displays small diff between max and min values', async () => {
464
+ var _a;
465
+ const el = await fixture(html `
466
+ <histogram-date-range bins="[1519,2643,1880,2041,1638,1441]">
467
+ </histogram-date-range>
468
+ `);
469
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
470
+ const heights = Array.from(bars).map(b => b.height.baseVal.value);
471
+ expect(heights).to.eql([37, 40, 38, 38, 37, 36]);
472
+ });
473
+ it('correctly aligns bins to exact month boundaries when binSnapping=month', async () => {
474
+ var _a;
475
+ const el = await fixture(html `
476
+ <histogram-date-range
477
+ binSnapping="month"
478
+ dateFormat="YYYY-MM"
479
+ tooltipDateFormat="MMM YYYY"
480
+ minDate="2020-01"
481
+ maxDate="2021-12"
482
+ bins="[10,20,30,40,50,60,70,80]"
483
+ ></histogram-date-range>
484
+ `);
485
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
486
+ const tooltips = Array.from(bars).map(b => b.dataset.tooltip);
487
+ expect(tooltips).to.eql([
488
+ 'Jan 2020 - Mar 2020',
489
+ 'Apr 2020 - Jun 2020',
490
+ 'Jul 2020 - Sep 2020',
491
+ 'Oct 2020 - Dec 2020',
492
+ 'Jan 2021 - Mar 2021',
493
+ 'Apr 2021 - Jun 2021',
494
+ 'Jul 2021 - Sep 2021',
495
+ 'Oct 2021 - Dec 2021',
496
+ ]);
497
+ });
498
+ it('correctly handles month snapping for years 0-99', async () => {
499
+ var _a;
500
+ const el = await fixture(html `
501
+ <histogram-date-range
502
+ binSnapping="month"
503
+ dateFormat="YYYY-MM"
504
+ tooltipDateFormat="MMM YYYY"
505
+ minDate="0050-01"
506
+ maxDate="0065-12"
507
+ bins="[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32]"
508
+ ></histogram-date-range>
509
+ `);
510
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
511
+ const tooltips = Array.from(bars).map(b => b.dataset.tooltip);
512
+ expect(tooltips).to.eql([
513
+ 'Jan 50 - Jun 50',
514
+ 'Jul 50 - Dec 50',
515
+ 'Jan 51 - Jun 51',
516
+ 'Jul 51 - Dec 51',
517
+ 'Jan 52 - Jun 52',
518
+ 'Jul 52 - Dec 52',
519
+ 'Jan 53 - Jun 53',
520
+ 'Jul 53 - Dec 53',
521
+ 'Jan 54 - Jun 54',
522
+ 'Jul 54 - Dec 54',
523
+ 'Jan 55 - Jun 55',
524
+ 'Jul 55 - Dec 55',
525
+ 'Jan 56 - Jun 56',
526
+ 'Jul 56 - Dec 56',
527
+ 'Jan 57 - Jun 57',
528
+ 'Jul 57 - Dec 57',
529
+ 'Jan 58 - Jun 58',
530
+ 'Jul 58 - Dec 58',
531
+ 'Jan 59 - Jun 59',
532
+ 'Jul 59 - Dec 59',
533
+ 'Jan 60 - Jun 60',
534
+ 'Jul 60 - Dec 60',
535
+ 'Jan 61 - Jun 61',
536
+ 'Jul 61 - Dec 61',
537
+ 'Jan 62 - Jun 62',
538
+ 'Jul 62 - Dec 62',
539
+ 'Jan 63 - Jun 63',
540
+ 'Jul 63 - Dec 63',
541
+ 'Jan 64 - Jun 64',
542
+ 'Jul 64 - Dec 64',
543
+ 'Jan 65 - Jun 65',
544
+ 'Jul 65 - Dec 65',
545
+ ]);
546
+ });
547
+ it('correctly aligns bins to exact year boundaries when binSnapping=year', async () => {
548
+ var _a;
549
+ const el = await fixture(html `
550
+ <histogram-date-range
551
+ binSnapping="year"
552
+ minDate="2000"
553
+ maxDate="2019"
554
+ bins="[10,20,30,40,50,60,70,80,90,100]"
555
+ ></histogram-date-range>
556
+ `);
557
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
558
+ const tooltips = Array.from(bars).map(b => b.dataset.tooltip);
559
+ expect(tooltips).to.eql([
560
+ '2000 - 2001',
561
+ '2002 - 2003',
562
+ '2004 - 2005',
563
+ '2006 - 2007',
564
+ '2008 - 2009',
565
+ '2010 - 2011',
566
+ '2012 - 2013',
567
+ '2014 - 2015',
568
+ '2016 - 2017',
569
+ '2018 - 2019',
570
+ ]);
571
+ });
572
+ it('correctly handles year snapping for years 0-99', async () => {
573
+ var _a;
574
+ const el = await fixture(html `
575
+ <histogram-date-range
576
+ binSnapping="year"
577
+ dateFormat="YYYY"
578
+ minDate="0020"
579
+ maxDate="0025"
580
+ bins="[1,2,3,4,5,6]"
581
+ ></histogram-date-range>
582
+ `);
583
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
584
+ const tooltips = Array.from(bars).map(b => b.dataset.tooltip);
585
+ expect(tooltips).to.eql(['20', '21', '22', '23', '24', '25']);
586
+ });
587
+ it('does not duplicate start/end date in tooltips when representing a single year', async () => {
588
+ var _a;
589
+ const el = await fixture(html `
590
+ <histogram-date-range
591
+ binSnapping="year"
592
+ dateFormat="YYYY"
593
+ minDate="2001"
594
+ maxDate="2005"
595
+ bins="[10,20,30,40,50]"
596
+ ></histogram-date-range>
597
+ `);
598
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
599
+ const tooltips = Array.from(bars).map(b => b.dataset.tooltip);
600
+ expect(tooltips).to.eql(['2001', '2002', '2003', '2004', '2005']);
601
+ });
602
+ it('falls back to default date format for tooltips if no tooltip date format provided', async () => {
603
+ var _a;
604
+ const el = await fixture(html `
605
+ <histogram-date-range
606
+ binSnapping="year"
607
+ minDate="2001"
608
+ maxDate="2005"
609
+ bins="[10,20,30,40,50]"
610
+ ></histogram-date-range>
611
+ `);
612
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
613
+ let tooltips = Array.from(bars).map(b => b.dataset.tooltip);
614
+ expect(tooltips).to.eql(['2001', '2002', '2003', '2004', '2005']); // default YYYY date format
615
+ el.dateFormat = 'YYYY/MM';
616
+ el.minDate = '2001/01';
617
+ el.maxDate = '2005/01';
618
+ await el.updateComplete;
619
+ // Should use dateFormat fallback for tooltips
620
+ tooltips = Array.from(bars).map(b => b.dataset.tooltip);
621
+ expect(tooltips).to.eql([
622
+ '2001/01 - 2001/12',
623
+ '2002/01 - 2002/12',
624
+ '2003/01 - 2003/12',
625
+ '2004/01 - 2004/12',
626
+ '2005/01 - 2005/12',
627
+ ]);
628
+ el.dateFormat = 'YYYY';
629
+ el.tooltipDateFormat = 'MMMM YYYY';
630
+ el.minDate = '2001';
631
+ el.maxDate = '2005';
632
+ await el.updateComplete;
633
+ // Should use defined tooltipDateFormat for tooltips
634
+ tooltips = Array.from(bars).map(b => b.dataset.tooltip);
635
+ expect(tooltips).to.eql([
636
+ 'January 2001 - December 2001',
637
+ 'January 2002 - December 2002',
638
+ 'January 2003 - December 2003',
639
+ 'January 2004 - December 2004',
640
+ 'January 2005 - December 2005',
641
+ ]);
642
+ });
643
+ it('has a disabled state', async () => {
644
+ var _a, _b, _c;
645
+ const el = await fixture(html `
646
+ <histogram-date-range
647
+ minDate="1900"
648
+ maxDate="2020"
649
+ disabled
650
+ bins="[33, 1, 100]"
651
+ >
652
+ </histogram-date-range>
653
+ `);
654
+ expect((_b = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.inner-container')) === null || _b === void 0 ? void 0 : _b.classList.contains('disabled')).to.eq(true);
655
+ const minSlider = (_c = el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#slider-min');
656
+ expect(Math.round(minSlider.getBoundingClientRect().x)).to.eq(8); // initial state
657
+ // attempt to slide to right
658
+ minSlider.dispatchEvent(new PointerEvent('pointerdown'));
659
+ await el.updateComplete;
660
+ // cursor is not draggable if disabled
661
+ expect(minSlider.classList.contains('draggable')).to.be.false;
662
+ // attempt to slide to right
663
+ window.dispatchEvent(new PointerEvent('pointermove', { clientX: 70 }));
664
+ await el.updateComplete;
665
+ // slider does not moved if element disabled
666
+ expect(Math.round(minSlider.getBoundingClientRect().x)).to.eq(8);
667
+ });
668
+ it('has a loading state with an activity indicator', async () => {
669
+ var _a, _b, _c, _d;
670
+ const el = await fixture(html `
671
+ <histogram-date-range
672
+ minDate="1900"
673
+ maxDate="2020"
674
+ loading
675
+ bins="[33, 1, 100]"
676
+ >
677
+ </histogram-date-range>
678
+ `);
679
+ expect((_d = (_c = (_b = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('ia-activity-indicator')) === null || _b === void 0 ? void 0 : _b.attributes) === null || _c === void 0 ? void 0 : _c.getNamedItem('mode')) === null || _d === void 0 ? void 0 : _d.value).to.eq('processing');
680
+ });
681
+ it('can use LitElement bound properties', async () => {
682
+ var _a, _b;
683
+ const el = await fixture(html `
684
+ <histogram-date-range
685
+ .minDate=${1900}
686
+ .maxDate=${'Dec 4, 2020'}
687
+ .minSelectedDate=${2012}
688
+ .maxSelectedDate=${2019}
689
+ .bins=${[33, 1, 100]}
690
+ >
691
+ </histogram-date-range>
692
+ `);
693
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
694
+ expect(minDateInput.value).to.eq('2012');
695
+ const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
696
+ expect(maxDateInput.value).to.eq('2019');
697
+ });
698
+ });
698
699
  //# sourceMappingURL=histogram-date-range.test.js.map