@internetarchive/collection-browser 0.2.22 → 0.3.0-alpha.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 (220) hide show
  1. package/.editorconfig +29 -29
  2. package/.github/workflows/ci.yml +26 -26
  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/LICENSE +661 -661
  8. package/README.md +83 -83
  9. package/dist/index.d.ts +9 -9
  10. package/dist/index.js +9 -9
  11. package/dist/src/app-root.d.ts +42 -39
  12. package/dist/src/app-root.js +236 -203
  13. package/dist/src/app-root.js.map +1 -1
  14. package/dist/src/assets/img/icons/arrow-left.d.ts +2 -2
  15. package/dist/src/assets/img/icons/arrow-left.js +2 -2
  16. package/dist/src/assets/img/icons/arrow-right.d.ts +2 -2
  17. package/dist/src/assets/img/icons/arrow-right.js +2 -2
  18. package/dist/src/assets/img/icons/chevron.d.ts +2 -2
  19. package/dist/src/assets/img/icons/chevron.js +2 -2
  20. package/dist/src/assets/img/icons/empty-query.d.ts +2 -2
  21. package/dist/src/assets/img/icons/empty-query.js +2 -2
  22. package/dist/src/assets/img/icons/eye-closed.d.ts +2 -2
  23. package/dist/src/assets/img/icons/eye-closed.js +2 -2
  24. package/dist/src/assets/img/icons/eye.d.ts +2 -2
  25. package/dist/src/assets/img/icons/eye.js +2 -2
  26. package/dist/src/assets/img/icons/favorite-filled.d.ts +1 -1
  27. package/dist/src/assets/img/icons/favorite-filled.js +2 -2
  28. package/dist/src/assets/img/icons/login-required.d.ts +1 -1
  29. package/dist/src/assets/img/icons/login-required.js +2 -2
  30. package/dist/src/assets/img/icons/mediatype/account.d.ts +1 -1
  31. package/dist/src/assets/img/icons/mediatype/account.js +2 -2
  32. package/dist/src/assets/img/icons/mediatype/audio.d.ts +1 -1
  33. package/dist/src/assets/img/icons/mediatype/audio.js +2 -2
  34. package/dist/src/assets/img/icons/mediatype/collection.d.ts +1 -1
  35. package/dist/src/assets/img/icons/mediatype/collection.js +2 -2
  36. package/dist/src/assets/img/icons/mediatype/data.d.ts +1 -1
  37. package/dist/src/assets/img/icons/mediatype/data.js +2 -2
  38. package/dist/src/assets/img/icons/mediatype/etree.d.ts +1 -1
  39. package/dist/src/assets/img/icons/mediatype/etree.js +2 -2
  40. package/dist/src/assets/img/icons/mediatype/film.d.ts +1 -1
  41. package/dist/src/assets/img/icons/mediatype/film.js +2 -2
  42. package/dist/src/assets/img/icons/mediatype/images.d.ts +1 -1
  43. package/dist/src/assets/img/icons/mediatype/images.js +2 -2
  44. package/dist/src/assets/img/icons/mediatype/radio.d.ts +1 -1
  45. package/dist/src/assets/img/icons/mediatype/radio.js +2 -2
  46. package/dist/src/assets/img/icons/mediatype/software.d.ts +1 -1
  47. package/dist/src/assets/img/icons/mediatype/software.js +2 -2
  48. package/dist/src/assets/img/icons/mediatype/texts.d.ts +1 -1
  49. package/dist/src/assets/img/icons/mediatype/texts.js +2 -2
  50. package/dist/src/assets/img/icons/mediatype/tv.d.ts +1 -1
  51. package/dist/src/assets/img/icons/mediatype/tv.js +2 -2
  52. package/dist/src/assets/img/icons/mediatype/video.d.ts +1 -1
  53. package/dist/src/assets/img/icons/mediatype/video.js +2 -2
  54. package/dist/src/assets/img/icons/mediatype/web.d.ts +1 -1
  55. package/dist/src/assets/img/icons/mediatype/web.js +2 -2
  56. package/dist/src/assets/img/icons/null-result.d.ts +2 -2
  57. package/dist/src/assets/img/icons/null-result.js +2 -2
  58. package/dist/src/assets/img/icons/restricted.d.ts +1 -1
  59. package/dist/src/assets/img/icons/restricted.js +2 -2
  60. package/dist/src/assets/img/icons/reviews.d.ts +1 -1
  61. package/dist/src/assets/img/icons/reviews.js +2 -2
  62. package/dist/src/assets/img/icons/upload.d.ts +1 -1
  63. package/dist/src/assets/img/icons/upload.js +2 -2
  64. package/dist/src/assets/img/icons/views.d.ts +1 -1
  65. package/dist/src/assets/img/icons/views.js +2 -2
  66. package/dist/src/circular-activity-indicator.d.ts +5 -5
  67. package/dist/src/circular-activity-indicator.js +17 -17
  68. package/dist/src/collection-browser.d.ts +235 -233
  69. package/dist/src/collection-browser.js +1032 -1046
  70. package/dist/src/collection-browser.js.map +1 -1
  71. package/dist/src/collection-facets/facets-template.d.ts +16 -16
  72. package/dist/src/collection-facets/facets-template.js +125 -125
  73. package/dist/src/collection-facets/facets-util.d.ts +10 -10
  74. package/dist/src/collection-facets/facets-util.js +19 -19
  75. package/dist/src/collection-facets/more-facets-content.d.ts +84 -83
  76. package/dist/src/collection-facets/more-facets-content.js +353 -351
  77. package/dist/src/collection-facets/more-facets-content.js.map +1 -1
  78. package/dist/src/collection-facets/more-facets-pagination.d.ts +36 -36
  79. package/dist/src/collection-facets/more-facets-pagination.js +192 -192
  80. package/dist/src/collection-facets.d.ts +71 -79
  81. package/dist/src/collection-facets.js +325 -338
  82. package/dist/src/collection-facets.js.map +1 -1
  83. package/dist/src/empty-placeholder.d.ts +11 -11
  84. package/dist/src/empty-placeholder.js +42 -42
  85. package/dist/src/language-code-handler/language-code-handler.d.ts +37 -37
  86. package/dist/src/language-code-handler/language-code-handler.js +26 -26
  87. package/dist/src/language-code-handler/language-code-mapping.d.ts +1 -1
  88. package/dist/src/language-code-handler/language-code-mapping.js +562 -562
  89. package/dist/src/mediatype/mediatype-config.d.ts +3 -3
  90. package/dist/src/mediatype/mediatype-config.js +85 -85
  91. package/dist/src/models.d.ts +90 -89
  92. package/dist/src/models.js +85 -85
  93. package/dist/src/models.js.map +1 -1
  94. package/dist/src/restoration-state-handler.d.ts +38 -38
  95. package/dist/src/restoration-state-handler.js +202 -202
  96. package/dist/src/sort-filter-bar/alpha-bar.d.ts +9 -9
  97. package/dist/src/sort-filter-bar/alpha-bar.js +41 -41
  98. package/dist/src/sort-filter-bar/img/compact.d.ts +1 -1
  99. package/dist/src/sort-filter-bar/img/compact.js +2 -2
  100. package/dist/src/sort-filter-bar/img/list.d.ts +1 -1
  101. package/dist/src/sort-filter-bar/img/list.js +2 -2
  102. package/dist/src/sort-filter-bar/img/sort-triangle.d.ts +1 -1
  103. package/dist/src/sort-filter-bar/img/sort-triangle.js +2 -2
  104. package/dist/src/sort-filter-bar/img/tile.d.ts +1 -1
  105. package/dist/src/sort-filter-bar/img/tile.js +2 -2
  106. package/dist/src/sort-filter-bar/sort-filter-bar.d.ts +107 -107
  107. package/dist/src/sort-filter-bar/sort-filter-bar.js +423 -423
  108. package/dist/src/styles/item-image-styles.d.ts +8 -8
  109. package/dist/src/styles/item-image-styles.js +9 -9
  110. package/dist/src/tiles/collection-browser-loading-tile.d.ts +5 -5
  111. package/dist/src/tiles/collection-browser-loading-tile.js +15 -15
  112. package/dist/src/tiles/grid/account-tile.d.ts +8 -8
  113. package/dist/src/tiles/grid/account-tile.js +20 -20
  114. package/dist/src/tiles/grid/collection-tile.d.ts +7 -7
  115. package/dist/src/tiles/grid/collection-tile.js +23 -23
  116. package/dist/src/tiles/grid/item-tile.d.ts +24 -24
  117. package/dist/src/tiles/grid/item-tile.js +87 -87
  118. package/dist/src/tiles/grid/tile-stats.d.ts +10 -10
  119. package/dist/src/tiles/grid/tile-stats.js +35 -35
  120. package/dist/src/tiles/image-block.d.ts +17 -17
  121. package/dist/src/tiles/image-block.js +73 -73
  122. package/dist/src/tiles/item-image.d.ts +31 -31
  123. package/dist/src/tiles/item-image.js +103 -103
  124. package/dist/src/tiles/list/account-label.d.ts +1 -1
  125. package/dist/src/tiles/list/account-label.js +6 -6
  126. package/dist/src/tiles/list/date-label.d.ts +1 -1
  127. package/dist/src/tiles/list/date-label.js +12 -12
  128. package/dist/src/tiles/list/tile-list-compact-header.d.ts +12 -12
  129. package/dist/src/tiles/list/tile-list-compact-header.js +41 -41
  130. package/dist/src/tiles/list/tile-list-compact.d.ts +20 -20
  131. package/dist/src/tiles/list/tile-list-compact.js +87 -87
  132. package/dist/src/tiles/list/tile-list.d.ts +50 -50
  133. package/dist/src/tiles/list/tile-list.js +263 -263
  134. package/dist/src/tiles/mediatype-icon.d.ts +9 -9
  135. package/dist/src/tiles/mediatype-icon.js +47 -47
  136. package/dist/src/tiles/overlay/icon-overlay.d.ts +7 -7
  137. package/dist/src/tiles/overlay/icon-overlay.js +31 -31
  138. package/dist/src/tiles/overlay/text-overlay.d.ts +8 -8
  139. package/dist/src/tiles/overlay/text-overlay.js +31 -31
  140. package/dist/src/tiles/text-snippet-block.d.ts +29 -29
  141. package/dist/src/tiles/text-snippet-block.js +81 -81
  142. package/dist/src/tiles/text-snippet-block.js.map +1 -1
  143. package/dist/src/tiles/tile-dispatcher.d.ts +36 -36
  144. package/dist/src/tiles/tile-dispatcher.js +128 -128
  145. package/dist/src/utils/analytics-events.d.ts +18 -18
  146. package/dist/src/utils/analytics-events.js +20 -20
  147. package/dist/src/utils/format-count.d.ts +7 -7
  148. package/dist/src/utils/format-count.js +75 -75
  149. package/dist/src/utils/format-date.d.ts +2 -2
  150. package/dist/src/utils/format-date.js +23 -23
  151. package/dist/test/collection-browser.test.d.ts +1 -1
  152. package/dist/test/collection-browser.test.js +328 -200
  153. package/dist/test/collection-browser.test.js.map +1 -1
  154. package/dist/test/collection-facets/facets-template.test.d.ts +1 -1
  155. package/dist/test/collection-facets/facets-template.test.js +62 -62
  156. package/dist/test/collection-facets/facets-util.test.d.ts +1 -1
  157. package/dist/test/collection-facets/facets-util.test.js +12 -12
  158. package/dist/test/collection-facets/more-facets-content.test.d.ts +1 -1
  159. package/dist/test/collection-facets/more-facets-content.test.js +92 -91
  160. package/dist/test/collection-facets/more-facets-content.test.js.map +1 -1
  161. package/dist/test/collection-facets/more-facets-pagination.test.d.ts +1 -1
  162. package/dist/test/collection-facets/more-facets-pagination.test.js +117 -117
  163. package/dist/test/collection-facets.test.d.ts +2 -2
  164. package/dist/test/collection-facets.test.js +182 -181
  165. package/dist/test/collection-facets.test.js.map +1 -1
  166. package/dist/test/empty-placeholder.test.d.ts +1 -1
  167. package/dist/test/empty-placeholder.test.js +33 -33
  168. package/dist/test/icon-overlay.test.d.ts +1 -1
  169. package/dist/test/icon-overlay.test.js +24 -24
  170. package/dist/test/item-image.test.d.ts +1 -1
  171. package/dist/test/item-image.test.js +56 -56
  172. package/dist/test/mediatype-config.test.d.ts +1 -1
  173. package/dist/test/mediatype-config.test.js +16 -16
  174. package/dist/test/mocks/mock-analytics-handler.d.ts +10 -10
  175. package/dist/test/mocks/mock-analytics-handler.js +15 -15
  176. package/dist/test/mocks/mock-collection-name-cache.d.ts +7 -7
  177. package/dist/test/mocks/mock-collection-name-cache.js +13 -13
  178. package/dist/test/mocks/mock-search-responses.d.ts +5 -4
  179. package/dist/test/mocks/mock-search-responses.js +103 -57
  180. package/dist/test/mocks/mock-search-responses.js.map +1 -1
  181. package/dist/test/mocks/mock-search-service.d.ts +13 -8
  182. package/dist/test/mocks/mock-search-service.js +25 -19
  183. package/dist/test/mocks/mock-search-service.js.map +1 -1
  184. package/dist/test/sort-filter-bar/sort-filter-bar.test.d.ts +1 -1
  185. package/dist/test/sort-filter-bar/sort-filter-bar.test.js +113 -113
  186. package/dist/test/text-overlay.test.d.ts +1 -1
  187. package/dist/test/text-overlay.test.js +41 -41
  188. package/dist/test/text-snippet-block.test.d.ts +1 -1
  189. package/dist/test/text-snippet-block.test.js +57 -45
  190. package/dist/test/text-snippet-block.test.js.map +1 -1
  191. package/dist/test/tile-stats.test.d.ts +1 -1
  192. package/dist/test/tile-stats.test.js +33 -33
  193. package/dist/test/tiles/grid/item-tile.test.d.ts +1 -1
  194. package/dist/test/tiles/grid/item-tile.test.js +107 -107
  195. package/dist/test/tiles/list/tile-list.test.d.ts +1 -1
  196. package/dist/test/tiles/list/tile-list.test.js +36 -36
  197. package/dist/test/utils/format-count.test.d.ts +1 -1
  198. package/dist/test/utils/format-count.test.js +23 -23
  199. package/dist/test/utils/format-date.test.d.ts +1 -1
  200. package/dist/test/utils/format-date.test.js +17 -17
  201. package/index.html +24 -24
  202. package/local.archive.org.cert +86 -86
  203. package/local.archive.org.key +27 -27
  204. package/package.json +115 -115
  205. package/renovate.json +6 -6
  206. package/src/app-root.ts +49 -11
  207. package/src/collection-browser.ts +76 -86
  208. package/src/collection-facets/more-facets-content.ts +35 -27
  209. package/src/collection-facets.ts +9 -26
  210. package/src/models.ts +2 -0
  211. package/src/tiles/text-snippet-block.ts +1 -1
  212. package/test/collection-browser.test.ts +192 -0
  213. package/test/collection-facets/more-facets-content.test.ts +5 -5
  214. package/test/collection-facets.test.ts +16 -15
  215. package/test/mocks/mock-search-responses.ts +83 -34
  216. package/test/mocks/mock-search-service.ts +27 -17
  217. package/test/text-snippet-block.test.ts +17 -0
  218. package/tsconfig.json +21 -21
  219. package/web-dev-server.config.mjs +30 -30
  220. package/web-test-runner.config.mjs +41 -41
@@ -3,6 +3,7 @@ import { expect, fixture } from '@open-wc/testing';
3
3
  import { html } from 'lit';
4
4
  import sinon from 'sinon';
5
5
  import type { InfiniteScroller } from '@internetarchive/infinite-scroller';
6
+ import { SearchType } from '@internetarchive/search-service';
6
7
  import type { CollectionBrowser } from '../src/collection-browser';
7
8
  import '../src/collection-browser';
8
9
  import {
@@ -182,6 +183,48 @@ describe('Collection Browser', () => {
182
183
  ).to.contains('Results');
183
184
  });
184
185
 
186
+ it('queries the search service with a metadata search', async () => {
187
+ const searchService = new MockSearchService();
188
+
189
+ const el = await fixture<CollectionBrowser>(
190
+ html` <collection-browser
191
+ .searchService=${searchService}
192
+ searchTarget="metadata"
193
+ >
194
+ </collection-browser>`
195
+ );
196
+
197
+ el.baseQuery = 'collection:foo';
198
+ await el.updateComplete;
199
+
200
+ expect(searchService.searchParams?.query).to.equal('collection:foo');
201
+ expect(searchService.searchType).to.equal(SearchType.METADATA);
202
+ expect(
203
+ el.shadowRoot?.querySelector('#big-results-label')?.textContent
204
+ ).to.contains('Results');
205
+ });
206
+
207
+ it('queries the search service with a fulltext search', async () => {
208
+ const searchService = new MockSearchService();
209
+
210
+ const el = await fixture<CollectionBrowser>(
211
+ html` <collection-browser
212
+ .searchService=${searchService}
213
+ searchTarget="fulltext"
214
+ >
215
+ </collection-browser>`
216
+ );
217
+
218
+ el.baseQuery = 'collection:foo';
219
+ await el.updateComplete;
220
+
221
+ expect(searchService.searchParams?.query).to.equal('collection:foo');
222
+ expect(searchService.searchType).to.equal(SearchType.FULLTEXT);
223
+ expect(
224
+ el.shadowRoot?.querySelector('#big-results-label')?.textContent
225
+ ).to.contains('Results');
226
+ });
227
+
185
228
  it('queries for collection names after a fetch', async () => {
186
229
  const searchService = new MockSearchService();
187
230
  const collectionNameCache = new MockCollectionNameCache();
@@ -205,6 +248,155 @@ describe('Collection Browser', () => {
205
248
  ]);
206
249
  });
207
250
 
251
+ it('keeps search results from fetch if no change to query or sort param', async () => {
252
+ const resultsSpy = sinon.spy();
253
+ const searchService = new MockSearchService({
254
+ asyncResponse: true,
255
+ resultsSpy,
256
+ });
257
+
258
+ const el = await fixture<CollectionBrowser>(
259
+ html`<collection-browser .searchService=${searchService}>
260
+ </collection-browser>`
261
+ );
262
+
263
+ el.baseQuery = 'with-sort';
264
+ el.sortParam = { field: 'foo', direction: 'asc' };
265
+ await el.updateComplete;
266
+
267
+ await el.fetchPage(2);
268
+
269
+ // If there is no change to the query or sort param during the fetch, the results
270
+ // should be read.
271
+ expect(resultsSpy.callCount).to.be.greaterThanOrEqual(1);
272
+ });
273
+
274
+ it('discards obsolete search results if sort params changed before arrival', async () => {
275
+ const resultsSpy = sinon.spy();
276
+ const searchService = new MockSearchService({
277
+ asyncResponse: true,
278
+ resultsSpy,
279
+ });
280
+
281
+ const el = await fixture<CollectionBrowser>(
282
+ html`<collection-browser .searchService=${searchService}>
283
+ </collection-browser>`
284
+ );
285
+
286
+ el.baseQuery = 'with-sort';
287
+ el.sortParam = { field: 'foo', direction: 'asc' };
288
+ await el.updateComplete;
289
+
290
+ const fetchPromise = el.fetchPage(2);
291
+ el.sortParam = { field: 'foo', direction: 'desc' };
292
+ await fetchPromise;
293
+
294
+ // If the different sort param causes the results to be discarded,
295
+ // the results array should never be read.
296
+ expect(resultsSpy.callCount).to.equal(0);
297
+ });
298
+
299
+ it('discards obsolete search results if sort param added before arrival', async () => {
300
+ const resultsSpy = sinon.spy();
301
+ const searchService = new MockSearchService({
302
+ asyncResponse: true,
303
+ resultsSpy,
304
+ });
305
+
306
+ const el = await fixture<CollectionBrowser>(
307
+ html`<collection-browser .searchService=${searchService}>
308
+ </collection-browser>`
309
+ );
310
+
311
+ el.baseQuery = 'single-result';
312
+ await el.updateComplete;
313
+
314
+ const fetchPromise = el.fetchPage(2);
315
+ el.sortParam = { field: 'foo', direction: 'asc' };
316
+ await fetchPromise;
317
+
318
+ // If the different sort param causes the results to be discarded,
319
+ // the results array should never be read.
320
+ expect(resultsSpy.callCount).to.equal(0);
321
+ });
322
+
323
+ it('discards obsolete search results if sort param cleared before arrival', async () => {
324
+ const resultsSpy = sinon.spy();
325
+ const searchService = new MockSearchService({
326
+ asyncResponse: true,
327
+ resultsSpy,
328
+ });
329
+
330
+ const el = await fixture<CollectionBrowser>(
331
+ html`<collection-browser .searchService=${searchService}>
332
+ </collection-browser>`
333
+ );
334
+
335
+ el.baseQuery = 'with-sort';
336
+ await el.updateComplete;
337
+
338
+ const fetchPromise = el.fetchPage(2);
339
+ el.sortParam = null;
340
+ await fetchPromise;
341
+
342
+ // If the different sort param causes the results to be discarded,
343
+ // the results array should never be read.
344
+ expect(resultsSpy.callCount).to.equal(0);
345
+ });
346
+
347
+ it('sets sort properties when user changes sort', async () => {
348
+ const el = await fixture<CollectionBrowser>(
349
+ html`<collection-browser></collection-browser>`
350
+ );
351
+
352
+ expect(el.selectedSort).to.equal(SortField.relevance);
353
+
354
+ el.baseQuery = 'foo';
355
+ await el.updateComplete;
356
+
357
+ const sortBar = el.shadowRoot?.querySelector('sort-filter-bar');
358
+ const sortSelector = sortBar?.shadowRoot?.querySelector(
359
+ '#desktop-sort-selector'
360
+ );
361
+ expect(sortSelector).to.exist;
362
+
363
+ // Click the title sorter
364
+ [...(sortSelector?.children as HTMLCollection & Iterable<any>)] // tsc doesn't know children is iterable
365
+ .find(child => child.textContent?.trim() === 'Title')
366
+ ?.querySelector('a[href]')
367
+ ?.click();
368
+
369
+ await el.updateComplete;
370
+
371
+ expect(el.selectedSort).to.equal(SortField.title);
372
+ });
373
+
374
+ it('scrolls to page', async () => {
375
+ const el = await fixture<CollectionBrowser>(
376
+ html`<collection-browser></collection-browser>`
377
+ );
378
+
379
+ const infiniteScroller = el.shadowRoot?.querySelector(
380
+ 'infinite-scroller'
381
+ ) as InfiniteScroller;
382
+ expect(infiniteScroller).to.exist;
383
+
384
+ const oldScrollToCell = infiniteScroller.scrollToCell;
385
+ const spy = sinon.spy();
386
+ infiniteScroller.scrollToCell = spy;
387
+
388
+ el.goToPage(1);
389
+
390
+ // Give it a second to scroll
391
+ await new Promise(res => {
392
+ setTimeout(res, 1000);
393
+ });
394
+
395
+ expect(spy.callCount).to.equal(1);
396
+
397
+ infiniteScroller.scrollToCell = oldScrollToCell;
398
+ });
399
+
208
400
  it('refreshes when certain properties change - with some analytics event sampling', async () => {
209
401
  const mockAnalyticsHandler = new MockAnalyticsHandler();
210
402
  const searchService = new MockSearchService();
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable import/no-duplicates */
2
2
  import { expect, fixture, oneEvent } from '@open-wc/testing';
3
3
  import { html } from 'lit';
4
- import type { Aggregation } from '@internetarchive/search-service';
4
+ import { Aggregation } from '@internetarchive/search-service';
5
5
  import type { MoreFacetsContent } from '../../src/collection-facets/more-facets-content';
6
6
  import '../../src/collection-facets/more-facets-content';
7
7
  import { MockSearchService } from '../mocks/mock-search-service';
@@ -18,15 +18,15 @@ const selectedFacetsGroup = {
18
18
  ],
19
19
  };
20
20
 
21
- const aggregation: Record<string, Aggregation> = {
22
- 'user_aggs__terms__field:collectionSorter__size:1': {
21
+ const aggregations: Record<string, Aggregation> = {
22
+ collection: new Aggregation({
23
23
  buckets: [
24
24
  {
25
25
  key: 'foo',
26
26
  doc_count: 5,
27
27
  },
28
28
  ],
29
- },
29
+ }),
30
30
  };
31
31
 
32
32
  describe('More facets content', () => {
@@ -109,7 +109,7 @@ describe('More facets content', () => {
109
109
  html`<more-facets-content
110
110
  .searchService=${searchService}
111
111
  .selectedFacets=${selectedFacetsGroup}
112
- .aggregations=${aggregation}
112
+ .aggregations=${aggregations}
113
113
  ></more-facets-content>`
114
114
  );
115
115
 
@@ -2,7 +2,7 @@
2
2
  import { expect, fixture } from '@open-wc/testing';
3
3
  import sinon from 'sinon';
4
4
  import { html } from 'lit';
5
- import type { Aggregation } from '@internetarchive/search-service';
5
+ import { Aggregation } from '@internetarchive/search-service';
6
6
  import {
7
7
  ModalManager,
8
8
  ModalManagerInterface,
@@ -35,14 +35,14 @@ describe('Collection Facets', () => {
35
35
  );
36
36
 
37
37
  const aggs: Record<string, Aggregation> = {
38
- 'user_aggs__terms__field:subjectSorter__size:1': {
38
+ subject: new Aggregation({
39
39
  buckets: [
40
40
  {
41
41
  key: 'foo',
42
42
  doc_count: 5,
43
43
  },
44
44
  ],
45
- },
45
+ }),
46
46
  };
47
47
 
48
48
  el.aggregations = aggs;
@@ -68,22 +68,22 @@ describe('Collection Facets', () => {
68
68
  );
69
69
 
70
70
  const aggs: Record<string, Aggregation> = {
71
- 'user_aggs__terms__field:subjectSorter__size:1': {
71
+ subject: new Aggregation({
72
72
  buckets: [
73
73
  {
74
74
  key: 'foo',
75
75
  doc_count: 5,
76
76
  },
77
77
  ],
78
- },
79
- 'user_aggs__terms__field:mediatypeSorter__size:1': {
78
+ }),
79
+ mediatype: new Aggregation({
80
80
  buckets: [
81
81
  {
82
82
  key: 'bar',
83
83
  doc_count: 10,
84
84
  },
85
85
  ],
86
- },
86
+ }),
87
87
  };
88
88
 
89
89
  el.aggregations = aggs;
@@ -99,14 +99,14 @@ describe('Collection Facets', () => {
99
99
  );
100
100
 
101
101
  const aggs: Record<string, Aggregation> = {
102
- 'user_aggs__terms__field:collection__size:1': {
102
+ collection: new Aggregation({
103
103
  buckets: [
104
104
  {
105
105
  key: 'foo',
106
106
  doc_count: 5,
107
107
  },
108
108
  ],
109
- },
109
+ }),
110
110
  };
111
111
 
112
112
  el.aggregations = aggs;
@@ -127,14 +127,14 @@ describe('Collection Facets', () => {
127
127
  );
128
128
 
129
129
  const aggs: Record<string, Aggregation> = {
130
- 'user_aggs__terms__field:subjectSorter__size:1': {
130
+ subject: new Aggregation({
131
131
  buckets: [
132
132
  {
133
133
  key: 'foo',
134
134
  doc_count: 5,
135
135
  },
136
136
  ],
137
- },
137
+ }),
138
138
  };
139
139
 
140
140
  el.aggregations = aggs;
@@ -155,14 +155,14 @@ describe('Collection Facets', () => {
155
155
  );
156
156
 
157
157
  const aggs: Record<string, Aggregation> = {
158
- 'user_aggs__terms__field:subjectSorter__size:1': {
158
+ subject: new Aggregation({
159
159
  buckets: [
160
160
  {
161
161
  key: 'foo',
162
162
  doc_count: 5,
163
163
  },
164
164
  ],
165
- },
165
+ }),
166
166
  };
167
167
 
168
168
  el.aggregations = aggs;
@@ -171,6 +171,7 @@ describe('Collection Facets', () => {
171
171
  const moreLink = el.shadowRoot?.querySelector('.more-link');
172
172
  expect(moreLink).to.be.null;
173
173
  });
174
+
174
175
  it('Render More Facets', async () => {
175
176
  const el = await fixture<CollectionFacets>(
176
177
  html`<collection-facets
@@ -179,7 +180,7 @@ describe('Collection Facets', () => {
179
180
  );
180
181
 
181
182
  const aggs: Record<string, Aggregation> = {
182
- 'user_aggs__terms__field:subjectSorter__size:1': {
183
+ subject: new Aggregation({
183
184
  buckets: [
184
185
  {
185
186
  key: 'foo',
@@ -210,7 +211,7 @@ describe('Collection Facets', () => {
210
211
  doc_count: 5,
211
212
  },
212
213
  ],
213
- },
214
+ }),
214
215
  };
215
216
 
216
217
  el.aggregations = aggs;
@@ -1,6 +1,6 @@
1
1
  import type { Result } from '@internetarchive/result-type';
2
2
  import {
3
- Metadata,
3
+ ItemHit,
4
4
  SearchResponse,
5
5
  SearchServiceError,
6
6
  } from '@internetarchive/search-service';
@@ -10,61 +10,110 @@ export const mockSuccessSingleResult: Result<
10
10
  SearchServiceError
11
11
  > = {
12
12
  success: {
13
+ request: {
14
+ clientParameters: {
15
+ user_query: 'collection:foo',
16
+ sort: [],
17
+ },
18
+ finalizedParameters: {
19
+ user_query: 'collection:foo',
20
+ sort: [],
21
+ },
22
+ },
13
23
  rawResponse: {},
14
24
  response: {
15
- numFound: 1,
16
- docs: [
17
- new Metadata({
18
- identifier: 'foo',
19
- collections_raw: ['foo', 'bar'],
25
+ totalResults: 1,
26
+ returnedCount: 1,
27
+ results: [
28
+ new ItemHit({
29
+ fields: {
30
+ identifier: 'foo',
31
+ collection: ['foo', 'bar'],
32
+ },
20
33
  }),
21
34
  ],
22
- start: 0,
23
35
  },
24
36
  responseHeader: {
25
- status: 0,
26
- QTime: 0,
27
- params: {
28
- query: 'collection:foo',
29
- qin: 'collection:foo',
30
- fields: 'identifier, collections_raw',
31
- wt: 'foo',
32
- start: 0,
33
- },
37
+ succeeded: true,
38
+ query_time: 0,
34
39
  },
35
40
  },
36
41
  };
37
42
 
43
+ export const getMockSuccessSingleResultWithSort: (
44
+ resultsSpy: Function
45
+ ) => Result<SearchResponse, SearchServiceError> = (resultsSpy: Function) => ({
46
+ success: {
47
+ request: {
48
+ clientParameters: {
49
+ user_query: 'with-sort',
50
+ sort: ['foo:asc'],
51
+ },
52
+ finalizedParameters: {
53
+ user_query: 'with-sort',
54
+ sort: ['foo:asc'],
55
+ },
56
+ },
57
+ rawResponse: {},
58
+ response: {
59
+ totalResults: 1,
60
+ returnedCount: 1,
61
+ get results() {
62
+ resultsSpy();
63
+ return [
64
+ new ItemHit({
65
+ fields: {
66
+ identifier: 'foo',
67
+ collection: ['foo', 'bar'],
68
+ },
69
+ }),
70
+ ];
71
+ },
72
+ },
73
+ responseHeader: {
74
+ succeeded: true,
75
+ query_time: 0,
76
+ },
77
+ },
78
+ });
79
+
38
80
  export const mockSuccessMultipleResults: Result<
39
81
  SearchResponse,
40
82
  SearchServiceError
41
83
  > = {
42
84
  success: {
85
+ request: {
86
+ clientParameters: {
87
+ user_query: 'collection:foo',
88
+ sort: [],
89
+ },
90
+ finalizedParameters: {
91
+ user_query: 'collection:foo',
92
+ sort: [],
93
+ },
94
+ },
43
95
  rawResponse: {},
44
96
  response: {
45
- numFound: 2,
46
- docs: [
47
- new Metadata({
48
- identifier: 'foo',
49
- collections_raw: ['foo', 'bar'],
97
+ totalResults: 2,
98
+ returnedCount: 2,
99
+ results: [
100
+ new ItemHit({
101
+ fields: {
102
+ identifier: 'foo',
103
+ collection: ['foo', 'bar'],
104
+ },
50
105
  }),
51
- new Metadata({
52
- identifier: 'bar',
53
- collections_raw: ['baz', 'boop'],
106
+ new ItemHit({
107
+ fields: {
108
+ identifier: 'bar',
109
+ collection: ['baz', 'boop'],
110
+ },
54
111
  }),
55
112
  ],
56
- start: 0,
57
113
  },
58
114
  responseHeader: {
59
- status: 0,
60
- QTime: 0,
61
- params: {
62
- query: 'collection:foo',
63
- qin: 'collection:foo',
64
- fields: 'identifier, collections_raw',
65
- wt: 'foo',
66
- start: 0,
67
- },
115
+ succeeded: true,
116
+ query_time: 0,
68
117
  },
69
118
  },
70
119
  };
@@ -1,43 +1,53 @@
1
1
  import type { Result } from '@internetarchive/result-type';
2
2
  import type {
3
- MetadataResponse,
4
3
  SearchParams,
5
4
  SearchResponse,
6
5
  SearchServiceInterface,
7
6
  SearchServiceError,
7
+ SearchType,
8
8
  } from '@internetarchive/search-service';
9
9
  import {
10
10
  mockSuccessSingleResult,
11
11
  mockSuccessMultipleResults,
12
+ getMockSuccessSingleResultWithSort,
12
13
  } from './mock-search-responses';
13
14
 
14
15
  export class MockSearchService implements SearchServiceInterface {
15
16
  searchParams?: SearchParams;
16
17
 
18
+ searchType?: SearchType;
19
+
20
+ asyncResponse: boolean;
21
+
22
+ resultsSpy: Function;
23
+
24
+ constructor({ asyncResponse = false, resultsSpy = () => {} } = {}) {
25
+ this.asyncResponse = asyncResponse;
26
+ this.resultsSpy = resultsSpy;
27
+ }
28
+
17
29
  async search(
18
- params: SearchParams
30
+ params: SearchParams,
31
+ searchType: SearchType
19
32
  ): Promise<Result<SearchResponse, SearchServiceError>> {
20
33
  this.searchParams = params;
34
+ this.searchType = searchType;
35
+
36
+ if (this.asyncResponse) {
37
+ // Add an artificial 1-tick delay
38
+ await new Promise(res => {
39
+ setTimeout(res, 0);
40
+ });
41
+ }
21
42
 
22
43
  if (this.searchParams?.query === 'single-result') {
23
44
  return mockSuccessSingleResult;
24
45
  }
25
46
 
26
- return mockSuccessMultipleResults;
27
- }
28
-
29
- async fetchMetadata(
30
- identifier: string
31
- ): Promise<Result<MetadataResponse, SearchServiceError>> {
32
- console.debug('fetchMetadata', identifier);
33
- throw new Error('Method not implemented.');
34
- }
47
+ if (this.searchParams?.query === 'with-sort') {
48
+ return getMockSuccessSingleResultWithSort(this.resultsSpy);
49
+ }
35
50
 
36
- async fetchMetadataValue<T>(
37
- identifier: string,
38
- keypath: string
39
- ): Promise<Result<T, SearchServiceError>> {
40
- console.debug('fetchMetadataValue', identifier, keypath);
41
- throw new Error('Method not implemented.');
51
+ return mockSuccessMultipleResults;
42
52
  }
43
53
  }
@@ -37,6 +37,23 @@ describe('TextSnippetBlock component', () => {
37
37
  expect(container?.querySelectorAll('mark').length).to.equal(3);
38
38
  });
39
39
 
40
+ it('should render marked snippets containing newlines', async () => {
41
+ const snippets = [
42
+ 'some {{{snippet}}} text',
43
+ 'some {{{other}}} {{{snippet\n text}}}',
44
+ ];
45
+
46
+ const el = await fixture<TextSnippetBlock>(
47
+ html`<text-snippet-block .snippets=${snippets}></text-snippet-block>`
48
+ );
49
+
50
+ const container = el.shadowRoot?.querySelector('.container');
51
+
52
+ // Has the correct number of snippets and highlights
53
+ expect(container?.children.length).to.equal(snippets.length);
54
+ expect(container?.querySelectorAll('mark').length).to.equal(3);
55
+ });
56
+
40
57
  it('should render correctly in grid mode', async () => {
41
58
  const el = await fixture<TextSnippetBlock>(
42
59
  html`<text-snippet-block
package/tsconfig.json CHANGED
@@ -1,21 +1,21 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es2018",
4
- "module": "esnext",
5
- "moduleResolution": "node",
6
- "noEmitOnError": true,
7
- "lib": ["es2017", "dom"],
8
- "strict": true,
9
- "esModuleInterop": false,
10
- "allowSyntheticDefaultImports": true,
11
- "experimentalDecorators": true,
12
- "importHelpers": true,
13
- "outDir": "dist",
14
- "sourceMap": true,
15
- "inlineSources": true,
16
- "rootDir": "./",
17
- "declaration": true,
18
- "importsNotUsedAsValues": "error"
19
- },
20
- "include": ["src", "test", "index.ts", "types"],
21
- }
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2018",
4
+ "module": "esnext",
5
+ "moduleResolution": "node",
6
+ "noEmitOnError": true,
7
+ "lib": ["es2017", "dom"],
8
+ "strict": true,
9
+ "esModuleInterop": false,
10
+ "allowSyntheticDefaultImports": true,
11
+ "experimentalDecorators": true,
12
+ "importHelpers": true,
13
+ "outDir": "dist",
14
+ "sourceMap": true,
15
+ "inlineSources": true,
16
+ "rootDir": "./",
17
+ "declaration": true,
18
+ "importsNotUsedAsValues": "error"
19
+ },
20
+ "include": ["src", "test", "index.ts", "types"],
21
+ }