@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
@@ -978,31 +978,20 @@ describe('Collection Browser', () => {
978
978
 
979
979
  const sortBar = el.shadowRoot?.querySelector(
980
980
  '#content-container sort-filter-bar',
981
- );
982
- const sortSelector = sortBar?.shadowRoot?.querySelector(
983
- '#desktop-sort-selector',
984
- );
985
- expect(sortSelector, 'sort bar').to.exist;
986
-
987
- // Click the title sorter
988
- Array.from(sortSelector!.children)
989
- .find(child => child.textContent?.trim() === 'Title')
990
- ?.querySelector('button')
991
- ?.click();
981
+ ) as SortFilterBar;
982
+ expect(sortBar, 'sort bar').to.exist;
992
983
 
984
+ // Switch to title sort
985
+ sortBar.setSelectedSort(SortField.title);
993
986
  await el.updateComplete;
994
-
995
987
  expect(el.selectedSort).to.equal(SortField.title);
988
+ expect(el.sortDirection).to.equal('asc'); // Default for title sort
996
989
 
997
- // Click the creator sorter
998
- Array.from(sortSelector!.children)
999
- .find(child => child.textContent?.trim() === 'Creator')
1000
- ?.querySelector('button')
1001
- ?.click();
1002
-
990
+ // Switch to descending sort order
991
+ sortBar.setSortDirection('desc');
1003
992
  await el.updateComplete;
1004
-
1005
- expect(el.selectedSort).to.equal(SortField.creator);
993
+ expect(el.selectedSort).to.equal(SortField.title);
994
+ expect(el.sortDirection).to.equal('desc');
1006
995
  });
1007
996
 
1008
997
  it('sets sort filter properties when user selects title filter', async () => {
@@ -6,7 +6,6 @@ import { MockSearchService } from '../mocks/mock-search-service';
6
6
  import { MockAnalyticsHandler } from '../mocks/mock-analytics-handler';
7
7
  import type { FacetsTemplate } from '../../src/collection-facets/facets-template';
8
8
  import type { SelectedFacets } from '../../src/models';
9
- import { Aggregation, type Bucket } from '@internetarchive/search-service';
10
9
 
11
10
  const selectedFacetsGroup = {
12
11
  title: 'Media Type',
@@ -55,7 +54,7 @@ describe('More facets content', () => {
55
54
  expect(el.shadowRoot?.querySelector('.facets-loader')).to.exist;
56
55
  });
57
56
 
58
- it('should NOT render pagination when facet count < 1000', async () => {
57
+ it('should render pagination for more facets', async () => {
59
58
  const searchService = new MockSearchService();
60
59
 
61
60
  const el = await fixture<MoreFacetsContent>(
@@ -65,22 +64,11 @@ describe('More facets content', () => {
65
64
  );
66
65
 
67
66
  el.facetKey = 'year';
68
- el.query = 'more-facets'; // Produces a response with 45 aggregations (< 1000)
67
+ el.query = 'more-facets'; // Produces a response with 40+ aggregations for multiple pages
69
68
  await el.updateComplete;
70
69
  await aTimeout(50); // Give it a moment to perform the (mock) search query after the initial update
71
70
 
72
- // Verify pagination component is NOT present (horizontal scroll mode)
73
- expect(el.shadowRoot?.querySelector('more-facets-pagination')).to.not.exist;
74
-
75
- // Verify horizontal scroll mode CSS class is applied
76
- expect(
77
- el.shadowRoot?.querySelector('.facets-content.horizontal-scroll-mode'),
78
- ).to.exist;
79
-
80
- // Verify footer still exists with buttons
81
- expect(el.shadowRoot?.querySelector('.footer')).to.exist;
82
- expect(el.shadowRoot?.querySelector('.btn-cancel')).to.exist;
83
- expect(el.shadowRoot?.querySelector('.btn-submit')).to.exist;
71
+ expect(el.shadowRoot?.querySelectorAll('more-facets-pagination')).to.exist;
84
72
  });
85
73
 
86
74
  it('query for more facets content using search service', async () => {
@@ -240,207 +228,4 @@ describe('More facets content', () => {
240
228
  expect(mockAnalyticsHandler.callAction).to.equal('applyMoreFacetsModal');
241
229
  expect(mockAnalyticsHandler.callLabel).to.equal('collection');
242
230
  });
243
-
244
- it('should have horizontal scrolling enabled', async () => {
245
- const searchService = new MockSearchService();
246
-
247
- const el = await fixture<MoreFacetsContent>(
248
- html`<more-facets-content
249
- .searchService=${searchService}
250
- ></more-facets-content>`,
251
- );
252
-
253
- el.facetKey = 'year';
254
- el.query = 'more-facets';
255
- await el.updateComplete;
256
- await aTimeout(50);
257
-
258
- const facetsContent = el.shadowRoot?.querySelector(
259
- '.facets-content',
260
- ) as HTMLElement;
261
- const styles = window.getComputedStyle(facetsContent);
262
-
263
- expect(styles.overflowX).to.equal('auto');
264
- expect(styles.overflowY).to.equal('hidden');
265
- });
266
-
267
- it('should have horizontal container wrapper', async () => {
268
- const searchService = new MockSearchService();
269
-
270
- const el = await fixture<MoreFacetsContent>(
271
- html`<more-facets-content
272
- .searchService=${searchService}
273
- ></more-facets-content>`,
274
- );
275
-
276
- el.facetKey = 'year';
277
- el.query = 'more-facets';
278
- await el.updateComplete;
279
- await aTimeout(50);
280
-
281
- const container = el.shadowRoot?.querySelector(
282
- '.facets-horizontal-container',
283
- );
284
- expect(container).to.exist;
285
-
286
- const facetsTemplate = container?.querySelector('facets-template');
287
- expect(facetsTemplate).to.exist;
288
- });
289
-
290
- it('should render pagination when facet count >= 1000', async () => {
291
- // Manually create aggregations with 1000+ facets
292
- const buckets: Bucket[] = [];
293
- for (let i = 0; i < 1000; i++) {
294
- buckets.push({ key: `value-${i}`, doc_count: i + 1 });
295
- }
296
-
297
- const el = await fixture<MoreFacetsContent>(
298
- html`<more-facets-content
299
- .facetKey=${'subject'}
300
- .selectedFacets=${{
301
- mediatype: {},
302
- lending: {},
303
- year: {},
304
- subject: {},
305
- collection: {},
306
- creator: {},
307
- language: {},
308
- }}
309
- ></more-facets-content>`,
310
- );
311
-
312
- // @ts-expect-error - accessing private property for testing
313
- el.aggregations = {
314
- subject: new Aggregation({ buckets }),
315
- };
316
- el.facetsLoading = false;
317
- await el.updateComplete;
318
-
319
- // Verify pagination component IS present
320
- expect(el.shadowRoot?.querySelector('more-facets-pagination')).to.exist;
321
-
322
- // Verify pagination mode CSS class is applied
323
- expect(el.shadowRoot?.querySelector('.facets-content.pagination-mode')).to
324
- .exist;
325
-
326
- // Verify horizontal container wrapper does NOT exist in pagination mode
327
- expect(el.shadowRoot?.querySelector('.facets-horizontal-container')).to.not
328
- .exist;
329
- });
330
-
331
- it('pagination page change should send analytics event', async () => {
332
- const mockAnalyticsHandler = new MockAnalyticsHandler();
333
-
334
- // Manually create aggregations with 1000+ facets
335
- const buckets: Bucket[] = [];
336
- for (let i = 0; i < 1000; i++) {
337
- buckets.push({ key: `value-${i}`, doc_count: i + 1 });
338
- }
339
-
340
- const el = await fixture<MoreFacetsContent>(
341
- html`<more-facets-content
342
- .facetKey=${'subject'}
343
- .selectedFacets=${{
344
- mediatype: {},
345
- lending: {},
346
- year: {},
347
- subject: {},
348
- collection: {},
349
- creator: {},
350
- language: {},
351
- }}
352
- .analyticsHandler=${mockAnalyticsHandler}
353
- ></more-facets-content>`,
354
- );
355
-
356
- // @ts-expect-error - accessing private property for testing
357
- el.aggregations = {
358
- subject: new Aggregation({ buckets }),
359
- };
360
- el.facetsLoading = false;
361
- await el.updateComplete;
362
-
363
- // Get the pagination component
364
- const pagination = el.shadowRoot?.querySelector(
365
- 'more-facets-pagination',
366
- ) as any;
367
- expect(pagination).to.exist;
368
-
369
- // Simulate clicking page 2
370
- pagination.currentPage = 2;
371
- await pagination.updateComplete;
372
-
373
- // Verify analytics event was sent
374
- expect(mockAnalyticsHandler.callCategory).to.equal('collection-browser');
375
- expect(mockAnalyticsHandler.callAction).to.equal('moreFacetsPageChange');
376
- expect(mockAnalyticsHandler.callLabel).to.equal('2');
377
- });
378
-
379
- it('should show clear button when filter text is present', async () => {
380
- const searchService = new MockSearchService();
381
-
382
- const el = await fixture<MoreFacetsContent>(
383
- html`<more-facets-content
384
- .facetKey=${'year'}
385
- .query=${'more-facets'}
386
- .searchService=${searchService}
387
- .selectedFacets=${yearSelectedFacets}
388
- ></more-facets-content>`,
389
- );
390
-
391
- await el.updateComplete;
392
- await aTimeout(50);
393
-
394
- // Initially, no clear button should exist
395
- expect(el.shadowRoot?.querySelector('.filter-clear-btn')).to.not.exist;
396
-
397
- // Type into the filter input
398
- const filterInput = el.shadowRoot?.querySelector(
399
- '#facet-filter',
400
- ) as HTMLInputElement;
401
- expect(filterInput).to.exist;
402
-
403
- filterInput.value = 'test';
404
- filterInput.dispatchEvent(new Event('input'));
405
- await el.updateComplete;
406
-
407
- // Now clear button should exist
408
- expect(el.shadowRoot?.querySelector('.filter-clear-btn')).to.exist;
409
- });
410
-
411
- it('should clear filter text when clear button is clicked', async () => {
412
- const searchService = new MockSearchService();
413
-
414
- const el = await fixture<MoreFacetsContent>(
415
- html`<more-facets-content
416
- .facetKey=${'year'}
417
- .query=${'more-facets'}
418
- .searchService=${searchService}
419
- .selectedFacets=${yearSelectedFacets}
420
- ></more-facets-content>`,
421
- );
422
-
423
- await el.updateComplete;
424
- await aTimeout(50);
425
-
426
- // Type into the filter input
427
- const filterInput = el.shadowRoot?.querySelector(
428
- '#facet-filter',
429
- ) as HTMLInputElement;
430
- filterInput.value = 'test';
431
- filterInput.dispatchEvent(new Event('input'));
432
- await el.updateComplete;
433
-
434
- // Click the clear button
435
- const clearBtn = el.shadowRoot?.querySelector(
436
- '.filter-clear-btn',
437
- ) as HTMLButtonElement;
438
- expect(clearBtn).to.exist;
439
- clearBtn.click();
440
- await el.updateComplete;
441
-
442
- // Filter input should be empty and clear button should be gone
443
- expect(filterInput.value).to.equal('');
444
- expect(el.shadowRoot?.querySelector('.filter-clear-btn')).to.not.exist;
445
- });
446
231
  });
@@ -198,88 +198,4 @@ describe('More facets pagination', () => {
198
198
  expect(el.currentPage).to.equal(6); // brings us forward 1 page
199
199
  });
200
200
  });
201
-
202
- describe('Compact mode', () => {
203
- it('shows all pages when size <= 3', async () => {
204
- const el = await fixture<MoreFacetsPagination>(
205
- html`<more-facets-pagination
206
- .size=${3}
207
- .compact=${true}
208
- ></more-facets-pagination>`,
209
- );
210
-
211
- await el.updateComplete;
212
- expect(el.pages).to.deep.equal([1, 2, 3]);
213
- });
214
-
215
- it('shows first, prev, current, next, ..., last for middle page', async () => {
216
- const el = await fixture<MoreFacetsPagination>(
217
- html`<more-facets-pagination
218
- .size=${20}
219
- .currentPage=${10}
220
- .compact=${true}
221
- ></more-facets-pagination>`,
222
- );
223
-
224
- await el.updateComplete;
225
- // first, ..., prev, current, next, ..., last
226
- expect(el.pages).to.deep.equal([1, 0, 9, 10, 11, 0, 20]);
227
- });
228
-
229
- it('shows correct pages when on page 1', async () => {
230
- const el = await fixture<MoreFacetsPagination>(
231
- html`<more-facets-pagination
232
- .size=${20}
233
- .currentPage=${1}
234
- .compact=${true}
235
- ></more-facets-pagination>`,
236
- );
237
-
238
- await el.updateComplete;
239
- // first (current), next, ..., last
240
- expect(el.pages).to.deep.equal([1, 2, 0, 20]);
241
- });
242
-
243
- it('shows correct pages when on last page', async () => {
244
- const el = await fixture<MoreFacetsPagination>(
245
- html`<more-facets-pagination
246
- .size=${20}
247
- .currentPage=${20}
248
- .compact=${true}
249
- ></more-facets-pagination>`,
250
- );
251
-
252
- await el.updateComplete;
253
- // first, ..., prev, last (current)
254
- expect(el.pages).to.deep.equal([1, 0, 19, 20]);
255
- });
256
-
257
- it('shows correct pages when on page 2', async () => {
258
- const el = await fixture<MoreFacetsPagination>(
259
- html`<more-facets-pagination
260
- .size=${20}
261
- .currentPage=${2}
262
- .compact=${true}
263
- ></more-facets-pagination>`,
264
- );
265
-
266
- await el.updateComplete;
267
- // first, current, next, ..., last
268
- expect(el.pages).to.deep.equal([1, 2, 3, 0, 20]);
269
- });
270
-
271
- it('shows correct pages when on second-to-last page', async () => {
272
- const el = await fixture<MoreFacetsPagination>(
273
- html`<more-facets-pagination
274
- .size=${20}
275
- .currentPage=${19}
276
- .compact=${true}
277
- ></more-facets-pagination>`,
278
- );
279
-
280
- await el.updateComplete;
281
- // first, ..., prev, current, last
282
- expect(el.pages).to.deep.equal([1, 0, 18, 19, 20]);
283
- });
284
- });
285
201
  });