@internetarchive/collection-browser 4.1.0-alpha-webdev8164.0 → 4.1.0-alpha-webdev8186.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 (51) hide show
  1. package/.editorconfig +29 -29
  2. package/.github/workflows/ci.yml +27 -27
  3. package/.github/workflows/gh-pages-main.yml +39 -39
  4. package/.github/workflows/npm-publish.yml +39 -39
  5. package/.github/workflows/pr-preview.yml +38 -38
  6. package/.husky/pre-commit +4 -4
  7. package/.prettierignore +1 -1
  8. package/LICENSE +661 -661
  9. package/README.md +83 -83
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.js.map +1 -1
  12. package/dist/src/collection-browser.js +3 -13
  13. package/dist/src/collection-browser.js.map +1 -1
  14. package/dist/src/collection-facets/facets-template.js +0 -5
  15. package/dist/src/collection-facets/facets-template.js.map +1 -1
  16. package/dist/src/collection-facets/more-facets-content.d.ts +8 -47
  17. package/dist/src/collection-facets/more-facets-content.js +83 -382
  18. package/dist/src/collection-facets/more-facets-content.js.map +1 -1
  19. package/dist/src/collection-facets/more-facets-pagination.d.ts +0 -10
  20. package/dist/src/collection-facets/more-facets-pagination.js +1 -64
  21. package/dist/src/collection-facets/more-facets-pagination.js.map +1 -1
  22. package/dist/src/sort-filter-bar/sort-filter-bar.d.ts +13 -172
  23. package/dist/src/sort-filter-bar/sort-filter-bar.js +37 -546
  24. package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -1
  25. package/dist/test/collection-browser.test.js +8 -13
  26. package/dist/test/collection-browser.test.js.map +1 -1
  27. package/dist/test/collection-facets/more-facets-content.test.js +3 -154
  28. package/dist/test/collection-facets/more-facets-content.test.js.map +1 -1
  29. package/dist/test/collection-facets/more-facets-pagination.test.js +0 -60
  30. package/dist/test/collection-facets/more-facets-pagination.test.js.map +1 -1
  31. package/dist/test/sort-filter-bar/sort-filter-bar.test.js +86 -401
  32. package/dist/test/sort-filter-bar/sort-filter-bar.test.js.map +1 -1
  33. package/eslint.config.mjs +53 -53
  34. package/index.html +24 -24
  35. package/index.ts +1 -0
  36. package/local.archive.org.cert +86 -86
  37. package/local.archive.org.key +27 -27
  38. package/package.json +121 -121
  39. package/renovate.json +6 -6
  40. package/src/collection-browser.ts +3 -13
  41. package/src/collection-facets/facets-template.ts +0 -5
  42. package/src/collection-facets/more-facets-content.ts +94 -411
  43. package/src/collection-facets/more-facets-pagination.ts +1 -73
  44. package/src/sort-filter-bar/sort-filter-bar.ts +42 -603
  45. package/test/collection-browser.test.ts +9 -20
  46. package/test/collection-facets/more-facets-content.test.ts +3 -218
  47. package/test/collection-facets/more-facets-pagination.test.ts +0 -84
  48. package/test/sort-filter-bar/sort-filter-bar.test.ts +110 -566
  49. package/tsconfig.json +25 -25
  50. package/web-dev-server.config.mjs +30 -30
  51. package/web-test-runner.config.mjs +52 -52
@@ -2,35 +2,28 @@ import { expect, fixture } from '@open-wc/testing';
2
2
  import sinon from 'sinon';
3
3
  import { html } from 'lit';
4
4
  import type { IaDropdown } from '@internetarchive/ia-dropdown';
5
- import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
6
5
  import type { SortFilterBar } from '../../src/sort-filter-bar/sort-filter-bar';
7
6
  import { SortField, defaultSortAvailability } from '../../src/models';
8
7
 
9
8
  import '../../src/sort-filter-bar/sort-filter-bar';
10
9
 
11
- describe('Sort selector default buttons', async () => {
10
+ describe('Sort dropdown behavior', () => {
12
11
  let el: SortFilterBar;
13
- let sortSelectorContainer: HTMLElement | null | undefined;
14
- let desktopSortSelector: HTMLElement | null | undefined;
12
+ let sortDropdown: IaDropdown;
15
13
 
16
14
  beforeEach(async () => {
17
15
  el = await fixture<SortFilterBar>(html`
18
16
  <sort-filter-bar></sort-filter-bar>
19
17
  `);
20
- sortSelectorContainer = el.shadowRoot?.querySelector(
21
- '#sort-selector-container',
22
- );
23
- desktopSortSelector = sortSelectorContainer?.querySelector(
24
- '#desktop-sort-selector',
25
- );
26
-
27
- el.resizeObserver = new SharedResizeObserver();
18
+ sortDropdown = el.shadowRoot?.querySelector('#sort-dropdown') as IaDropdown;
28
19
  await el.updateComplete;
29
20
  });
30
21
 
31
22
  it('should render basic component', async () => {
23
+ const sortSelectorContainer = el.shadowRoot?.querySelector(
24
+ '#sort-selector-container',
25
+ );
32
26
  expect(sortSelectorContainer).to.exist;
33
- expect(desktopSortSelector).to.exist;
34
27
  });
35
28
 
36
29
  it('should render sort-by label', async () => {
@@ -47,49 +40,25 @@ describe('Sort selector default buttons', async () => {
47
40
  expect(sortDirections?.querySelector('.sort-direction-icon')).to.exist;
48
41
  });
49
42
 
50
- it('renders default set of sort options if not overridden', async () => {
51
- const allSortSelectors = desktopSortSelector?.querySelectorAll(
52
- 'button',
53
- ) as NodeListOf<HTMLButtonElement>;
54
- expect(allSortSelectors).to.exist;
55
- expect(allSortSelectors.length).to.equal(3);
56
- expect(allSortSelectors[0]?.textContent?.trim()).to.equal('Relevance');
57
- expect(allSortSelectors[1]?.textContent?.trim()).to.equal('Title');
58
- expect(allSortSelectors[2]?.textContent?.trim()).to.equal('Creator');
59
-
60
- const allSortDropdowns = desktopSortSelector?.querySelectorAll(
61
- 'ia-dropdown',
62
- ) as NodeListOf<IaDropdown>;
63
- expect(allSortDropdowns).to.exist;
64
- expect(allSortDropdowns.length).to.equal(2);
65
-
66
- expect(allSortDropdowns[0]?.options.length).to.equal(2);
67
- expect(allSortDropdowns[0]?.options.map(o => o.id)).to.deep.equal([
68
- SortField.weeklyview,
43
+ it('renders default set of sort options in dropdown', async () => {
44
+ expect(sortDropdown).to.exist;
45
+ expect(sortDropdown.options.map(o => o.id)).to.deep.equal([
46
+ SortField.relevance,
69
47
  SortField.alltimeview,
70
- ]);
71
- expect(allSortDropdowns[0]?.textContent?.trim()).to.equal('Weekly views');
72
-
73
- expect(allSortDropdowns[1]?.options.length).to.equal(4);
74
- expect(allSortDropdowns[1]?.options.map(o => o.id)).to.deep.equal([
48
+ SortField.weeklyview,
49
+ SortField.title,
75
50
  SortField.date,
76
51
  SortField.datearchived,
77
52
  SortField.datereviewed,
78
53
  SortField.dateadded,
54
+ SortField.creator,
79
55
  ]);
80
- expect(allSortDropdowns[1]?.textContent?.trim()).to.equal('Date published');
81
-
82
- // Relevance selected by default
83
- const defaultSortSelector =
84
- desktopSortSelector?.querySelector('button.selected');
85
- expect(defaultSortSelector?.textContent?.trim()).to.equal('Relevance');
86
56
  });
87
57
 
88
- it('renders an overridden set of sort options if specified', async () => {
58
+ it('respects overridden sort field availability', async () => {
89
59
  const customSortAvailability: Record<SortField, boolean> = {
90
60
  ...defaultSortAvailability,
91
61
  [SortField.title]: false,
92
- [SortField.datefavorited]: true,
93
62
  [SortField.datearchived]: false,
94
63
  [SortField.datereviewed]: false,
95
64
  [SortField.creator]: false,
@@ -98,319 +67,50 @@ describe('Sort selector default buttons', async () => {
98
67
  el.sortFieldAvailability = customSortAvailability;
99
68
  await el.updateComplete;
100
69
 
101
- const allSortSelectors = desktopSortSelector?.querySelectorAll(
102
- 'button',
103
- ) as NodeListOf<HTMLButtonElement>;
104
- expect(allSortSelectors).to.exist;
105
- expect(allSortSelectors.length).to.equal(1);
106
- expect(allSortSelectors[0]?.textContent?.trim()).to.equal('Relevance');
107
-
108
- const allSortDropdowns = desktopSortSelector?.querySelectorAll(
109
- 'ia-dropdown',
110
- ) as NodeListOf<IaDropdown>;
111
- expect(allSortDropdowns).to.exist;
112
- expect(allSortDropdowns.length).to.equal(2);
113
-
114
- expect(allSortDropdowns[0]?.options.length).to.equal(2);
115
- expect(allSortDropdowns[0]?.options.map(o => o.id)).to.deep.equal([
116
- SortField.weeklyview,
70
+ const dropdown = el.shadowRoot?.querySelector(
71
+ '#sort-dropdown',
72
+ ) as IaDropdown;
73
+ expect(dropdown.options.length).to.equal(5);
74
+ expect(dropdown.options.map(o => o.id)).to.deep.equal([
75
+ SortField.relevance,
117
76
  SortField.alltimeview,
118
- ]);
119
-
120
- expect(allSortDropdowns[1]?.options.length).to.equal(3);
121
- expect(allSortDropdowns[1]?.options.map(o => o.id)).to.deep.equal([
122
- SortField.datefavorited,
77
+ SortField.weeklyview,
123
78
  SortField.date,
124
79
  SortField.dateadded,
125
80
  ]);
126
81
  });
127
82
 
128
- it('renders a views button instead of a dropdown if it would only have one option', async () => {
129
- const customSortAvailability: Record<SortField, boolean> = {
130
- ...defaultSortAvailability,
131
- // Disable weekly views (but keep All-time Views)
132
- [SortField.weeklyview]: false,
133
- };
134
-
135
- el.sortFieldAvailability = customSortAvailability;
136
- await el.updateComplete;
137
-
138
- const allSortSelectors = desktopSortSelector?.querySelectorAll(
139
- 'button',
140
- ) as NodeListOf<HTMLButtonElement>;
141
- expect(allSortSelectors).to.exist;
142
- expect(allSortSelectors.length).to.equal(4);
143
- expect(allSortSelectors[0]?.textContent?.trim()).to.equal('Relevance');
144
- expect(allSortSelectors[1]?.textContent?.trim()).to.equal('All-time views');
145
- expect(allSortSelectors[2]?.textContent?.trim()).to.equal('Title');
146
- expect(allSortSelectors[3]?.textContent?.trim()).to.equal('Creator');
147
-
148
- const allSortDropdowns = desktopSortSelector?.querySelectorAll(
149
- 'ia-dropdown',
150
- ) as NodeListOf<IaDropdown>;
151
- expect(allSortDropdowns).to.exist;
152
- expect(allSortDropdowns.length).to.equal(1);
153
- });
154
-
155
- it('renders a date button instead of a dropdown if it would only have one option', async () => {
156
- const customSortAvailability: Record<SortField, boolean> = {
157
- ...defaultSortAvailability,
158
- // Disable all default dates except Date Added
159
- [SortField.date]: false,
160
- [SortField.datearchived]: false,
161
- [SortField.datereviewed]: false,
162
- };
163
-
164
- el.sortFieldAvailability = customSortAvailability;
165
- await el.updateComplete;
166
-
167
- const allSortSelectors = desktopSortSelector?.querySelectorAll(
168
- 'button',
169
- ) as NodeListOf<HTMLButtonElement>;
170
- expect(allSortSelectors).to.exist;
171
- expect(allSortSelectors.length).to.equal(4);
172
- expect(allSortSelectors[0]?.textContent?.trim()).to.equal('Relevance');
173
- expect(allSortSelectors[1]?.textContent?.trim()).to.equal('Title');
174
- expect(allSortSelectors[2]?.textContent?.trim()).to.equal('Date added');
175
- expect(allSortSelectors[3]?.textContent?.trim()).to.equal('Creator');
176
-
177
- const allSortDropdowns = desktopSortSelector?.querySelectorAll(
178
- 'ia-dropdown',
179
- ) as NodeListOf<IaDropdown>;
180
- expect(allSortDropdowns).to.exist;
181
- expect(allSortDropdowns.length).to.equal(1);
182
- });
183
-
184
- it('does not render a views dropdown that would have zero available options', async () => {
185
- const customSortAvailability: Record<SortField, boolean> = {
186
- ...defaultSortAvailability,
187
- // Disable all view sorts
188
- [SortField.weeklyview]: false,
189
- [SortField.alltimeview]: false,
190
- };
191
-
192
- el.sortFieldAvailability = customSortAvailability;
193
- await el.updateComplete;
194
-
195
- const allSortSelectors = desktopSortSelector?.querySelectorAll(
196
- 'button',
197
- ) as NodeListOf<HTMLButtonElement>;
198
- expect(allSortSelectors).to.exist;
199
- expect(allSortSelectors.length).to.equal(3);
200
-
201
- const allSortDropdowns = desktopSortSelector?.querySelectorAll(
202
- 'ia-dropdown',
203
- ) as NodeListOf<IaDropdown>;
204
- expect(allSortDropdowns).to.exist;
205
- expect(allSortDropdowns.length).to.equal(1);
206
- expect(allSortDropdowns[0].options?.[0]?.id).to.equal(SortField.date);
207
- });
208
-
209
- it('does not render a date dropdown that would have zero available options', async () => {
210
- const customSortAvailability: Record<SortField, boolean> = {
211
- ...defaultSortAvailability,
212
- // Disable all date sorts
213
- [SortField.date]: false,
214
- [SortField.dateadded]: false,
215
- [SortField.datearchived]: false,
216
- [SortField.datereviewed]: false,
217
- };
218
-
219
- el.sortFieldAvailability = customSortAvailability;
220
- await el.updateComplete;
221
-
222
- const allSortSelectors = desktopSortSelector?.querySelectorAll(
223
- 'button',
224
- ) as NodeListOf<HTMLButtonElement>;
225
- expect(allSortSelectors).to.exist;
226
- expect(allSortSelectors.length).to.equal(3);
227
-
228
- const allSortDropdowns = desktopSortSelector?.querySelectorAll(
229
- 'ia-dropdown',
230
- ) as NodeListOf<IaDropdown>;
231
- expect(allSortDropdowns).to.exist;
232
- expect(allSortDropdowns.length).to.equal(1);
233
- expect(allSortDropdowns[0].options?.[0]?.id).to.equal(SortField.weeklyview);
234
- });
235
-
236
- it('allows changing the default views sort shown', async () => {
237
- el.defaultViewSort = SortField.alltimeview;
238
- await el.updateComplete;
239
-
240
- const viewsDropdown = el.shadowRoot?.querySelector(
241
- '#views-dropdown',
242
- ) as IaDropdown;
243
- expect(viewsDropdown).to.exist;
244
- expect(viewsDropdown.textContent?.trim()).to.equal('All-time views');
245
- });
246
-
247
- it('allows changing the default date sort shown', async () => {
248
- el.defaultDateSort = SortField.datereviewed;
83
+ it('shows the display name of the selected sort', async () => {
84
+ el.selectedSort = SortField.alltimeview;
249
85
  await el.updateComplete;
250
86
 
251
- const dateDropdown = el.shadowRoot?.querySelector(
252
- '#date-dropdown',
253
- ) as IaDropdown;
254
- expect(dateDropdown).to.exist;
255
- expect(dateDropdown.textContent?.trim()).to.equal('Date reviewed');
256
- });
257
-
258
- it('should render default view-sort selector', async () => {
259
- const defaultSortSelector = desktopSortSelector?.children
260
- .item(1)
261
- ?.querySelector('ia-dropdown');
262
- expect(defaultSortSelector?.textContent?.trim()).to.equal('Weekly views');
87
+ const label = sortDropdown?.querySelector('.dropdown-label');
88
+ expect(label?.textContent?.trim()).to.equal('All-time views');
263
89
  });
264
90
 
265
- it('should render active view-sort selectors', async () => {
266
- el.selectedSort = 'alltimeview' as SortField;
267
- await el.updateComplete;
268
-
269
- const defaultSortSelector = desktopSortSelector?.querySelector(
270
- 'ia-dropdown.selected',
271
- );
272
- expect(defaultSortSelector?.textContent?.trim()).to.equal('All-time views');
273
- });
274
-
275
- it('should render default title-sort selector', async () => {
276
- const defaultSortSelector = desktopSortSelector?.children
277
- .item(2)
278
- ?.querySelector('button');
279
- expect(defaultSortSelector?.textContent?.trim()).to.equal('Title');
280
- });
281
-
282
- it('should render default date-sort selector', async () => {
283
- const defaultSortSelector = desktopSortSelector?.children
284
- .item(3)
285
- ?.querySelector('ia-dropdown');
286
- expect(defaultSortSelector?.textContent?.trim()).to.equal('Date published');
287
- });
288
-
289
- it('should render active date-sort selectors', async () => {
290
- el.selectedSort = 'datereviewed' as SortField;
291
- await el.updateComplete;
91
+ it('changes selected sort when dropdown option selected', async () => {
92
+ expect(sortDropdown).to.exist;
292
93
 
293
- const defaultSortSelector = desktopSortSelector?.querySelector(
294
- 'ia-dropdown.selected',
94
+ sortDropdown.selectedOption = 'title';
95
+ const option = { id: 'title' };
96
+ sortDropdown.dispatchEvent(
97
+ new CustomEvent('optionSelected', { detail: { option } }),
295
98
  );
296
- expect(defaultSortSelector?.textContent?.trim()).to.equal('Date reviewed');
297
- });
298
-
299
- it('should render default creator-sort selector', async () => {
300
- const defaultSortSelector = desktopSortSelector?.children
301
- .item(4)
302
- ?.querySelector('button');
303
- expect(defaultSortSelector?.textContent?.trim()).to.equal('Creator');
304
- });
305
-
306
- it('handles click event on view-sort selector', async () => {
307
- const defaultSortSelector = desktopSortSelector?.children
308
- .item(1)
309
- ?.querySelector('.dropdown-label') as HTMLElement;
310
-
311
- defaultSortSelector?.click();
312
- await el.updateComplete;
313
-
314
- expect(el.selectedSort).to.equal('weeklyview');
315
- });
316
-
317
- it('handles click event on title selector', async () => {
318
- const defaultSortSelector = desktopSortSelector?.children
319
- .item(2)
320
- ?.querySelector('button');
321
-
322
- defaultSortSelector?.click();
323
99
  await el.updateComplete;
324
100
 
325
101
  expect(el.selectedSort).to.equal('title');
326
102
  });
327
103
 
328
- it('handles click event on date-sort selector', async () => {
329
- const defaultSortSelector = desktopSortSelector?.children
330
- .item(3)
331
- ?.querySelector('.dropdown-label') as HTMLElement;
332
-
333
- defaultSortSelector?.click();
334
- await el.updateComplete;
335
-
336
- expect(el.selectedSort).to.equal('date');
337
- });
338
-
339
- it('handles click event on creator selector', async () => {
340
- const defaultSortSelector = desktopSortSelector?.children
341
- .item(4)
342
- ?.querySelector('button');
343
-
344
- defaultSortSelector?.click();
345
- await el.updateComplete;
346
-
347
- expect(el.selectedSort).to.equal('creator');
348
- });
349
-
350
- it('handles click event on relevance selector', async () => {
351
- el.sortFieldAvailability = {
352
- ...el.sortFieldAvailability,
353
- [SortField.relevance]: true,
354
- };
355
- el.selectedSort = 'title' as SortField;
356
- await el.updateComplete;
357
-
358
- const defaultSortSelector = desktopSortSelector?.children
359
- .item(0)
360
- ?.querySelector('button');
361
-
362
- defaultSortSelector?.click();
363
- await el.updateComplete;
364
-
365
- expect(el.selectedSort).to.equal('relevance');
366
- });
367
-
368
- it('handles return/space key event on view-sort selector', async () => {
369
- const defaultSortSelector = desktopSortSelector?.children
370
- .item(1)
371
- ?.querySelector('.dropdown-label') as HTMLElement;
372
-
373
- el.selectedSort = 'relevance' as SortField;
374
- const enterEvent = new KeyboardEvent('keydown', { key: 'Enter' });
375
- defaultSortSelector?.dispatchEvent(enterEvent);
104
+ it('selects a sort option by clicking it in the dropdown', async () => {
105
+ el.selectedSort = SortField.title;
376
106
  await el.updateComplete;
377
107
 
378
- expect(el.selectedSort).to.equal('weeklyview');
379
-
380
- el.selectedSort = 'relevance' as SortField;
381
- const spaceEvent = new KeyboardEvent('keydown', { key: ' ' });
382
- defaultSortSelector?.dispatchEvent(spaceEvent);
383
- await el.updateComplete;
384
-
385
- expect(el.selectedSort).to.equal('weeklyview');
386
- });
387
-
388
- it('handles return/space key event on date-sort selector', async () => {
389
- const defaultSortSelector = desktopSortSelector?.children
390
- .item(3)
391
- ?.querySelector('.dropdown-label') as HTMLElement;
392
-
393
- el.selectedSort = 'relevance' as SortField;
394
- const enterEvent = new KeyboardEvent('keydown', { key: 'Enter' });
395
- defaultSortSelector?.dispatchEvent(enterEvent);
396
- await el.updateComplete;
397
-
398
- expect(el.selectedSort).to.equal('date');
399
-
400
- el.selectedSort = 'relevance' as SortField;
401
- const spaceEvent = new KeyboardEvent('keydown', { key: ' ' });
402
- defaultSortSelector?.dispatchEvent(spaceEvent);
403
- await el.updateComplete;
404
-
405
- expect(el.selectedSort).to.equal('date');
406
- });
407
-
408
- it('handles click event on view-sort dropdown option', async () => {
409
- const defaultSortSelector = desktopSortSelector?.children
410
- .item(1)
411
- ?.querySelector('ia-dropdown') as IaDropdown;
108
+ const dropdown = el.shadowRoot?.querySelector(
109
+ '#sort-dropdown',
110
+ ) as IaDropdown;
111
+ expect(dropdown).to.exist;
412
112
 
413
- const firstOption = defaultSortSelector?.shadowRoot?.querySelector(
113
+ const firstOption = dropdown?.shadowRoot?.querySelector(
414
114
  'li > button',
415
115
  ) as HTMLButtonElement;
416
116
  expect(firstOption).to.exist;
@@ -418,36 +118,35 @@ describe('Sort selector default buttons', async () => {
418
118
  firstOption?.click();
419
119
  await el.updateComplete;
420
120
 
421
- expect(el.selectedSort).to.equal('weeklyview');
121
+ // The first option is relevance by default
122
+ expect(el.selectedSort).to.equal(SortField.relevance);
422
123
  });
423
124
 
424
- it('handles click event on date-sort dropdown option', async () => {
425
- const defaultSortSelector = desktopSortSelector?.children
426
- .item(3)
427
- ?.querySelector('ia-dropdown') as IaDropdown;
125
+ it('emits sortChanged event when sort option selected', async () => {
126
+ const sortChangedHandler = sinon.spy();
127
+ el.addEventListener('sortChanged', sortChangedHandler);
428
128
 
429
- const firstOption = defaultSortSelector?.shadowRoot?.querySelector(
430
- 'li > button',
431
- ) as HTMLButtonElement;
432
- expect(firstOption).to.exist;
433
-
434
- firstOption?.click();
129
+ const option = { id: SortField.title };
130
+ sortDropdown.dispatchEvent(
131
+ new CustomEvent('optionSelected', { detail: { option } }),
132
+ );
435
133
  await el.updateComplete;
436
134
 
437
- expect(el.selectedSort).to.equal('date');
135
+ expect(sortChangedHandler.calledOnce).to.be.true;
136
+ const eventDetail = sortChangedHandler.firstCall.args[0].detail;
137
+ expect(eventDetail.selectedSort).to.equal(SortField.title);
138
+ expect(eventDetail.sortDirection).to.equal('asc');
438
139
  });
439
140
 
440
- it('shows view sort selector backdrop when view sort open', async () => {
441
- const defaultSortSelector = desktopSortSelector?.children
442
- .item(1)
443
- ?.querySelector('ia-dropdown') as IaDropdown;
141
+ it('renders sort selector backdrop when dropdown is open', async () => {
142
+ expect(sortDropdown).to.exist;
444
143
 
445
- const caret = defaultSortSelector?.shadowRoot?.querySelector(
144
+ const caret = sortDropdown?.shadowRoot?.querySelector(
446
145
  '.caret',
447
146
  ) as HTMLElement;
448
147
  expect(caret).to.exist;
449
148
 
450
- caret?.click();
149
+ caret!.click();
451
150
  await el.updateComplete;
452
151
 
453
152
  let backdrop = el.shadowRoot?.querySelector(
@@ -455,7 +154,8 @@ describe('Sort selector default buttons', async () => {
455
154
  ) as HTMLElement;
456
155
  expect(backdrop).to.exist;
457
156
 
458
- backdrop?.click();
157
+ // Clicking the backdrop should close the dropdown
158
+ backdrop!.click();
459
159
  await el.updateComplete;
460
160
 
461
161
  backdrop = el.shadowRoot?.querySelector(
@@ -464,17 +164,15 @@ describe('Sort selector default buttons', async () => {
464
164
  expect(backdrop).not.to.exist;
465
165
  });
466
166
 
467
- it('shows date sort selector backdrop when date sort open', async () => {
468
- const defaultSortSelector = desktopSortSelector?.children
469
- .item(3)
470
- ?.querySelector('ia-dropdown') as IaDropdown;
167
+ it('pressing Escape key closes the dropdown', async () => {
168
+ expect(sortDropdown).to.exist;
471
169
 
472
- const caret = defaultSortSelector?.shadowRoot?.querySelector(
170
+ const caret = sortDropdown?.shadowRoot?.querySelector(
473
171
  '.caret',
474
172
  ) as HTMLElement;
475
173
  expect(caret).to.exist;
476
174
 
477
- caret?.click();
175
+ caret!.click();
478
176
  await el.updateComplete;
479
177
 
480
178
  let backdrop = el.shadowRoot?.querySelector(
@@ -482,7 +180,7 @@ describe('Sort selector default buttons', async () => {
482
180
  ) as HTMLElement;
483
181
  expect(backdrop).to.exist;
484
182
 
485
- backdrop?.click();
183
+ document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }));
486
184
  await el.updateComplete;
487
185
 
488
186
  backdrop = el.shadowRoot?.querySelector(
@@ -491,31 +189,61 @@ describe('Sort selector default buttons', async () => {
491
189
  expect(backdrop).not.to.exist;
492
190
  });
493
191
 
494
- it('closes dropdown by hitting escape key', async () => {
495
- const defaultSortSelector = desktopSortSelector?.children
496
- .item(3)
497
- ?.querySelector('ia-dropdown') as IaDropdown;
192
+ it('clears title filter when sort changed from title', async () => {
193
+ el.selectedSort = 'title' as SortField;
194
+ el.selectedTitleFilter = 'A';
195
+ await el.updateComplete;
498
196
 
499
- const caret = defaultSortSelector?.shadowRoot?.querySelector(
500
- '.caret',
501
- ) as HTMLElement;
502
- expect(caret).to.exist;
197
+ const dropdown = el.shadowRoot?.querySelector(
198
+ '#sort-dropdown',
199
+ ) as IaDropdown;
200
+ expect(dropdown).to.exist;
503
201
 
504
- caret?.click();
202
+ dropdown.selectedOption = 'relevance';
203
+ const option = { id: 'relevance' };
204
+ dropdown.dispatchEvent(
205
+ new CustomEvent('optionSelected', { detail: { option } }),
206
+ );
505
207
  await el.updateComplete;
506
208
 
507
- let backdrop = el.shadowRoot?.querySelector(
508
- '#sort-selector-backdrop',
509
- ) as HTMLElement;
510
- expect(backdrop).to.exist;
209
+ expect(el.selectedSort).to.equal('relevance');
210
+ expect(el.selectedTitleFilter).to.be.null;
211
+ });
511
212
 
512
- document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }));
213
+ it('clears creator filter when sort changed from creator', async () => {
214
+ el.selectedSort = 'creator' as SortField;
215
+ el.selectedCreatorFilter = 'A';
513
216
  await el.updateComplete;
514
217
 
515
- backdrop = el.shadowRoot?.querySelector(
516
- '#sort-selector-backdrop',
517
- ) as HTMLElement;
518
- expect(backdrop).not.to.exist;
218
+ const dropdown = el.shadowRoot?.querySelector(
219
+ '#sort-dropdown',
220
+ ) as IaDropdown;
221
+ expect(dropdown).to.exist;
222
+
223
+ dropdown.selectedOption = 'relevance';
224
+ const option = { id: 'relevance' };
225
+ dropdown.dispatchEvent(
226
+ new CustomEvent('optionSelected', { detail: { option } }),
227
+ );
228
+ await el.updateComplete;
229
+
230
+ expect(el.selectedSort).to.equal('relevance');
231
+ expect(el.selectedCreatorFilter).to.be.null;
232
+ });
233
+
234
+ it('contains sort-options slot when enabled', async () => {
235
+ const slotEl = await fixture<SortFilterBar>(html`
236
+ <sort-filter-bar .enableSortOptionsSlot=${true}></sort-filter-bar>
237
+ `);
238
+ await slotEl.updateComplete;
239
+
240
+ const sortOptionsSlot = slotEl?.shadowRoot?.querySelector(
241
+ 'slot[name="sort-options"]',
242
+ );
243
+ expect(sortOptionsSlot).to.exist;
244
+
245
+ expect(slotEl?.shadowRoot?.querySelector('#sort-selector-container')).to.not
246
+ .exist;
519
247
  });
520
248
  });
521
249
 
@@ -699,187 +427,3 @@ describe('Sort/filter bar letter behavior', () => {
699
427
  expect(el.selectedCreatorFilter).to.equal('C');
700
428
  });
701
429
  });
702
-
703
- describe('Sort/filter bar mobile view', () => {
704
- let origWindowSize: { width: number; height: number };
705
- before(() => {
706
- origWindowSize = { width: window.innerWidth, height: window.innerHeight };
707
- window.resizeTo(500, 600);
708
- });
709
-
710
- after(() => {
711
- window.resizeTo(origWindowSize.width, origWindowSize.height);
712
- });
713
-
714
- it('renders in mobile view', async () => {
715
- const el = await fixture<SortFilterBar>(html`
716
- <sort-filter-bar></sort-filter-bar>
717
- `);
718
-
719
- const mobileSortContainer = el.shadowRoot?.querySelector(
720
- '#mobile-sort-container',
721
- );
722
- const desktopSortContainer = el.shadowRoot?.querySelector(
723
- '#desktop-sort-container',
724
- );
725
-
726
- expect(mobileSortContainer?.classList?.contains('visible')).to.be.true;
727
- expect(desktopSortContainer?.classList?.contains('hidden')).to.be.true;
728
- });
729
-
730
- it('changes selected sort in mobile view', async () => {
731
- const el = await fixture<SortFilterBar>(html`
732
- <sort-filter-bar></sort-filter-bar>
733
- `);
734
-
735
- const mobileDropdown = el.shadowRoot?.querySelector(
736
- '#mobile-dropdown',
737
- ) as IaDropdown;
738
- expect(mobileDropdown).to.exist;
739
-
740
- mobileDropdown.selectedOption = 'title';
741
- const option = { id: 'title' };
742
- mobileDropdown.dispatchEvent(
743
- new CustomEvent('optionSelected', { detail: { option } }),
744
- );
745
- await el.updateComplete;
746
-
747
- expect(el.selectedSort).to.equal('title');
748
- });
749
-
750
- it('clears title filter when sort changed from title in mobile view', async () => {
751
- const el = await fixture<SortFilterBar>(html`
752
- <sort-filter-bar></sort-filter-bar>
753
- `);
754
-
755
- el.selectedSort = 'title' as SortField;
756
- el.selectedTitleFilter = 'A';
757
- await el.updateComplete;
758
-
759
- const mobileDropdown = el.shadowRoot?.querySelector(
760
- '#mobile-dropdown',
761
- ) as IaDropdown;
762
- expect(mobileDropdown).to.exist;
763
-
764
- mobileDropdown.selectedOption = 'relevance';
765
- const option = { id: 'relevance' };
766
- mobileDropdown.dispatchEvent(
767
- new CustomEvent('optionSelected', { detail: { option } }),
768
- );
769
- await el.updateComplete;
770
-
771
- expect(el.selectedSort).to.equal('relevance');
772
- expect(el.selectedTitleFilter).to.be.null;
773
- });
774
-
775
- it('clears creator filter when sort changed from creator in mobile view', async () => {
776
- const el = await fixture<SortFilterBar>(html`
777
- <sort-filter-bar></sort-filter-bar>
778
- `);
779
-
780
- el.selectedSort = 'creator' as SortField;
781
- el.selectedCreatorFilter = 'A';
782
- await el.updateComplete;
783
-
784
- const mobileDropdown = el.shadowRoot?.querySelector(
785
- '#mobile-dropdown',
786
- ) as IaDropdown;
787
- expect(mobileDropdown).to.exist;
788
-
789
- mobileDropdown.selectedOption = 'relevance';
790
- const option = { id: 'relevance' };
791
- mobileDropdown.dispatchEvent(
792
- new CustomEvent('optionSelected', { detail: { option } }),
793
- );
794
- await el.updateComplete;
795
-
796
- expect(el.selectedSort).to.equal('relevance');
797
- expect(el.selectedCreatorFilter).to.be.null;
798
- });
799
-
800
- it('shows sort selector backdrop when mobile sort open', async () => {
801
- const el = await fixture<SortFilterBar>(html`
802
- <sort-filter-bar></sort-filter-bar>
803
- `);
804
-
805
- const mobileDropdown = el.shadowRoot?.querySelector(
806
- '#mobile-dropdown',
807
- ) as IaDropdown;
808
- expect(mobileDropdown).to.exist;
809
-
810
- const caret = mobileDropdown?.shadowRoot?.querySelector(
811
- '.caret',
812
- ) as HTMLElement;
813
- expect(caret).to.exist;
814
-
815
- caret?.click();
816
- await el.updateComplete;
817
-
818
- let backdrop = el.shadowRoot?.querySelector(
819
- '#sort-selector-backdrop',
820
- ) as HTMLElement;
821
- expect(backdrop).to.exist;
822
-
823
- backdrop?.click();
824
- await el.updateComplete;
825
-
826
- backdrop = el.shadowRoot?.querySelector(
827
- '#sort-selector-backdrop',
828
- ) as HTMLElement;
829
- expect(backdrop).not.to.exist;
830
- });
831
-
832
- it('shows loansTab top-bar slot Default View', async () => {
833
- const resizeStub = new SharedResizeObserver();
834
- const addSpy = sinon.spy(resizeStub, 'addObserver');
835
- const removeSpy = sinon.spy(resizeStub, 'removeObserver');
836
-
837
- const el = await fixture<SortFilterBar>(html`
838
- <sort-filter-bar .resizeObserver=${resizeStub}></sort-filter-bar>
839
- `);
840
-
841
- // this element exists
842
- expect(el?.shadowRoot?.querySelector('#sort-selector-container')).to.exist;
843
-
844
- // loads & unloads twice when [re]setting ResizeObserver
845
- expect(addSpy.callCount).to.equal(2);
846
-
847
- const resizeStub2 = new SharedResizeObserver();
848
- el.resizeObserver = resizeStub2;
849
- await el.updateComplete;
850
- expect(removeSpy.callCount).to.equal(2);
851
- });
852
-
853
- it('contains sort-options slot when enabled', async () => {
854
- const resizeStub = new SharedResizeObserver();
855
- const addSpy = sinon.spy(resizeStub, 'addObserver');
856
- const removeSpy = sinon.spy(resizeStub, 'removeObserver');
857
-
858
- const el = await fixture<SortFilterBar>(html`
859
- <sort-filter-bar
860
- .resizeObserver=${resizeStub}
861
- .enableSortOptionsSlot=${true}
862
- ></sort-filter-bar>
863
- `);
864
-
865
- await el.updateComplete;
866
-
867
- // slot exists
868
- const sortOptionsSlot = el?.shadowRoot?.querySelector(
869
- 'slot[name="sort-options"]',
870
- );
871
- expect(sortOptionsSlot).to.exist;
872
-
873
- // sort bar does not exist
874
- expect(el?.shadowRoot?.querySelector('#sort-selector-container')).to.not
875
- .exist;
876
-
877
- const resizeStub2 = new SharedResizeObserver();
878
- el.resizeObserver = resizeStub2;
879
- await el.updateComplete;
880
-
881
- // there's no need for resize observer
882
- expect(addSpy.callCount).to.equal(0);
883
- expect(removeSpy.callCount).to.equal(0);
884
- });
885
- });