@internetarchive/collection-browser 4.5.1-alpha-webdev8221.0 → 4.5.1

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 (63) hide show
  1. package/dist/index.js.map +1 -1
  2. package/dist/src/app-root.js +683 -683
  3. package/dist/src/app-root.js.map +1 -1
  4. package/dist/src/collection-browser.js +766 -766
  5. package/dist/src/collection-browser.js.map +1 -1
  6. package/dist/src/collection-facets/facet-row.js +143 -143
  7. package/dist/src/collection-facets/facet-row.js.map +1 -1
  8. package/dist/src/collection-facets/facets-template.js +24 -24
  9. package/dist/src/collection-facets/facets-template.js.map +1 -1
  10. package/dist/src/data-source/collection-browser-data-source-interface.js.map +1 -1
  11. package/dist/src/data-source/collection-browser-data-source.js.map +1 -1
  12. package/dist/src/restoration-state-handler.js.map +1 -1
  13. package/dist/src/styles/tile-action-styles.js +43 -43
  14. package/dist/src/styles/tile-action-styles.js.map +1 -1
  15. package/dist/src/tiles/base-tile-component.js +11 -11
  16. package/dist/src/tiles/base-tile-component.js.map +1 -1
  17. package/dist/src/tiles/grid/item-tile.js +138 -138
  18. package/dist/src/tiles/grid/item-tile.js.map +1 -1
  19. package/dist/src/tiles/list/tile-list-compact-header.js +62 -62
  20. package/dist/src/tiles/list/tile-list-compact-header.js.map +1 -1
  21. package/dist/src/tiles/list/tile-list-compact.js +123 -123
  22. package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
  23. package/dist/src/tiles/list/tile-list.js +310 -310
  24. package/dist/src/tiles/list/tile-list.js.map +1 -1
  25. package/dist/src/tiles/models.js.map +1 -1
  26. package/dist/src/tiles/tile-dispatcher.js +286 -286
  27. package/dist/src/tiles/tile-dispatcher.js.map +1 -1
  28. package/dist/src/tiles/tile-display-value-provider.js.map +1 -1
  29. package/dist/src/utils/date-filter-field.js.map +1 -1
  30. package/dist/test/collection-browser.test.js +203 -203
  31. package/dist/test/collection-browser.test.js.map +1 -1
  32. package/dist/test/collection-facets/facet-row.test.js +31 -31
  33. package/dist/test/collection-facets/facet-row.test.js.map +1 -1
  34. package/dist/test/tiles/grid/item-tile.test.js +77 -77
  35. package/dist/test/tiles/grid/item-tile.test.js.map +1 -1
  36. package/dist/test/tiles/list/tile-list.test.js +134 -134
  37. package/dist/test/tiles/list/tile-list.test.js.map +1 -1
  38. package/dist/test/tiles/tile-dispatcher.test.js +92 -92
  39. package/dist/test/tiles/tile-dispatcher.test.js.map +1 -1
  40. package/index.ts +29 -29
  41. package/package.json +1 -1
  42. package/src/app-root.ts +1284 -1284
  43. package/src/collection-browser.ts +3165 -3165
  44. package/src/collection-facets/facet-row.ts +309 -309
  45. package/src/collection-facets/facets-template.ts +85 -85
  46. package/src/data-source/collection-browser-data-source-interface.ts +351 -351
  47. package/src/data-source/collection-browser-data-source.ts +1474 -1474
  48. package/src/restoration-state-handler.ts +550 -550
  49. package/src/styles/tile-action-styles.ts +59 -59
  50. package/src/tiles/base-tile-component.ts +124 -124
  51. package/src/tiles/grid/item-tile.ts +347 -347
  52. package/src/tiles/list/tile-list-compact-header.ts +112 -112
  53. package/src/tiles/list/tile-list-compact.ts +278 -278
  54. package/src/tiles/list/tile-list.ts +718 -718
  55. package/src/tiles/models.ts +21 -21
  56. package/src/tiles/tile-dispatcher.ts +637 -637
  57. package/src/tiles/tile-display-value-provider.ts +133 -133
  58. package/src/utils/date-filter-field.ts +11 -11
  59. package/test/collection-browser.test.ts +2639 -2639
  60. package/test/collection-facets/facet-row.test.ts +421 -421
  61. package/test/tiles/grid/item-tile.test.ts +520 -520
  62. package/test/tiles/list/tile-list.test.ts +576 -576
  63. package/test/tiles/tile-dispatcher.test.ts +320 -320
@@ -1,421 +1,421 @@
1
- import { expect, fixture } from '@open-wc/testing';
2
- import sinon from 'sinon';
3
- import { html } from 'lit';
4
- import type { FacetRow } from '../../src/collection-facets/facet-row';
5
- import '../../src/collection-facets/facet-row';
6
- import type { FacetState } from '../../src/models';
7
-
8
- describe('Facet row', () => {
9
- it('renders nothing if no bucket provided', async () => {
10
- const el = await fixture<FacetRow>(
11
- html`<facet-row .facetType=${'subject'}></facet-row>`,
12
- );
13
-
14
- expect(el.shadowRoot?.querySelector('.facet-row-container')).not.to.exist;
15
- });
16
-
17
- it('renders nothing if no facet type provided', async () => {
18
- const bucket = {
19
- key: 'foo',
20
- state: 'none' as FacetState,
21
- count: 5,
22
- };
23
-
24
- const el = await fixture<FacetRow>(
25
- html`<facet-row .bucket=${bucket}></facet-row>`,
26
- );
27
-
28
- expect(el.shadowRoot?.querySelector('.facet-row-container')).not.to.exist;
29
- });
30
-
31
- it('renders provided bucket as facet row', async () => {
32
- const bucket = {
33
- key: 'foo',
34
- state: 'none' as FacetState,
35
- count: 5,
36
- };
37
-
38
- const el = await fixture<FacetRow>(
39
- html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
40
- );
41
-
42
- expect(el.shadowRoot?.querySelector('.facet-row-container')).to.exist;
43
- expect(
44
- el.shadowRoot?.querySelectorAll('input[type="checkbox"]'),
45
- ).to.have.length(2);
46
- expect(el.shadowRoot?.querySelectorAll('label')).to.have.length(2);
47
-
48
- const labelText = el.shadowRoot?.querySelector('.facet-info-display');
49
- expect(labelText?.textContent?.trim()).to.match(/^foo\s*5$/);
50
- });
51
-
52
- it('renders locale-appropriate facet count', async () => {
53
- const bucket = {
54
- key: 'foo',
55
- state: 'none' as FacetState,
56
- count: 54321,
57
- };
58
-
59
- const el = await fixture<FacetRow>(
60
- html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
61
- );
62
-
63
- const facetCount = el.shadowRoot?.querySelector('.facet-count');
64
- expect(facetCount?.textContent).to.equal('54,321');
65
- });
66
-
67
- it('renders selected facets with checked checkbox', async () => {
68
- const bucket = {
69
- key: 'foo',
70
- state: 'selected' as FacetState,
71
- count: 5,
72
- };
73
-
74
- const el = await fixture<FacetRow>(
75
- html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
76
- );
77
-
78
- // "Positive" checkbox is checked; "Negative" checkbox is not checked
79
- const selectCheckbox = el.shadowRoot?.querySelector(
80
- '.select-facet-checkbox',
81
- ) as HTMLInputElement;
82
- const hideCheckbox = el.shadowRoot?.querySelector(
83
- '.hide-facet-checkbox',
84
- ) as HTMLInputElement;
85
- expect(selectCheckbox?.checked).to.be.true;
86
- expect(hideCheckbox?.checked).to.be.false;
87
-
88
- // Eye icon is not in its active state
89
- expect(
90
- el.shadowRoot?.querySelector('.hide-facet-icon'),
91
- ).to.exist.and.satisfy(
92
- (icon: HTMLElement) => !icon.classList.contains('active'),
93
- );
94
- });
95
-
96
- it('renders hidden facets with closed eye icon', async () => {
97
- const bucket = {
98
- key: 'foo',
99
- state: 'hidden' as FacetState,
100
- count: 5,
101
- };
102
-
103
- const el = await fixture<FacetRow>(
104
- html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
105
- );
106
-
107
- // "Positive" checkbox is not checked; "Negative" checkbox is checked
108
- const selectCheckbox = el.shadowRoot?.querySelector(
109
- '.select-facet-checkbox',
110
- ) as HTMLInputElement;
111
- const hideCheckbox = el.shadowRoot?.querySelector(
112
- '.hide-facet-checkbox',
113
- ) as HTMLInputElement;
114
- expect(selectCheckbox?.checked).to.be.false;
115
- expect(hideCheckbox?.checked).to.be.true;
116
-
117
- // Eye icon is in its "active" state
118
- expect(
119
- el.shadowRoot?.querySelector('.hide-facet-icon'),
120
- ).to.exist.and.satisfy((icon: HTMLElement) =>
121
- icon.classList.contains('active'),
122
- );
123
- });
124
-
125
- it('omits hide button when property is specified (and facet state is not hidden)', async () => {
126
- const bucket = {
127
- key: 'foo',
128
- state: 'none' as FacetState,
129
- count: 5,
130
- };
131
-
132
- const el = await fixture<FacetRow>(
133
- html`<facet-row
134
- .facetType=${'subject'}
135
- .bucket=${bucket}
136
- omitHideButton
137
- ></facet-row>`,
138
- );
139
-
140
- // Hide button's container is hidden
141
- expect(
142
- el.shadowRoot
143
- ?.querySelector('.hide-facet-container')
144
- ?.hasAttribute('hidden'),
145
- ).to.be.true;
146
- });
147
-
148
- it('does not omit hide button when facet state is hidden, even if property specified', async () => {
149
- const bucket = {
150
- key: 'foo',
151
- state: 'hidden' as FacetState,
152
- count: 5,
153
- };
154
-
155
- const el = await fixture<FacetRow>(
156
- html`<facet-row
157
- .facetType=${'subject'}
158
- .bucket=${bucket}
159
- omitHideButton
160
- ></facet-row>`,
161
- );
162
-
163
- // Hide button's container is NOT hidden (i.e., we SHOW the hide button like normal)
164
- expect(
165
- el.shadowRoot
166
- ?.querySelector('.hide-facet-container')
167
- ?.hasAttribute('hidden'),
168
- ).to.be.false;
169
- });
170
-
171
- it('renders correct accessible label for unchecked negative facets', async () => {
172
- const bucket = {
173
- key: 'foo',
174
- state: 'none' as FacetState,
175
- count: 5,
176
- };
177
-
178
- const el = await fixture<FacetRow>(
179
- html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
180
- );
181
-
182
- const hideFacetLabel = el.shadowRoot?.querySelector('.hide-facet-icon');
183
- expect(hideFacetLabel?.textContent?.trim()).to.match(/^Hide subject: foo$/);
184
- });
185
-
186
- it('renders correct accessible label for checked negative facets', async () => {
187
- const bucket = {
188
- key: 'foo',
189
- state: 'hidden' as FacetState,
190
- count: 5,
191
- };
192
-
193
- const el = await fixture<FacetRow>(
194
- html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
195
- );
196
-
197
- const hideFacetLabel = el.shadowRoot?.querySelector('.hide-facet-icon');
198
- expect(hideFacetLabel?.textContent?.trim()).to.match(
199
- /^Unhide subject: foo$/,
200
- );
201
- });
202
-
203
- it('renders collection facets as links', async () => {
204
- const bucket = {
205
- key: 'foo',
206
- state: 'none' as FacetState,
207
- count: 5,
208
- };
209
-
210
- const el = await fixture<FacetRow>(
211
- html`<facet-row
212
- .facetType=${'collection'}
213
- .bucket=${bucket}
214
- ></facet-row>`,
215
- );
216
-
217
- const collectionName = el.shadowRoot?.querySelector(
218
- '.facet-title > a:link',
219
- );
220
- expect(collectionName).to.exist;
221
- expect(collectionName?.getAttribute('href')).to.equal('/details/foo');
222
- });
223
-
224
- it('does not render non-collection facets as links', async () => {
225
- const bucket = {
226
- key: 'foo',
227
- state: 'none' as FacetState,
228
- count: 5,
229
- };
230
-
231
- const el = await fixture<FacetRow>(
232
- html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
233
- );
234
-
235
- expect(el.shadowRoot?.querySelector('a:link')).not.to.exist;
236
- });
237
-
238
- it('emits event when facet checkbox is clicked', async () => {
239
- const facetClickSpy = sinon.spy();
240
- const bucket = {
241
- key: 'foo',
242
- state: 'none' as FacetState,
243
- count: 5,
244
- };
245
-
246
- const el = await fixture<FacetRow>(
247
- html`<facet-row
248
- .facetType=${'subject'}
249
- .bucket=${bucket}
250
- @facetClick=${facetClickSpy}
251
- ></facet-row>`,
252
- );
253
-
254
- const positiveFacetCheck = el.shadowRoot?.querySelector(
255
- '.select-facet-checkbox',
256
- ) as HTMLInputElement;
257
- expect(positiveFacetCheck).to.exist;
258
- positiveFacetCheck.click();
259
-
260
- expect(facetClickSpy.callCount).to.equal(1);
261
- expect(facetClickSpy.lastCall.args[0]?.detail).to.deep.equal({
262
- facetType: 'subject',
263
- bucket: {
264
- key: 'foo',
265
- state: 'selected',
266
- count: 5,
267
- },
268
- negative: false,
269
- });
270
- });
271
-
272
- it('emits event when facet checkbox is unchecked', async () => {
273
- const facetClickSpy = sinon.spy();
274
- const bucket = {
275
- key: 'foo',
276
- state: 'selected' as FacetState,
277
- count: 5,
278
- };
279
-
280
- const el = await fixture<FacetRow>(
281
- html`<facet-row
282
- .facetType=${'subject'}
283
- .bucket=${bucket}
284
- @facetClick=${facetClickSpy}
285
- ></facet-row>`,
286
- );
287
-
288
- const positiveFacetCheck = el.shadowRoot?.querySelector(
289
- '.select-facet-checkbox',
290
- ) as HTMLInputElement;
291
- expect(positiveFacetCheck).to.exist;
292
- positiveFacetCheck.click();
293
-
294
- expect(facetClickSpy.callCount).to.equal(1);
295
- expect(facetClickSpy.lastCall.args[0]?.detail).to.deep.equal({
296
- facetType: 'subject',
297
- bucket: {
298
- key: 'foo',
299
- state: 'none',
300
- count: 5,
301
- },
302
- negative: false,
303
- });
304
- });
305
-
306
- it('emits event when facet negative icon is clicked', async () => {
307
- const facetClickSpy = sinon.spy();
308
- const bucket = {
309
- key: 'foo',
310
- state: 'none' as FacetState,
311
- count: 5,
312
- };
313
-
314
- const el = await fixture<FacetRow>(
315
- html`<facet-row
316
- .facetType=${'subject'}
317
- .bucket=${bucket}
318
- @facetClick=${facetClickSpy}
319
- ></facet-row>`,
320
- );
321
-
322
- const negativeFacetIcon = el.shadowRoot?.querySelector(
323
- '.hide-facet-icon',
324
- ) as HTMLLabelElement;
325
- expect(negativeFacetIcon).to.exist;
326
- negativeFacetIcon.click();
327
-
328
- expect(facetClickSpy.callCount).to.equal(1);
329
- expect(facetClickSpy.lastCall.args[0]?.detail).to.deep.equal({
330
- facetType: 'subject',
331
- bucket: {
332
- key: 'foo',
333
- state: 'hidden',
334
- count: 5,
335
- },
336
- negative: true,
337
- });
338
- });
339
-
340
- it('emits event when facet negative icon is unchecked', async () => {
341
- const facetClickSpy = sinon.spy();
342
- const bucket = {
343
- key: 'foo',
344
- state: 'hidden' as FacetState,
345
- count: 5,
346
- };
347
-
348
- const el = await fixture<FacetRow>(
349
- html`<facet-row
350
- .facetType=${'subject'}
351
- .bucket=${bucket}
352
- @facetClick=${facetClickSpy}
353
- ></facet-row>`,
354
- );
355
-
356
- const negativeFacetIcon = el.shadowRoot?.querySelector(
357
- '.hide-facet-icon',
358
- ) as HTMLLabelElement;
359
- expect(negativeFacetIcon).to.exist;
360
- negativeFacetIcon.click();
361
-
362
- expect(facetClickSpy.callCount).to.equal(1);
363
- expect(facetClickSpy.lastCall.args[0]?.detail).to.deep.equal({
364
- facetType: 'subject',
365
- bucket: {
366
- key: 'foo',
367
- state: 'none',
368
- count: 5,
369
- },
370
- negative: true,
371
- });
372
- });
373
-
374
- it('selects/deselects facet when label is clicked', async () => {
375
- const facetClickSpy = sinon.spy();
376
- const bucket = {
377
- key: 'foo',
378
- state: 'none' as FacetState,
379
- count: 5,
380
- };
381
-
382
- const el = await fixture<FacetRow>(
383
- html`<facet-row
384
- .facetType=${'subject'}
385
- .bucket=${bucket}
386
- @facetClick=${facetClickSpy}
387
- ></facet-row>`,
388
- );
389
-
390
- const facetLabel = el.shadowRoot?.querySelector(
391
- '.facet-info-display',
392
- ) as HTMLLabelElement;
393
- expect(facetLabel).to.exist;
394
-
395
- // Select facet by clicking label
396
- facetLabel.click();
397
- expect(facetClickSpy.callCount).to.equal(1);
398
- expect(facetClickSpy.lastCall.args[0]?.detail).to.deep.equal({
399
- facetType: 'subject',
400
- bucket: {
401
- key: 'foo',
402
- state: 'selected',
403
- count: 5,
404
- },
405
- negative: false,
406
- });
407
-
408
- // Deselect facet by clicking label
409
- facetLabel.click();
410
- expect(facetClickSpy.callCount).to.equal(2);
411
- expect(facetClickSpy.lastCall.args[0]?.detail).to.deep.equal({
412
- facetType: 'subject',
413
- bucket: {
414
- key: 'foo',
415
- state: 'none',
416
- count: 5,
417
- },
418
- negative: false,
419
- });
420
- });
421
- });
1
+ import { expect, fixture } from '@open-wc/testing';
2
+ import sinon from 'sinon';
3
+ import { html } from 'lit';
4
+ import type { FacetRow } from '../../src/collection-facets/facet-row';
5
+ import '../../src/collection-facets/facet-row';
6
+ import type { FacetState } from '../../src/models';
7
+
8
+ describe('Facet row', () => {
9
+ it('renders nothing if no bucket provided', async () => {
10
+ const el = await fixture<FacetRow>(
11
+ html`<facet-row .facetType=${'subject'}></facet-row>`,
12
+ );
13
+
14
+ expect(el.shadowRoot?.querySelector('.facet-row-container')).not.to.exist;
15
+ });
16
+
17
+ it('renders nothing if no facet type provided', async () => {
18
+ const bucket = {
19
+ key: 'foo',
20
+ state: 'none' as FacetState,
21
+ count: 5,
22
+ };
23
+
24
+ const el = await fixture<FacetRow>(
25
+ html`<facet-row .bucket=${bucket}></facet-row>`,
26
+ );
27
+
28
+ expect(el.shadowRoot?.querySelector('.facet-row-container')).not.to.exist;
29
+ });
30
+
31
+ it('renders provided bucket as facet row', async () => {
32
+ const bucket = {
33
+ key: 'foo',
34
+ state: 'none' as FacetState,
35
+ count: 5,
36
+ };
37
+
38
+ const el = await fixture<FacetRow>(
39
+ html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
40
+ );
41
+
42
+ expect(el.shadowRoot?.querySelector('.facet-row-container')).to.exist;
43
+ expect(
44
+ el.shadowRoot?.querySelectorAll('input[type="checkbox"]'),
45
+ ).to.have.length(2);
46
+ expect(el.shadowRoot?.querySelectorAll('label')).to.have.length(2);
47
+
48
+ const labelText = el.shadowRoot?.querySelector('.facet-info-display');
49
+ expect(labelText?.textContent?.trim()).to.match(/^foo\s*5$/);
50
+ });
51
+
52
+ it('renders locale-appropriate facet count', async () => {
53
+ const bucket = {
54
+ key: 'foo',
55
+ state: 'none' as FacetState,
56
+ count: 54321,
57
+ };
58
+
59
+ const el = await fixture<FacetRow>(
60
+ html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
61
+ );
62
+
63
+ const facetCount = el.shadowRoot?.querySelector('.facet-count');
64
+ expect(facetCount?.textContent).to.equal('54,321');
65
+ });
66
+
67
+ it('renders selected facets with checked checkbox', async () => {
68
+ const bucket = {
69
+ key: 'foo',
70
+ state: 'selected' as FacetState,
71
+ count: 5,
72
+ };
73
+
74
+ const el = await fixture<FacetRow>(
75
+ html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
76
+ );
77
+
78
+ // "Positive" checkbox is checked; "Negative" checkbox is not checked
79
+ const selectCheckbox = el.shadowRoot?.querySelector(
80
+ '.select-facet-checkbox',
81
+ ) as HTMLInputElement;
82
+ const hideCheckbox = el.shadowRoot?.querySelector(
83
+ '.hide-facet-checkbox',
84
+ ) as HTMLInputElement;
85
+ expect(selectCheckbox?.checked).to.be.true;
86
+ expect(hideCheckbox?.checked).to.be.false;
87
+
88
+ // Eye icon is not in its active state
89
+ expect(
90
+ el.shadowRoot?.querySelector('.hide-facet-icon'),
91
+ ).to.exist.and.satisfy(
92
+ (icon: HTMLElement) => !icon.classList.contains('active'),
93
+ );
94
+ });
95
+
96
+ it('renders hidden facets with closed eye icon', async () => {
97
+ const bucket = {
98
+ key: 'foo',
99
+ state: 'hidden' as FacetState,
100
+ count: 5,
101
+ };
102
+
103
+ const el = await fixture<FacetRow>(
104
+ html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
105
+ );
106
+
107
+ // "Positive" checkbox is not checked; "Negative" checkbox is checked
108
+ const selectCheckbox = el.shadowRoot?.querySelector(
109
+ '.select-facet-checkbox',
110
+ ) as HTMLInputElement;
111
+ const hideCheckbox = el.shadowRoot?.querySelector(
112
+ '.hide-facet-checkbox',
113
+ ) as HTMLInputElement;
114
+ expect(selectCheckbox?.checked).to.be.false;
115
+ expect(hideCheckbox?.checked).to.be.true;
116
+
117
+ // Eye icon is in its "active" state
118
+ expect(
119
+ el.shadowRoot?.querySelector('.hide-facet-icon'),
120
+ ).to.exist.and.satisfy((icon: HTMLElement) =>
121
+ icon.classList.contains('active'),
122
+ );
123
+ });
124
+
125
+ it('omits hide button when property is specified (and facet state is not hidden)', async () => {
126
+ const bucket = {
127
+ key: 'foo',
128
+ state: 'none' as FacetState,
129
+ count: 5,
130
+ };
131
+
132
+ const el = await fixture<FacetRow>(
133
+ html`<facet-row
134
+ .facetType=${'subject'}
135
+ .bucket=${bucket}
136
+ omitHideButton
137
+ ></facet-row>`,
138
+ );
139
+
140
+ // Hide button's container is hidden
141
+ expect(
142
+ el.shadowRoot
143
+ ?.querySelector('.hide-facet-container')
144
+ ?.hasAttribute('hidden'),
145
+ ).to.be.true;
146
+ });
147
+
148
+ it('does not omit hide button when facet state is hidden, even if property specified', async () => {
149
+ const bucket = {
150
+ key: 'foo',
151
+ state: 'hidden' as FacetState,
152
+ count: 5,
153
+ };
154
+
155
+ const el = await fixture<FacetRow>(
156
+ html`<facet-row
157
+ .facetType=${'subject'}
158
+ .bucket=${bucket}
159
+ omitHideButton
160
+ ></facet-row>`,
161
+ );
162
+
163
+ // Hide button's container is NOT hidden (i.e., we SHOW the hide button like normal)
164
+ expect(
165
+ el.shadowRoot
166
+ ?.querySelector('.hide-facet-container')
167
+ ?.hasAttribute('hidden'),
168
+ ).to.be.false;
169
+ });
170
+
171
+ it('renders correct accessible label for unchecked negative facets', async () => {
172
+ const bucket = {
173
+ key: 'foo',
174
+ state: 'none' as FacetState,
175
+ count: 5,
176
+ };
177
+
178
+ const el = await fixture<FacetRow>(
179
+ html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
180
+ );
181
+
182
+ const hideFacetLabel = el.shadowRoot?.querySelector('.hide-facet-icon');
183
+ expect(hideFacetLabel?.textContent?.trim()).to.match(/^Hide subject: foo$/);
184
+ });
185
+
186
+ it('renders correct accessible label for checked negative facets', async () => {
187
+ const bucket = {
188
+ key: 'foo',
189
+ state: 'hidden' as FacetState,
190
+ count: 5,
191
+ };
192
+
193
+ const el = await fixture<FacetRow>(
194
+ html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
195
+ );
196
+
197
+ const hideFacetLabel = el.shadowRoot?.querySelector('.hide-facet-icon');
198
+ expect(hideFacetLabel?.textContent?.trim()).to.match(
199
+ /^Unhide subject: foo$/,
200
+ );
201
+ });
202
+
203
+ it('renders collection facets as links', async () => {
204
+ const bucket = {
205
+ key: 'foo',
206
+ state: 'none' as FacetState,
207
+ count: 5,
208
+ };
209
+
210
+ const el = await fixture<FacetRow>(
211
+ html`<facet-row
212
+ .facetType=${'collection'}
213
+ .bucket=${bucket}
214
+ ></facet-row>`,
215
+ );
216
+
217
+ const collectionName = el.shadowRoot?.querySelector(
218
+ '.facet-title > a:link',
219
+ );
220
+ expect(collectionName).to.exist;
221
+ expect(collectionName?.getAttribute('href')).to.equal('/details/foo');
222
+ });
223
+
224
+ it('does not render non-collection facets as links', async () => {
225
+ const bucket = {
226
+ key: 'foo',
227
+ state: 'none' as FacetState,
228
+ count: 5,
229
+ };
230
+
231
+ const el = await fixture<FacetRow>(
232
+ html`<facet-row .facetType=${'subject'} .bucket=${bucket}></facet-row>`,
233
+ );
234
+
235
+ expect(el.shadowRoot?.querySelector('a:link')).not.to.exist;
236
+ });
237
+
238
+ it('emits event when facet checkbox is clicked', async () => {
239
+ const facetClickSpy = sinon.spy();
240
+ const bucket = {
241
+ key: 'foo',
242
+ state: 'none' as FacetState,
243
+ count: 5,
244
+ };
245
+
246
+ const el = await fixture<FacetRow>(
247
+ html`<facet-row
248
+ .facetType=${'subject'}
249
+ .bucket=${bucket}
250
+ @facetClick=${facetClickSpy}
251
+ ></facet-row>`,
252
+ );
253
+
254
+ const positiveFacetCheck = el.shadowRoot?.querySelector(
255
+ '.select-facet-checkbox',
256
+ ) as HTMLInputElement;
257
+ expect(positiveFacetCheck).to.exist;
258
+ positiveFacetCheck.click();
259
+
260
+ expect(facetClickSpy.callCount).to.equal(1);
261
+ expect(facetClickSpy.lastCall.args[0]?.detail).to.deep.equal({
262
+ facetType: 'subject',
263
+ bucket: {
264
+ key: 'foo',
265
+ state: 'selected',
266
+ count: 5,
267
+ },
268
+ negative: false,
269
+ });
270
+ });
271
+
272
+ it('emits event when facet checkbox is unchecked', async () => {
273
+ const facetClickSpy = sinon.spy();
274
+ const bucket = {
275
+ key: 'foo',
276
+ state: 'selected' as FacetState,
277
+ count: 5,
278
+ };
279
+
280
+ const el = await fixture<FacetRow>(
281
+ html`<facet-row
282
+ .facetType=${'subject'}
283
+ .bucket=${bucket}
284
+ @facetClick=${facetClickSpy}
285
+ ></facet-row>`,
286
+ );
287
+
288
+ const positiveFacetCheck = el.shadowRoot?.querySelector(
289
+ '.select-facet-checkbox',
290
+ ) as HTMLInputElement;
291
+ expect(positiveFacetCheck).to.exist;
292
+ positiveFacetCheck.click();
293
+
294
+ expect(facetClickSpy.callCount).to.equal(1);
295
+ expect(facetClickSpy.lastCall.args[0]?.detail).to.deep.equal({
296
+ facetType: 'subject',
297
+ bucket: {
298
+ key: 'foo',
299
+ state: 'none',
300
+ count: 5,
301
+ },
302
+ negative: false,
303
+ });
304
+ });
305
+
306
+ it('emits event when facet negative icon is clicked', async () => {
307
+ const facetClickSpy = sinon.spy();
308
+ const bucket = {
309
+ key: 'foo',
310
+ state: 'none' as FacetState,
311
+ count: 5,
312
+ };
313
+
314
+ const el = await fixture<FacetRow>(
315
+ html`<facet-row
316
+ .facetType=${'subject'}
317
+ .bucket=${bucket}
318
+ @facetClick=${facetClickSpy}
319
+ ></facet-row>`,
320
+ );
321
+
322
+ const negativeFacetIcon = el.shadowRoot?.querySelector(
323
+ '.hide-facet-icon',
324
+ ) as HTMLLabelElement;
325
+ expect(negativeFacetIcon).to.exist;
326
+ negativeFacetIcon.click();
327
+
328
+ expect(facetClickSpy.callCount).to.equal(1);
329
+ expect(facetClickSpy.lastCall.args[0]?.detail).to.deep.equal({
330
+ facetType: 'subject',
331
+ bucket: {
332
+ key: 'foo',
333
+ state: 'hidden',
334
+ count: 5,
335
+ },
336
+ negative: true,
337
+ });
338
+ });
339
+
340
+ it('emits event when facet negative icon is unchecked', async () => {
341
+ const facetClickSpy = sinon.spy();
342
+ const bucket = {
343
+ key: 'foo',
344
+ state: 'hidden' as FacetState,
345
+ count: 5,
346
+ };
347
+
348
+ const el = await fixture<FacetRow>(
349
+ html`<facet-row
350
+ .facetType=${'subject'}
351
+ .bucket=${bucket}
352
+ @facetClick=${facetClickSpy}
353
+ ></facet-row>`,
354
+ );
355
+
356
+ const negativeFacetIcon = el.shadowRoot?.querySelector(
357
+ '.hide-facet-icon',
358
+ ) as HTMLLabelElement;
359
+ expect(negativeFacetIcon).to.exist;
360
+ negativeFacetIcon.click();
361
+
362
+ expect(facetClickSpy.callCount).to.equal(1);
363
+ expect(facetClickSpy.lastCall.args[0]?.detail).to.deep.equal({
364
+ facetType: 'subject',
365
+ bucket: {
366
+ key: 'foo',
367
+ state: 'none',
368
+ count: 5,
369
+ },
370
+ negative: true,
371
+ });
372
+ });
373
+
374
+ it('selects/deselects facet when label is clicked', async () => {
375
+ const facetClickSpy = sinon.spy();
376
+ const bucket = {
377
+ key: 'foo',
378
+ state: 'none' as FacetState,
379
+ count: 5,
380
+ };
381
+
382
+ const el = await fixture<FacetRow>(
383
+ html`<facet-row
384
+ .facetType=${'subject'}
385
+ .bucket=${bucket}
386
+ @facetClick=${facetClickSpy}
387
+ ></facet-row>`,
388
+ );
389
+
390
+ const facetLabel = el.shadowRoot?.querySelector(
391
+ '.facet-info-display',
392
+ ) as HTMLLabelElement;
393
+ expect(facetLabel).to.exist;
394
+
395
+ // Select facet by clicking label
396
+ facetLabel.click();
397
+ expect(facetClickSpy.callCount).to.equal(1);
398
+ expect(facetClickSpy.lastCall.args[0]?.detail).to.deep.equal({
399
+ facetType: 'subject',
400
+ bucket: {
401
+ key: 'foo',
402
+ state: 'selected',
403
+ count: 5,
404
+ },
405
+ negative: false,
406
+ });
407
+
408
+ // Deselect facet by clicking label
409
+ facetLabel.click();
410
+ expect(facetClickSpy.callCount).to.equal(2);
411
+ expect(facetClickSpy.lastCall.args[0]?.detail).to.deep.equal({
412
+ facetType: 'subject',
413
+ bucket: {
414
+ key: 'foo',
415
+ state: 'none',
416
+ count: 5,
417
+ },
418
+ negative: false,
419
+ });
420
+ });
421
+ });