@internetarchive/collection-browser 0.4.0 → 0.4.2

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 (58) hide show
  1. package/dist/src/app-root.js +1 -1
  2. package/dist/src/app-root.js.map +1 -1
  3. package/dist/src/collection-browser.d.ts +40 -3
  4. package/dist/src/collection-browser.js +214 -58
  5. package/dist/src/collection-browser.js.map +1 -1
  6. package/dist/src/collection-facets/more-facets-content.d.ts +3 -2
  7. package/dist/src/collection-facets/more-facets-content.js +6 -2
  8. package/dist/src/collection-facets/more-facets-content.js.map +1 -1
  9. package/dist/src/collection-facets.d.ts +3 -2
  10. package/dist/src/collection-facets.js +6 -2
  11. package/dist/src/collection-facets.js.map +1 -1
  12. package/dist/src/models.d.ts +9 -0
  13. package/dist/src/models.js +8 -0
  14. package/dist/src/models.js.map +1 -1
  15. package/dist/src/restoration-state-handler.d.ts +0 -1
  16. package/dist/src/restoration-state-handler.js +4 -4
  17. package/dist/src/restoration-state-handler.js.map +1 -1
  18. package/dist/src/sort-filter-bar/alpha-bar.d.ts +3 -0
  19. package/dist/src/sort-filter-bar/alpha-bar.js +32 -13
  20. package/dist/src/sort-filter-bar/alpha-bar.js.map +1 -1
  21. package/dist/src/sort-filter-bar/sort-filter-bar.d.ts +2 -1
  22. package/dist/src/sort-filter-bar/sort-filter-bar.js +7 -0
  23. package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -1
  24. package/dist/src/tiles/image-block.js +0 -1
  25. package/dist/src/tiles/image-block.js.map +1 -1
  26. package/dist/test/collection-browser.test.js +81 -9
  27. package/dist/test/collection-browser.test.js.map +1 -1
  28. package/dist/test/collection-facets/more-facets-content.test.js +2 -2
  29. package/dist/test/collection-facets/more-facets-content.test.js.map +1 -1
  30. package/dist/test/mocks/mock-search-responses.d.ts +2 -0
  31. package/dist/test/mocks/mock-search-responses.js +70 -0
  32. package/dist/test/mocks/mock-search-responses.js.map +1 -1
  33. package/dist/test/mocks/mock-search-service.js +5 -1
  34. package/dist/test/mocks/mock-search-service.js.map +1 -1
  35. package/dist/test/restoration-state-handler.test.js +0 -1
  36. package/dist/test/restoration-state-handler.test.js.map +1 -1
  37. package/dist/test/sort-filter-bar/alpha-bar.test.d.ts +1 -0
  38. package/dist/test/sort-filter-bar/alpha-bar.test.js +44 -0
  39. package/dist/test/sort-filter-bar/alpha-bar.test.js.map +1 -0
  40. package/dist/test/sort-filter-bar/sort-filter-bar.test.js +32 -0
  41. package/dist/test/sort-filter-bar/sort-filter-bar.test.js.map +1 -1
  42. package/package.json +3 -3
  43. package/src/app-root.ts +1 -1
  44. package/src/collection-browser.ts +273 -57
  45. package/src/collection-facets/more-facets-content.ts +6 -2
  46. package/src/collection-facets.ts +6 -2
  47. package/src/models.ts +15 -0
  48. package/src/restoration-state-handler.ts +7 -5
  49. package/src/sort-filter-bar/alpha-bar.ts +26 -9
  50. package/src/sort-filter-bar/sort-filter-bar.ts +9 -0
  51. package/src/tiles/image-block.ts +0 -1
  52. package/test/collection-browser.test.ts +90 -10
  53. package/test/collection-facets/more-facets-content.test.ts +2 -2
  54. package/test/mocks/mock-search-responses.ts +78 -0
  55. package/test/mocks/mock-search-service.ts +6 -0
  56. package/test/restoration-state-handler.test.ts +0 -3
  57. package/test/sort-filter-bar/alpha-bar.test.ts +52 -0
  58. package/test/sort-filter-bar/sort-filter-bar.test.ts +44 -0
@@ -1,10 +1,13 @@
1
1
  import { LitElement, html, css } from 'lit';
2
2
  import { customElement, property } from 'lit/decorators.js';
3
+ import type { PrefixFilterCounts } from '../models';
3
4
 
4
5
  @customElement('alpha-bar')
5
6
  export class AlphaBar extends LitElement {
6
7
  @property({ type: String }) selectedLetter: string | null = null;
7
8
 
9
+ @property({ type: Object }) letterCounts?: PrefixFilterCounts;
10
+
8
11
  private get selectedUppercaseLetter(): string | undefined {
9
12
  return this.selectedLetter?.toUpperCase();
10
13
  }
@@ -21,15 +24,9 @@ export class AlphaBar extends LitElement {
21
24
  ? 'selected'
22
25
  : ''}
23
26
  >
24
- <a
25
- href="#"
26
- @click=${(e: Event) => {
27
- e.preventDefault();
28
- this.letterClicked(letter);
29
- }}
30
- >
31
- ${letter}
32
- </a>
27
+ ${this.letterCounts?.[letter]
28
+ ? this.letterLinkTemplate(letter)
29
+ : html`<span>${letter}</span>`}
33
30
  </li>
34
31
  `
35
32
  )}
@@ -38,6 +35,20 @@ export class AlphaBar extends LitElement {
38
35
  `;
39
36
  }
40
37
 
38
+ private letterLinkTemplate(letter: string) {
39
+ return html`
40
+ <a
41
+ href="#"
42
+ @click=${(e: Event) => {
43
+ e.preventDefault();
44
+ this.letterClicked(letter);
45
+ }}
46
+ >
47
+ ${letter}
48
+ </a>
49
+ `;
50
+ }
51
+
41
52
  private letterClicked(letter: string) {
42
53
  if (letter === this.selectedUppercaseLetter) {
43
54
  this.selectedLetter = null;
@@ -85,6 +96,12 @@ export class AlphaBar extends LitElement {
85
96
  display: block;
86
97
  }
87
98
 
99
+ span {
100
+ color: #aaa;
101
+ padding: 0.5rem 0;
102
+ display: block;
103
+ }
104
+
88
105
  .selected {
89
106
  background-color: darkgray;
90
107
  }
@@ -13,6 +13,8 @@ import type {
13
13
  } from '@internetarchive/shared-resize-observer';
14
14
  import {
15
15
  CollectionDisplayMode,
16
+ PrefixFilterCounts,
17
+ PrefixFilterType,
16
18
  SortField,
17
19
  SortFieldDisplayName,
18
20
  } from '../models';
@@ -42,6 +44,11 @@ export class SortFilterBar
42
44
 
43
45
  @property({ type: Boolean }) showRelevance: boolean = true;
44
46
 
47
+ @property({ type: Object }) prefixFilterCountMap?: Record<
48
+ PrefixFilterType,
49
+ PrefixFilterCounts
50
+ >;
51
+
45
52
  @property({ type: Object }) resizeObserver?: SharedResizeObserverInterface;
46
53
 
47
54
  @state() alphaSelectorVisible: AlphaSelector | null = null;
@@ -563,6 +570,7 @@ export class SortFilterBar
563
570
  private get titleSelectorBar() {
564
571
  return html` <alpha-bar
565
572
  .selectedLetter=${this.selectedTitleFilter}
573
+ .letterCounts=${this.prefixFilterCountMap?.title}
566
574
  @letterChanged=${this.titleLetterChanged}
567
575
  ></alpha-bar>`;
568
576
  }
@@ -570,6 +578,7 @@ export class SortFilterBar
570
578
  private get creatorSelectorBar() {
571
579
  return html` <alpha-bar
572
580
  .selectedLetter=${this.selectedCreatorFilter}
581
+ .letterCounts=${this.prefixFilterCountMap?.creator}
573
582
  @letterChanged=${this.creatorLetterChanged}
574
583
  ></alpha-bar>`;
575
584
  }
@@ -91,7 +91,6 @@ export class ImageBlock extends LitElement {
91
91
  .grid {
92
92
  height: var(--imgBlockHeight, 16rem);
93
93
  flex: 1;
94
- display: inline-block;
95
94
  position: initial;
96
95
  }
97
96
 
@@ -20,6 +20,20 @@ import { analyticsCategories } from '../src/utils/analytics-events';
20
20
  import type { TileDispatcher } from '../src/tiles/tile-dispatcher';
21
21
  import type { CollectionFacets } from '../src/collection-facets';
22
22
 
23
+ /**
24
+ * Wait for the next tick of the event loop.
25
+ *
26
+ * This is necessary in some of the tests because certain collection browser
27
+ * updates take more than one tick to render (e.g., date picker & query changes).
28
+ * These delays are non-ideal and should eventually be investigated and fixed,
29
+ * but they are minor enough that waiting for the next tick is a reasonable
30
+ * testing solution for now.
31
+ */
32
+ const nextTick = () =>
33
+ new Promise(resolve => {
34
+ setTimeout(resolve, 0);
35
+ });
36
+
23
37
  describe('Collection Browser', () => {
24
38
  beforeEach(async () => {
25
39
  // Apparently query params set by one test can bleed into other tests.
@@ -61,6 +75,8 @@ describe('Collection Browser', () => {
61
75
  );
62
76
 
63
77
  el.searchContext = 'betaSearchService';
78
+ el.selectedSort = 'creator' as SortField;
79
+ el.sortDirection = 'asc';
64
80
  el.selectedCreatorFilter = 'A';
65
81
  await el.updateComplete;
66
82
 
@@ -86,6 +102,7 @@ describe('Collection Browser', () => {
86
102
 
87
103
  el.searchContext = 'beta-search-service';
88
104
  el.selectedSort = 'title' as SortField;
105
+ el.sortDirection = 'asc';
89
106
  el.selectedTitleFilter = 'A';
90
107
  await el.updateComplete;
91
108
 
@@ -199,6 +216,7 @@ describe('Collection Browser', () => {
199
216
 
200
217
  el.baseQuery = 'collection:foo';
201
218
  await el.updateComplete;
219
+ await nextTick();
202
220
 
203
221
  expect(searchService.searchParams?.query).to.equal('collection:foo');
204
222
  expect(
@@ -219,6 +237,7 @@ describe('Collection Browser', () => {
219
237
 
220
238
  el.baseQuery = 'collection:foo';
221
239
  await el.updateComplete;
240
+ await nextTick();
222
241
 
223
242
  expect(searchService.searchParams?.query).to.equal('collection:foo');
224
243
  expect(searchService.searchType).to.equal(SearchType.METADATA);
@@ -240,6 +259,7 @@ describe('Collection Browser', () => {
240
259
 
241
260
  el.baseQuery = 'collection:foo';
242
261
  await el.updateComplete;
262
+ await nextTick();
243
263
 
244
264
  expect(searchService.searchParams?.query).to.equal('collection:foo');
245
265
  expect(searchService.searchType).to.equal(SearchType.FULLTEXT);
@@ -286,9 +306,16 @@ describe('Collection Browser', () => {
286
306
  el.selectedFacets = selectedFacets;
287
307
  await el.updateComplete;
288
308
 
289
- expect(searchService.searchParams?.query).to.equal(
290
- 'collection:foo AND (subject:("foo" OR -"bar") AND language:("en"))'
291
- );
309
+ expect(searchService.searchParams?.query).to.equal('collection:foo');
310
+ expect(searchService.searchParams?.filters).to.deep.equal({
311
+ subject: {
312
+ foo: 'inc',
313
+ bar: 'exc',
314
+ },
315
+ language: {
316
+ en: 'inc',
317
+ },
318
+ });
292
319
  });
293
320
 
294
321
  it('fires a separate date histogram query when year facets are applied', async () => {
@@ -337,7 +364,8 @@ describe('Collection Browser', () => {
337
364
 
338
365
  el.baseQuery = 'collection:foo';
339
366
  el.showHistogramDatePicker = true;
340
- el.dateRangeQueryClause = 'year:[1995 TO 2005]';
367
+ el.minSelectedDate = '1995';
368
+ el.maxSelectedDate = '2005';
341
369
  await el.updateComplete;
342
370
 
343
371
  expect(
@@ -375,7 +403,8 @@ describe('Collection Browser', () => {
375
403
 
376
404
  el.baseQuery = 'collection:foo';
377
405
  el.showHistogramDatePicker = false;
378
- el.dateRangeQueryClause = 'year:[1995 TO 2005]';
406
+ el.minSelectedDate = '1995';
407
+ el.maxSelectedDate = '2005';
379
408
  await el.updateComplete;
380
409
 
381
410
  expect(searchService.searchParams?.aggregations?.simpleParams).to.satisfy(
@@ -675,7 +704,9 @@ describe('Collection Browser', () => {
675
704
  </collection-browser>`
676
705
  );
677
706
 
678
- el.baseQuery = 'collection:foo';
707
+ el.baseQuery = 'first-title';
708
+ el.selectedSort = 'title' as SortField;
709
+ el.sortDirection = 'asc';
679
710
  el.selectedTitleFilter = 'X';
680
711
  await el.updateComplete;
681
712
 
@@ -685,7 +716,7 @@ describe('Collection Browser', () => {
685
716
  });
686
717
 
687
718
  expect(searchService.searchParams?.query).to.equal(
688
- 'collection:foo AND firstTitle:X'
719
+ 'first-title AND firstTitle:X'
689
720
  );
690
721
  });
691
722
 
@@ -696,7 +727,9 @@ describe('Collection Browser', () => {
696
727
  </collection-browser>`
697
728
  );
698
729
 
699
- el.baseQuery = 'collection:foo';
730
+ el.baseQuery = 'first-creator';
731
+ el.selectedSort = 'creator' as SortField;
732
+ el.sortDirection = 'asc';
700
733
  el.selectedCreatorFilter = 'X';
701
734
  await el.updateComplete;
702
735
 
@@ -706,10 +739,55 @@ describe('Collection Browser', () => {
706
739
  });
707
740
 
708
741
  expect(searchService.searchParams?.query).to.equal(
709
- 'collection:foo AND firstCreator:X'
742
+ 'first-creator AND firstCreator:X'
710
743
  );
711
744
  });
712
745
 
746
+ it('sets sort filter properties simultaneous with facets and date range', async () => {
747
+ const searchService = new MockSearchService();
748
+ const selectedFacets: SelectedFacets = {
749
+ collection: { foo: { key: 'foo', state: 'selected', count: 1 } },
750
+ creator: {},
751
+ language: {},
752
+ lending: {},
753
+ mediatype: {},
754
+ subject: {},
755
+ year: {},
756
+ };
757
+
758
+ const el = await fixture<CollectionBrowser>(
759
+ html`<collection-browser .searchService=${searchService}>
760
+ </collection-browser>`
761
+ );
762
+
763
+ el.baseQuery = 'first-creator';
764
+ el.selectedSort = 'creator' as SortField;
765
+ el.selectedFacets = selectedFacets;
766
+ el.minSelectedDate = '1950';
767
+ el.maxSelectedDate = '1970';
768
+ el.sortDirection = 'asc';
769
+ el.selectedCreatorFilter = 'X';
770
+ await el.updateComplete;
771
+
772
+ // Wait an extra tick
773
+ await new Promise(res => {
774
+ setTimeout(res, 0);
775
+ });
776
+
777
+ expect(searchService.searchParams?.query).to.equal(
778
+ 'first-creator AND firstCreator:X'
779
+ );
780
+ expect(searchService.searchParams?.filters).to.deep.equal({
781
+ collection: {
782
+ foo: 'inc',
783
+ },
784
+ year: {
785
+ '1950': 'gte',
786
+ '1970': 'lte',
787
+ },
788
+ });
789
+ });
790
+
713
791
  it('sets date range query when date picker selection changed', async () => {
714
792
  const searchService = new MockSearchService();
715
793
  const el = await fixture<CollectionBrowser>(
@@ -756,7 +834,8 @@ describe('Collection Browser', () => {
756
834
  // Ensure that the histogram change propagated to the collection browser's
757
835
  // date query correctly.
758
836
  await el.updateComplete;
759
- expect(el.dateRangeQueryClause).to.equal('year:[1960 TO 2000]');
837
+ expect(el.minSelectedDate).to.equal('1960');
838
+ expect(el.maxSelectedDate).to.equal('2000');
760
839
  });
761
840
 
762
841
  it('scrolls to page', async () => {
@@ -862,6 +941,7 @@ describe('Collection Browser', () => {
862
941
 
863
942
  el.baseQuery = 'single-result';
864
943
  await el.updateComplete;
944
+ await nextTick();
865
945
 
866
946
  expect(
867
947
  el.shadowRoot?.querySelector('#big-results-label')?.textContent
@@ -80,7 +80,7 @@ describe('More facets content', () => {
80
80
  );
81
81
 
82
82
  el.facetKey = 'collection';
83
- el.fullQuery = 'title:hello';
83
+ el.query = 'title:hello';
84
84
  await el.updateComplete;
85
85
 
86
86
  expect(searchService.searchParams?.query).to.equal('title:hello');
@@ -97,7 +97,7 @@ describe('More facets content', () => {
97
97
  );
98
98
 
99
99
  el.facetKey = 'collection';
100
- el.fullQuery = 'title:hello';
100
+ el.query = 'title:hello';
101
101
  await el.updateComplete;
102
102
 
103
103
  expect(searchService.searchParams?.query).to.equal('title:hello');
@@ -193,6 +193,84 @@ export const mockSuccessLoggedInAndNoPreviewResult: Result<
193
193
  },
194
194
  };
195
195
 
196
+ export const mockSuccessFirstTitleResult: Result<
197
+ SearchResponse,
198
+ SearchServiceError
199
+ > = {
200
+ success: {
201
+ request: {
202
+ clientParameters: {
203
+ user_query: 'first-title',
204
+ sort: ['title', 'asc'],
205
+ },
206
+ finalizedParameters: {
207
+ user_query: 'first-title',
208
+ sort: ['title', 'asc'],
209
+ },
210
+ },
211
+ rawResponse: {},
212
+ response: {
213
+ totalResults: 1,
214
+ returnedCount: 1,
215
+ aggregations: {
216
+ firstTitle: new Aggregation({
217
+ buckets: [{ key: 'X', doc_count: 1 }],
218
+ }),
219
+ },
220
+ results: [
221
+ new ItemHit({
222
+ fields: {
223
+ identifier: 'foo',
224
+ },
225
+ }),
226
+ ],
227
+ },
228
+ responseHeader: {
229
+ succeeded: true,
230
+ query_time: 0,
231
+ },
232
+ },
233
+ };
234
+
235
+ export const mockSuccessFirstCreatorResult: Result<
236
+ SearchResponse,
237
+ SearchServiceError
238
+ > = {
239
+ success: {
240
+ request: {
241
+ clientParameters: {
242
+ user_query: 'first-creator',
243
+ sort: ['creator', 'asc'],
244
+ },
245
+ finalizedParameters: {
246
+ user_query: 'first-creator',
247
+ sort: ['creator', 'asc'],
248
+ },
249
+ },
250
+ rawResponse: {},
251
+ response: {
252
+ totalResults: 1,
253
+ returnedCount: 1,
254
+ aggregations: {
255
+ firstCreator: new Aggregation({
256
+ buckets: [{ key: 'X', doc_count: 1 }],
257
+ }),
258
+ },
259
+ results: [
260
+ new ItemHit({
261
+ fields: {
262
+ identifier: 'foo',
263
+ },
264
+ }),
265
+ ],
266
+ },
267
+ responseHeader: {
268
+ succeeded: true,
269
+ query_time: 0,
270
+ },
271
+ },
272
+ };
273
+
196
274
  export const getMockSuccessSingleResultWithSort: (
197
275
  resultsSpy: Function
198
276
  ) => Result<SearchResponse, SearchServiceError> = (resultsSpy: Function) => ({
@@ -15,6 +15,8 @@ import {
15
15
  mockSuccessLoggedInAndNoPreviewResult,
16
16
  mockSuccessWithYearHistogramAggs,
17
17
  mockSuccessMultiLineDescription,
18
+ mockSuccessFirstTitleResult,
19
+ mockSuccessFirstCreatorResult,
18
20
  } from './mock-search-responses';
19
21
 
20
22
  export class MockSearchService implements SearchServiceInterface {
@@ -58,6 +60,10 @@ export class MockSearchService implements SearchServiceInterface {
58
60
  return mockSuccessNoPreviewResult;
59
61
  case 'loggedin-no-preview':
60
62
  return mockSuccessLoggedInAndNoPreviewResult;
63
+ case 'first-title':
64
+ return mockSuccessFirstTitleResult;
65
+ case 'first-creator':
66
+ return mockSuccessFirstCreatorResult;
61
67
  case 'with-sort':
62
68
  return getMockSuccessSingleResultWithSort(this.resultsSpy);
63
69
  default:
@@ -59,9 +59,6 @@ describe('Restoration state handler', () => {
59
59
  const restorationState = handler.getRestorationState();
60
60
  expect(restorationState.minSelectedDate).to.equal('2018');
61
61
  expect(restorationState.maxSelectedDate).to.equal('2021');
62
- expect(restorationState.dateRangeQueryClause).to.equal(
63
- 'year:"2018 TO 2021"'
64
- );
65
62
  });
66
63
 
67
64
  it('should restore creator filter from URL', async () => {
@@ -0,0 +1,52 @@
1
+ import { expect, fixture } from '@open-wc/testing';
2
+ import { html } from 'lit';
3
+ import type { AlphaBar } from '../../src/sort-filter-bar/alpha-bar';
4
+
5
+ import '../../src/sort-filter-bar/alpha-bar';
6
+
7
+ describe('Alphabetical Filter Bar', () => {
8
+ it('renders component', async () => {
9
+ const el = await fixture<AlphaBar>(html`<alpha-bar></alpha-bar>`);
10
+
11
+ // Should have all the letters
12
+ const letters = el.shadowRoot?.querySelectorAll('li');
13
+ expect(letters?.length).to.equal(26);
14
+ });
15
+
16
+ it('renders letters with items as links', async () => {
17
+ const el = await fixture<AlphaBar>(html`<alpha-bar></alpha-bar>`);
18
+
19
+ el.letterCounts = { U: 10, X: 10 };
20
+ await el.updateComplete;
21
+
22
+ // Should have exactly two letter links
23
+ const letterLinks = el.shadowRoot?.querySelectorAll('li > a[href]');
24
+ expect(letterLinks?.length).to.equal(2);
25
+ expect(letterLinks?.item(0).textContent?.trim()).to.equal('U');
26
+ expect(letterLinks?.item(1).textContent?.trim()).to.equal('X');
27
+ });
28
+
29
+ it('renders letters without items as uninteractive text', async () => {
30
+ const el = await fixture<AlphaBar>(html`<alpha-bar></alpha-bar>`);
31
+
32
+ el.letterCounts = { U: 10, X: 10 };
33
+ await el.updateComplete;
34
+
35
+ // All but the two letters above should just be inert spans, not links
36
+ const letterNonLinks = el.shadowRoot?.querySelectorAll('li > span');
37
+ expect(letterNonLinks?.length).to.equal(24);
38
+ expect(letterNonLinks?.item(0).textContent?.trim()).to.equal('A');
39
+ expect(letterNonLinks?.item(23).textContent?.trim()).to.equal('Z');
40
+ });
41
+
42
+ it('renders the selected letter with the "selected" class', async () => {
43
+ const el = await fixture<AlphaBar>(html`<alpha-bar></alpha-bar>`);
44
+
45
+ el.selectedLetter = 'B';
46
+ await el.updateComplete;
47
+
48
+ const selectedLetter = el.shadowRoot?.querySelector('li.selected');
49
+ expect(selectedLetter).to.exist;
50
+ expect(selectedLetter?.textContent?.trim()).to.equal('B');
51
+ });
52
+ });
@@ -185,3 +185,47 @@ describe('Display mode/style buttons', () => {
185
185
  expect(displayModeTitle).to.equal('Tile view');
186
186
  });
187
187
  });
188
+
189
+ describe('Sort/filter bar letter behavior', () => {
190
+ it('sets the selected title letter when clicked', async () => {
191
+ const el = await fixture<SortFilterBar>(html`
192
+ <sort-filter-bar></sort-filter-bar>
193
+ `);
194
+
195
+ el.selectedSort = 'title' as SortField;
196
+ el.prefixFilterCountMap = { title: { T: 1 }, creator: {} };
197
+ await el.updateComplete;
198
+
199
+ const alphaBar = el.shadowRoot?.querySelector('alpha-bar');
200
+ const letterLink = alphaBar?.shadowRoot?.querySelector(
201
+ 'li > a[href]'
202
+ ) as HTMLAnchorElement;
203
+ expect(letterLink?.textContent?.trim()).to.equal('T');
204
+
205
+ letterLink?.click();
206
+ await el.updateComplete;
207
+
208
+ expect(el.selectedTitleFilter).to.equal('T');
209
+ });
210
+
211
+ it('sets the selected creator letter when clicked', async () => {
212
+ const el = await fixture<SortFilterBar>(html`
213
+ <sort-filter-bar></sort-filter-bar>
214
+ `);
215
+
216
+ el.selectedSort = 'creator' as SortField;
217
+ el.prefixFilterCountMap = { title: {}, creator: { C: 1 } };
218
+ await el.updateComplete;
219
+
220
+ const alphaBar = el.shadowRoot?.querySelector('alpha-bar');
221
+ const letterLink = alphaBar?.shadowRoot?.querySelector(
222
+ 'li > a[href]'
223
+ ) as HTMLAnchorElement;
224
+ expect(letterLink?.textContent?.trim()).to.equal('C');
225
+
226
+ letterLink?.click();
227
+ await el.updateComplete;
228
+
229
+ expect(el.selectedCreatorFilter).to.equal('C');
230
+ });
231
+ });