@internetarchive/histogram-date-range 1.2.1-alpha.1 → 1.2.2-alpha-webdev7377.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.
Files changed (35) hide show
  1. package/.editorconfig +29 -29
  2. package/.eslintrc.js +14 -14
  3. package/.github/workflows/ci.yml +30 -26
  4. package/LICENSE +661 -661
  5. package/README.md +113 -113
  6. package/demo/index.css +22 -22
  7. package/demo/index.html +159 -159
  8. package/dist/demo/js/app-root.d.ts +19 -19
  9. package/dist/demo/js/app-root.js +46 -46
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/src/histogram-date-range.d.ts +166 -159
  14. package/dist/src/histogram-date-range.js +856 -846
  15. package/dist/src/histogram-date-range.js.map +1 -1
  16. package/dist/test/histogram-date-range.test.d.ts +1 -1
  17. package/dist/test/histogram-date-range.test.js +488 -488
  18. package/dist/test/histogram-date-range.test.js.map +1 -1
  19. package/docs/demo/index.css +22 -22
  20. package/docs/demo/index.html +159 -159
  21. package/docs/dist/src/histogram-date-range.js +17 -12
  22. package/index.ts +1 -1
  23. package/package.json +85 -85
  24. package/snowpack.config.js +10 -10
  25. package/src/histogram-date-range.ts +923 -915
  26. package/test/histogram-date-range.test.ts +684 -684
  27. package/tsconfig.json +21 -21
  28. package/web-dev-server.config.mjs +28 -28
  29. package/web-test-runner.config.mjs +29 -29
  30. package/dist/demo/app-root.d.ts +0 -19
  31. package/dist/demo/app-root.js +0 -58
  32. package/dist/demo/app-root.js.map +0 -1
  33. package/dist/docs/_snowpack/pkg/@internetarchive/ia-activity-indicator/ia-activity-indicator.d.ts +0 -1
  34. package/dist/docs/_snowpack/pkg/@internetarchive/ia-activity-indicator/ia-activity-indicator.js +0 -2
  35. package/dist/docs/_snowpack/pkg/@internetarchive/ia-activity-indicator/ia-activity-indicator.js.map +0 -1
@@ -1,489 +1,489 @@
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(Array.from(minSlider.classList).join(' ')).to.eq('draggable');
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
- });
221
- it("emits a custom event when the element's date range changes", async () => {
222
- var _a;
223
- const el = await createCustomElementInHTMLContainer();
224
- el.updateDelay = 30; // set debounce delay of 30ms
225
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
226
- const updateEventPromise = oneEvent(el, 'histogramDateRangeUpdated');
227
- // simulate typing a new value into input
228
- minDateInput.value = '1955';
229
- minDateInput.dispatchEvent(new Event('blur'));
230
- // will wait longer than debounce delay
231
- const { detail } = await updateEventPromise;
232
- // verify that event is emitted
233
- expect(detail.minDate).to.equal('1/1/1955');
234
- expect(detail.maxDate).to.equal('12/4/2020');
235
- let eventCount = 0;
236
- el.addEventListener('histogramDateRangeUpdated', () => (eventCount += 1));
237
- // events are not sent if no change since the last event that was sent
238
- minDateInput.value = '1955';
239
- minDateInput.dispatchEvent(new Event('blur'));
240
- await aTimeout(60); // wait longer than debounce delay
241
- expect(eventCount).to.equal(0);
242
- const updateEventPromise2 = oneEvent(el, 'histogramDateRangeUpdated');
243
- // with the debounce, multiple quick changes only result in one event sent
244
- minDateInput.value = '1965';
245
- minDateInput.dispatchEvent(new Event('blur'));
246
- await aTimeout(10); // wait less than the debounce delay
247
- minDateInput.dispatchEvent(new Event('focus'));
248
- minDateInput.value = '1975';
249
- minDateInput.dispatchEvent(new Event('blur'));
250
- await aTimeout(10);
251
- minDateInput.dispatchEvent(new Event('focus'));
252
- minDateInput.value = '1985';
253
- minDateInput.dispatchEvent(new Event('blur'));
254
- await aTimeout(10);
255
- const event2 = await updateEventPromise2;
256
- expect(event2.detail.minDate).to.equal('1/1/1985');
257
- expect(eventCount).to.equal(1); // only one event was fired
258
- });
259
- it('shows/hides tooltip when hovering over (or pointing at) a bar', async () => {
260
- var _a, _b;
261
- const el = await createCustomElementInHTMLContainer();
262
- // include a number which will require commas (1,000,000)
263
- el.bins = [1000000, 1, 100];
264
- await aTimeout(10);
265
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
266
- const tooltip = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#tooltip');
267
- expect(tooltip.innerText).to.eq('');
268
- // hover
269
- bars[0].dispatchEvent(new PointerEvent('pointerenter'));
270
- await el.updateComplete;
271
- expect(tooltip.innerText).to.match(/^1,000,000 items\n1\/1\/1900 - 4\/23\/1940/);
272
- expect(getComputedStyle(tooltip).display).to.eq('block');
273
- // leave
274
- bars[0].dispatchEvent(new PointerEvent('pointerleave'));
275
- await el.updateComplete;
276
- expect(getComputedStyle(tooltip).display).to.eq('none');
277
- expect(tooltip.innerText).to.eq('');
278
- // ensure singular item is not pluralized
279
- bars[1].dispatchEvent(new PointerEvent('pointerenter'));
280
- await el.updateComplete;
281
- expect(tooltip.innerText).to.match(/^1 item\n4\/23\/1940 - 8\/13\/1980/);
282
- });
283
- it('does not show tooltip while dragging', async () => {
284
- var _a, _b, _c;
285
- const el = await createCustomElementInHTMLContainer();
286
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
287
- const tooltip = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#tooltip');
288
- expect(tooltip.innerText).to.eq('');
289
- const minSlider = (_c = el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#slider-min');
290
- // pointer down and slide right
291
- minSlider.dispatchEvent(new PointerEvent('pointerdown'));
292
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: 100 }));
293
- await el.updateComplete;
294
- // hover over bar
295
- bars[0].dispatchEvent(new PointerEvent('pointerenter'));
296
- await el.updateComplete;
297
- // tooltip display is suppressed while dragging
298
- expect(tooltip.style.display).to.eq('');
299
- });
300
- it('passes the a11y audit', async () => {
301
- await fixture(subject).then(el => expect(el).shadowDom.to.be.accessible());
302
- });
303
- it('allows range to be pre-selected', async () => {
304
- var _a, _b;
305
- const el = await fixture(html `
306
- <histogram-date-range
307
- minDate="1900"
308
- maxDate="Dec 4, 2020"
309
- minSelectedDate="2012"
310
- maxSelectedDate="2019"
311
- bins="[33, 1, 100]"
312
- >
313
- </histogram-date-range>
314
- `);
315
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
316
- expect(minDateInput.value).to.eq('2012');
317
- const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
318
- expect(maxDateInput.value).to.eq('2019');
319
- });
320
- it('extends the selected range when the histogram is clicked outside of the current range', async () => {
321
- var _a, _b;
322
- const el = await fixture(html `
323
- <histogram-date-range
324
- minDate="1900"
325
- maxDate="2020"
326
- minSelectedDate="1950"
327
- maxSelectedDate="1955"
328
- bins="[33, 1, 1, 1, 10, 10, 1, 1, 1, 50, 100]"
329
- >
330
- </histogram-date-range>
331
- `);
332
- const leftBarToClick = Array.from((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar'))[1]; // click on second bar to the left
333
- leftBarToClick.dispatchEvent(new Event('click'));
334
- await el.updateComplete;
335
- expect(el.minSelectedDate).to.eq('1910'); // range was extended to left
336
- const rightBarToClick = Array.from((_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelectorAll('.bar'))[8]; // click on second bar from the right
337
- rightBarToClick.dispatchEvent(new Event('click'));
338
- expect(el.maxSelectedDate).to.eq('1998'); // range was extended to right
339
- });
340
- it('narrows the selected range when the histogram is clicked inside of the current range', async () => {
341
- var _a, _b;
342
- const el = await fixture(html `
343
- <histogram-date-range
344
- minDate="1900"
345
- maxDate="2020"
346
- minSelectedDate="1900"
347
- maxSelectedDate="2020"
348
- bins="[33, 1, 1, 1, 10, 10, 1, 1, 1, 50, 100]"
349
- >
350
- </histogram-date-range>
351
- `);
352
- ///////////////////////////////////////////////
353
- // NB: the slider nearest the clicked bar moves
354
- ///////////////////////////////////////////////
355
- const leftBarToClick = Array.from((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar'))[3]; // click on fourth bar to the left
356
- leftBarToClick.dispatchEvent(new Event('click'));
357
- expect(el.minSelectedDate).to.eq('1932'); // range was extended to the right
358
- const rightBarToClick = Array.from((_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelectorAll('.bar'))[8]; // click on second bar from the right
359
- rightBarToClick.dispatchEvent(new Event('click'));
360
- expect(el.maxSelectedDate).to.eq('1998'); // range was extended to the left
361
- });
362
- it('handles invalid pre-selected range by defaulting to overall max and min', async () => {
363
- var _a, _b;
364
- const el = await fixture(html `
365
- <histogram-date-range
366
- minDate="1900"
367
- maxDate="2020"
368
- minSelectedDate="2000xyz"
369
- maxSelectedDate="5000"
370
- bins="[33, 1, 100]"
371
- >
372
- </histogram-date-range>
373
- `);
374
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
375
- // malformed min date defaults to overall min
376
- expect(minDateInput.value).to.eq('1900');
377
- const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
378
- // well-formed max date is allowed
379
- expect(maxDateInput.value).to.eq('5000');
380
- });
381
- it('handles year values less than 1000 by overriding date format to just display year', async () => {
382
- var _a, _b;
383
- const el = await fixture(html `
384
- <histogram-date-range
385
- dateFormat="M/D/YYYY"
386
- minDate="-2000"
387
- maxDate="2000"
388
- minSelectedDate="-500"
389
- maxSelectedDate="500"
390
- bins="[33, 1, 100]"
391
- >
392
- </histogram-date-range>
393
- `);
394
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
395
- expect(minDateInput.value).to.eq('-500');
396
- const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
397
- expect(maxDateInput.value).to.eq('500');
398
- });
399
- it('handles missing data', async () => {
400
- var _a, _b;
401
- let el = await fixture(html `<histogram-date-range>
402
- minDate="1900" maxDate="2020" bins=""
403
- </histogram-date-range>`);
404
- expect((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.innerHTML).to.contain('no data');
405
- el = await fixture(html `<histogram-date-range
406
- minDate="1900"
407
- maxDate="2020"
408
- bins="[]"
409
- missingDataMessage="no data available"
410
- ></histogram-date-range>`);
411
- expect((_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.innerHTML).to.contain('no data available');
412
- });
413
- it('correctly displays data consisting of a single bin', async () => {
414
- var _a;
415
- const el = await fixture(html `
416
- <histogram-date-range minDate="2020" maxDate="2020" bins="[50]">
417
- </histogram-date-range>
418
- `);
419
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
420
- const heights = Array.from(bars).map(b => b.height.baseVal.value);
421
- expect(heights).to.eql([157]);
422
- });
423
- it('correctly displays small diff between max and min values', async () => {
424
- var _a;
425
- const el = await fixture(html `
426
- <histogram-date-range bins="[1519,2643,1880,2041,1638,1441]">
427
- </histogram-date-range>
428
- `);
429
- const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
430
- const heights = Array.from(bars).map(b => b.height.baseVal.value);
431
- expect(heights).to.eql([37, 40, 38, 38, 37, 36]);
432
- });
433
- it('has a disabled state', async () => {
434
- var _a, _b, _c;
435
- const el = await fixture(html `
436
- <histogram-date-range
437
- minDate="1900"
438
- maxDate="2020"
439
- disabled
440
- bins="[33, 1, 100]"
441
- >
442
- </histogram-date-range>
443
- `);
444
- 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);
445
- const minSlider = (_c = el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#slider-min');
446
- expect(Math.round(minSlider.getBoundingClientRect().x)).to.eq(8); // initial state
447
- // attempt to slide to right
448
- minSlider.dispatchEvent(new PointerEvent('pointerdown'));
449
- await el.updateComplete;
450
- // cursor is not draggable if disabled
451
- expect(Array.from(minSlider.classList).join(' ')).to.eq('');
452
- // attempt to slide to right
453
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: 70 }));
454
- await el.updateComplete;
455
- // slider does not moved if element disabled
456
- expect(Math.round(minSlider.getBoundingClientRect().x)).to.eq(8);
457
- });
458
- it('has a loading state with an activity indicator', async () => {
459
- var _a, _b, _c, _d;
460
- const el = await fixture(html `
461
- <histogram-date-range
462
- minDate="1900"
463
- maxDate="2020"
464
- loading
465
- bins="[33, 1, 100]"
466
- >
467
- </histogram-date-range>
468
- `);
469
- 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');
470
- });
471
- it('can use LitElement bound properties', async () => {
472
- var _a, _b;
473
- const el = await fixture(html `
474
- <histogram-date-range
475
- .minDate=${1900}
476
- .maxDate=${'Dec 4, 2020'}
477
- .minSelectedDate=${2012}
478
- .maxSelectedDate=${2019}
479
- .bins=${[33, 1, 100]}
480
- >
481
- </histogram-date-range>
482
- `);
483
- const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
484
- expect(minDateInput.value).to.eq('2012');
485
- const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
486
- expect(maxDateInput.value).to.eq('2019');
487
- });
488
- });
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(Array.from(minSlider.classList).join(' ')).to.eq('draggable');
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
+ });
221
+ it("emits a custom event when the element's date range changes", async () => {
222
+ var _a;
223
+ const el = await createCustomElementInHTMLContainer();
224
+ el.updateDelay = 30; // set debounce delay of 30ms
225
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
226
+ const updateEventPromise = oneEvent(el, 'histogramDateRangeUpdated');
227
+ // simulate typing a new value into input
228
+ minDateInput.value = '1955';
229
+ minDateInput.dispatchEvent(new Event('blur'));
230
+ // will wait longer than debounce delay
231
+ const { detail } = await updateEventPromise;
232
+ // verify that event is emitted
233
+ expect(detail.minDate).to.equal('1/1/1955');
234
+ expect(detail.maxDate).to.equal('12/4/2020');
235
+ let eventCount = 0;
236
+ el.addEventListener('histogramDateRangeUpdated', () => (eventCount += 1));
237
+ // events are not sent if no change since the last event that was sent
238
+ minDateInput.value = '1955';
239
+ minDateInput.dispatchEvent(new Event('blur'));
240
+ await aTimeout(60); // wait longer than debounce delay
241
+ expect(eventCount).to.equal(0);
242
+ const updateEventPromise2 = oneEvent(el, 'histogramDateRangeUpdated');
243
+ // with the debounce, multiple quick changes only result in one event sent
244
+ minDateInput.value = '1965';
245
+ minDateInput.dispatchEvent(new Event('blur'));
246
+ await aTimeout(10); // wait less than the debounce delay
247
+ minDateInput.dispatchEvent(new Event('focus'));
248
+ minDateInput.value = '1975';
249
+ minDateInput.dispatchEvent(new Event('blur'));
250
+ await aTimeout(10);
251
+ minDateInput.dispatchEvent(new Event('focus'));
252
+ minDateInput.value = '1985';
253
+ minDateInput.dispatchEvent(new Event('blur'));
254
+ await aTimeout(10);
255
+ const event2 = await updateEventPromise2;
256
+ expect(event2.detail.minDate).to.equal('1/1/1985');
257
+ expect(eventCount).to.equal(1); // only one event was fired
258
+ });
259
+ it('shows/hides tooltip when hovering over (or pointing at) a bar', async () => {
260
+ var _a, _b;
261
+ const el = await createCustomElementInHTMLContainer();
262
+ // include a number which will require commas (1,000,000)
263
+ el.bins = [1000000, 1, 100];
264
+ await aTimeout(10);
265
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
266
+ const tooltip = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#tooltip');
267
+ expect(tooltip.innerText).to.eq('');
268
+ // hover
269
+ bars[0].dispatchEvent(new PointerEvent('pointerenter'));
270
+ await el.updateComplete;
271
+ expect(tooltip.innerText).to.match(/^1,000,000 items\n1\/1\/1900 - 4\/23\/1940/);
272
+ expect(getComputedStyle(tooltip).display).to.eq('block');
273
+ // leave
274
+ bars[0].dispatchEvent(new PointerEvent('pointerleave'));
275
+ await el.updateComplete;
276
+ expect(getComputedStyle(tooltip).display).to.eq('none');
277
+ expect(tooltip.innerText).to.eq('');
278
+ // ensure singular item is not pluralized
279
+ bars[1].dispatchEvent(new PointerEvent('pointerenter'));
280
+ await el.updateComplete;
281
+ expect(tooltip.innerText).to.match(/^1 item\n4\/23\/1940 - 8\/13\/1980/);
282
+ });
283
+ it('does not show tooltip while dragging', async () => {
284
+ var _a, _b, _c;
285
+ const el = await createCustomElementInHTMLContainer();
286
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
287
+ const tooltip = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#tooltip');
288
+ expect(tooltip.innerText).to.eq('');
289
+ const minSlider = (_c = el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#slider-min');
290
+ // pointer down and slide right
291
+ minSlider.dispatchEvent(new PointerEvent('pointerdown'));
292
+ window.dispatchEvent(new PointerEvent('pointermove', { clientX: 100 }));
293
+ await el.updateComplete;
294
+ // hover over bar
295
+ bars[0].dispatchEvent(new PointerEvent('pointerenter'));
296
+ await el.updateComplete;
297
+ // tooltip display is suppressed while dragging
298
+ expect(tooltip.style.display).to.eq('');
299
+ });
300
+ it('passes the a11y audit', async () => {
301
+ await fixture(subject).then(el => expect(el).shadowDom.to.be.accessible());
302
+ });
303
+ it('allows range to be pre-selected', async () => {
304
+ var _a, _b;
305
+ const el = await fixture(html `
306
+ <histogram-date-range
307
+ minDate="1900"
308
+ maxDate="Dec 4, 2020"
309
+ minSelectedDate="2012"
310
+ maxSelectedDate="2019"
311
+ bins="[33, 1, 100]"
312
+ >
313
+ </histogram-date-range>
314
+ `);
315
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
316
+ expect(minDateInput.value).to.eq('2012');
317
+ const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
318
+ expect(maxDateInput.value).to.eq('2019');
319
+ });
320
+ it('extends the selected range when the histogram is clicked outside of the current range', async () => {
321
+ var _a, _b;
322
+ const el = await fixture(html `
323
+ <histogram-date-range
324
+ minDate="1900"
325
+ maxDate="2020"
326
+ minSelectedDate="1950"
327
+ maxSelectedDate="1955"
328
+ bins="[33, 1, 1, 1, 10, 10, 1, 1, 1, 50, 100]"
329
+ >
330
+ </histogram-date-range>
331
+ `);
332
+ const leftBarToClick = Array.from((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar'))[1]; // click on second bar to the left
333
+ leftBarToClick.dispatchEvent(new Event('click'));
334
+ await el.updateComplete;
335
+ expect(el.minSelectedDate).to.eq('1910'); // range was extended to left
336
+ const rightBarToClick = Array.from((_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelectorAll('.bar'))[8]; // click on second bar from the right
337
+ rightBarToClick.dispatchEvent(new Event('click'));
338
+ expect(el.maxSelectedDate).to.eq('1998'); // range was extended to right
339
+ });
340
+ it('narrows the selected range when the histogram is clicked inside of the current range', async () => {
341
+ var _a, _b;
342
+ const el = await fixture(html `
343
+ <histogram-date-range
344
+ minDate="1900"
345
+ maxDate="2020"
346
+ minSelectedDate="1900"
347
+ maxSelectedDate="2020"
348
+ bins="[33, 1, 1, 1, 10, 10, 1, 1, 1, 50, 100]"
349
+ >
350
+ </histogram-date-range>
351
+ `);
352
+ ///////////////////////////////////////////////
353
+ // NB: the slider nearest the clicked bar moves
354
+ ///////////////////////////////////////////////
355
+ const leftBarToClick = Array.from((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar'))[3]; // click on fourth bar to the left
356
+ leftBarToClick.dispatchEvent(new Event('click'));
357
+ expect(el.minSelectedDate).to.eq('1932'); // range was extended to the right
358
+ const rightBarToClick = Array.from((_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelectorAll('.bar'))[8]; // click on second bar from the right
359
+ rightBarToClick.dispatchEvent(new Event('click'));
360
+ expect(el.maxSelectedDate).to.eq('1998'); // range was extended to the left
361
+ });
362
+ it('handles invalid pre-selected range by defaulting to overall max and min', async () => {
363
+ var _a, _b;
364
+ const el = await fixture(html `
365
+ <histogram-date-range
366
+ minDate="1900"
367
+ maxDate="2020"
368
+ minSelectedDate="2000xyz"
369
+ maxSelectedDate="5000"
370
+ bins="[33, 1, 100]"
371
+ >
372
+ </histogram-date-range>
373
+ `);
374
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
375
+ // malformed min date defaults to overall min
376
+ expect(minDateInput.value).to.eq('1900');
377
+ const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
378
+ // well-formed max date is allowed
379
+ expect(maxDateInput.value).to.eq('5000');
380
+ });
381
+ it('handles year values less than 1000 by overriding date format to just display year', async () => {
382
+ var _a, _b;
383
+ const el = await fixture(html `
384
+ <histogram-date-range
385
+ dateFormat="M/D/YYYY"
386
+ minDate="-2000"
387
+ maxDate="2000"
388
+ minSelectedDate="-500"
389
+ maxSelectedDate="500"
390
+ bins="[33, 1, 100]"
391
+ >
392
+ </histogram-date-range>
393
+ `);
394
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
395
+ expect(minDateInput.value).to.eq('-500');
396
+ const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
397
+ expect(maxDateInput.value).to.eq('500');
398
+ });
399
+ it('handles missing data', async () => {
400
+ var _a, _b;
401
+ let el = await fixture(html `<histogram-date-range>
402
+ minDate="1900" maxDate="2020" bins=""
403
+ </histogram-date-range>`);
404
+ expect((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.innerHTML).to.contain('no data');
405
+ el = await fixture(html `<histogram-date-range
406
+ minDate="1900"
407
+ maxDate="2020"
408
+ bins="[]"
409
+ missingDataMessage="no data available"
410
+ ></histogram-date-range>`);
411
+ expect((_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.innerHTML).to.contain('no data available');
412
+ });
413
+ it('correctly displays data consisting of a single bin', async () => {
414
+ var _a;
415
+ const el = await fixture(html `
416
+ <histogram-date-range minDate="2020" maxDate="2020" bins="[50]">
417
+ </histogram-date-range>
418
+ `);
419
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
420
+ const heights = Array.from(bars).map(b => b.height.baseVal.value);
421
+ expect(heights).to.eql([157]);
422
+ });
423
+ it('correctly displays small diff between max and min values', async () => {
424
+ var _a;
425
+ const el = await fixture(html `
426
+ <histogram-date-range bins="[1519,2643,1880,2041,1638,1441]">
427
+ </histogram-date-range>
428
+ `);
429
+ const bars = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.bar');
430
+ const heights = Array.from(bars).map(b => b.height.baseVal.value);
431
+ expect(heights).to.eql([37, 40, 38, 38, 37, 36]);
432
+ });
433
+ it('has a disabled state', async () => {
434
+ var _a, _b, _c;
435
+ const el = await fixture(html `
436
+ <histogram-date-range
437
+ minDate="1900"
438
+ maxDate="2020"
439
+ disabled
440
+ bins="[33, 1, 100]"
441
+ >
442
+ </histogram-date-range>
443
+ `);
444
+ 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);
445
+ const minSlider = (_c = el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#slider-min');
446
+ expect(Math.round(minSlider.getBoundingClientRect().x)).to.eq(8); // initial state
447
+ // attempt to slide to right
448
+ minSlider.dispatchEvent(new PointerEvent('pointerdown'));
449
+ await el.updateComplete;
450
+ // cursor is not draggable if disabled
451
+ expect(Array.from(minSlider.classList).join(' ')).to.eq('');
452
+ // attempt to slide to right
453
+ window.dispatchEvent(new PointerEvent('pointermove', { clientX: 70 }));
454
+ await el.updateComplete;
455
+ // slider does not moved if element disabled
456
+ expect(Math.round(minSlider.getBoundingClientRect().x)).to.eq(8);
457
+ });
458
+ it('has a loading state with an activity indicator', async () => {
459
+ var _a, _b, _c, _d;
460
+ const el = await fixture(html `
461
+ <histogram-date-range
462
+ minDate="1900"
463
+ maxDate="2020"
464
+ loading
465
+ bins="[33, 1, 100]"
466
+ >
467
+ </histogram-date-range>
468
+ `);
469
+ 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');
470
+ });
471
+ it('can use LitElement bound properties', async () => {
472
+ var _a, _b;
473
+ const el = await fixture(html `
474
+ <histogram-date-range
475
+ .minDate=${1900}
476
+ .maxDate=${'Dec 4, 2020'}
477
+ .minSelectedDate=${2012}
478
+ .maxSelectedDate=${2019}
479
+ .bins=${[33, 1, 100]}
480
+ >
481
+ </histogram-date-range>
482
+ `);
483
+ const minDateInput = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#date-min');
484
+ expect(minDateInput.value).to.eq('2012');
485
+ const maxDateInput = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('#date-max');
486
+ expect(maxDateInput.value).to.eq('2019');
487
+ });
488
+ });
489
489
  //# sourceMappingURL=histogram-date-range.test.js.map