@internetarchive/search-service
Advanced tools
Comparing version 1.2.5-alpha.24 to 1.2.5-alpha.25
@@ -20,2 +20,6 @@ import type { ItemHit } from './item-hit'; | ||
/** | ||
* Type that includes all the fields present on any type of hit | ||
*/ | ||
declare type AllHitFields = ItemHit & TextHit & FavoritedSearchHit & WebArchiveHit; | ||
/** | ||
* Result is an expansive type definition encompassing all the optional | ||
@@ -26,3 +30,3 @@ * and required properties that may occur on any type of search result | ||
*/ | ||
export declare type SearchResult = Partial<ItemHit & TextHit & FavoritedSearchHit & WebArchiveHit> & HitInfo; | ||
export declare type SearchResult = Partial<AllHitFields> & HitInfo; | ||
export {}; |
@@ -48,7 +48,3 @@ import { Aggregation } from '../models/aggregation'; | ||
export declare type LendingSubElement = typeof LENDING_SUB_ELEMENTS[number]; | ||
export interface LendingPageElement extends Record<LendingSubElement, Record<string, unknown>[]> { | ||
loans: Record<string, unknown>[]; | ||
waitlist: Record<string, unknown>[]; | ||
loan_history: Record<string, unknown>[]; | ||
} | ||
export declare type LendingPageElement = Record<LendingSubElement, Record<string, unknown>[]>; | ||
export declare type WebArchivesPageElement = WebArchiveEntry[]; | ||
@@ -55,0 +51,0 @@ export declare type ForumPostsPageElement = ForumPost[]; |
@@ -10,3 +10,9 @@ export const LENDING_SUB_ELEMENTS = [ | ||
function fixWebCaptureDateFormatting(date) { | ||
return `${date.slice(0, 4)}-${date.slice(4, 6)}-${date.slice(6, 8)}T${date.slice(8, 10)}:${date.slice(10, 12)}:${date.slice(12, 14)}Z`; | ||
const year = date.slice(0, 4); | ||
const month = date.slice(4, 6); | ||
const day = date.slice(6, 8); | ||
const hour = date.slice(8, 10); | ||
const minute = date.slice(10, 12); | ||
const second = date.slice(12, 14); | ||
return `${year}-${month}-${day}T${hour}:${minute}:${second}Z`; | ||
} | ||
@@ -22,2 +28,4 @@ /** | ||
continue; | ||
const encodedUrl = encodeURIComponent(entry.url); | ||
const href = `https://web.archive.org/web/${entry.captures[0]}/${encodedUrl}`; | ||
results.push({ | ||
@@ -28,3 +36,3 @@ hit_type: 'web_archive', | ||
capture_dates: entry.captures.map(date => fixWebCaptureDateFormatting(date)), | ||
__href__: `https://web.archive.org/web/${entry.captures[0]}/${encodeURIComponent(entry.url)}`, | ||
__href__: href, | ||
}, | ||
@@ -31,0 +39,0 @@ }); |
@@ -69,2 +69,12 @@ import { Aggregation } from '../models/aggregation'; | ||
/** | ||
* Special handling for when the 'lending' page element is present on the response. | ||
* @returns An array of raw hits representing current loans. | ||
*/ | ||
private handleLendingPageElement; | ||
/** | ||
* Special handling for when the 'web_archives' page element is present on the response. | ||
* @returns An array of raw hits representing the web archive results. | ||
*/ | ||
private handleWebArchivesPageElement; | ||
/** | ||
* Returns a correctly-typed search result depending on the schema's hit_type. | ||
@@ -71,0 +81,0 @@ */ |
@@ -6,4 +6,4 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { FavoritedSearchHit } from '../models/hit-types/favorited-search-hit'; | ||
import { WebArchiveHit } from '../models/hit-types/web-archive-hit'; | ||
import { convertWebArchivesToSearchHits, LENDING_SUB_ELEMENTS, } from './page-elements'; | ||
import { WebArchiveHit } from '../models/hit-types/web-archive-hit'; | ||
/** | ||
@@ -17,3 +17,3 @@ * This is the search response details inside the SearchResponse object that contains | ||
constructor(body, schema) { | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s; | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p; | ||
this.schema = schema; | ||
@@ -36,19 +36,10 @@ const schemaHitType = schema === null || schema === void 0 ? void 0 : schema.hit_type; | ||
} | ||
else if ((_j = this.pageElements) === null || _j === void 0 ? void 0 : _j['lending']) { | ||
const pageElements = this.pageElements['lending']; | ||
hits = (_k = pageElements['loans']) !== null && _k !== void 0 ? _k : []; | ||
this.totalResults = (_l = hits.length) !== null && _l !== void 0 ? _l : 0; | ||
this.returnedCount = this.totalResults; | ||
// For loans, we also need to build hit models for each sub-element | ||
for (const subElement of LENDING_SUB_ELEMENTS) { | ||
pageElements[subElement] = ((_m = pageElements[subElement].map((hit) => { var _a; return SearchResponseDetails.createResult((_a = hit.hit_type) !== null && _a !== void 0 ? _a : schemaHitType, hit); })) !== null && _m !== void 0 ? _m : []); | ||
} | ||
else if ((_j = this.pageElements) === null || _j === void 0 ? void 0 : _j.lending) { | ||
hits = this.handleLendingPageElement(schemaHitType); | ||
} | ||
else if ((_o = this.pageElements) === null || _o === void 0 ? void 0 : _o['web_archives']) { | ||
hits = convertWebArchivesToSearchHits(this.pageElements['web_archives']); | ||
this.totalResults = hits.length; | ||
this.returnedCount = this.totalResults; | ||
else if ((_k = this.pageElements) === null || _k === void 0 ? void 0 : _k.web_archives) { | ||
hits = this.handleWebArchivesPageElement(); | ||
} | ||
this.results = | ||
(_p = hits === null || hits === void 0 ? void 0 : hits.map((hit) => { var _a; return SearchResponseDetails.createResult((_a = hit.hit_type) !== null && _a !== void 0 ? _a : schemaHitType, hit); })) !== null && _p !== void 0 ? _p : []; | ||
(_l = hits === null || hits === void 0 ? void 0 : hits.map((hit) => { var _a; return SearchResponseDetails.createResult((_a = hit.hit_type) !== null && _a !== void 0 ? _a : schemaHitType, hit); })) !== null && _l !== void 0 ? _l : []; | ||
// Use aggregations directly from the body if available. | ||
@@ -69,12 +60,39 @@ // Otherwise, try extracting them from the first page_element. | ||
if (body === null || body === void 0 ? void 0 : body.collection_titles) { | ||
this.collectionTitles = (_q = body.collection_titles) !== null && _q !== void 0 ? _q : {}; | ||
this.collectionTitles = (_m = body.collection_titles) !== null && _m !== void 0 ? _m : {}; | ||
} | ||
if (body === null || body === void 0 ? void 0 : body.collection_extra_info) { | ||
this.collectionExtraInfo = (_r = body.collection_extra_info) !== null && _r !== void 0 ? _r : null; | ||
this.collectionExtraInfo = (_o = body.collection_extra_info) !== null && _o !== void 0 ? _o : null; | ||
} | ||
if (body === null || body === void 0 ? void 0 : body.account_extra_info) { | ||
this.accountExtraInfo = (_s = body.account_extra_info) !== null && _s !== void 0 ? _s : null; | ||
this.accountExtraInfo = (_p = body.account_extra_info) !== null && _p !== void 0 ? _p : null; | ||
} | ||
} | ||
/** | ||
* Special handling for when the 'lending' page element is present on the response. | ||
* @returns An array of raw hits representing current loans. | ||
*/ | ||
handleLendingPageElement(schemaHitType) { | ||
var _a, _b, _c; | ||
const pageElements = (_a = this.pageElements) === null || _a === void 0 ? void 0 : _a.lending; | ||
const hits = (_b = pageElements.loans) !== null && _b !== void 0 ? _b : []; | ||
this.totalResults = hits.length; | ||
this.returnedCount = this.totalResults; | ||
// For loans, we also need to build hit models for each sub-element | ||
for (const subElement of LENDING_SUB_ELEMENTS) { | ||
pageElements[subElement] = ((_c = pageElements[subElement].map((hit) => { var _a; return SearchResponseDetails.createResult((_a = hit.hit_type) !== null && _a !== void 0 ? _a : schemaHitType, hit); })) !== null && _c !== void 0 ? _c : []); | ||
} | ||
return hits; | ||
} | ||
/** | ||
* Special handling for when the 'web_archives' page element is present on the response. | ||
* @returns An array of raw hits representing the web archive results. | ||
*/ | ||
handleWebArchivesPageElement() { | ||
var _a; | ||
const hits = convertWebArchivesToSearchHits((_a = this.pageElements) === null || _a === void 0 ? void 0 : _a.web_archives); | ||
this.totalResults = hits.length; | ||
this.returnedCount = this.totalResults; | ||
return hits; | ||
} | ||
/** | ||
* Returns a correctly-typed search result depending on the schema's hit_type. | ||
@@ -81,0 +99,0 @@ */ |
@@ -6,2 +6,15 @@ import { expect } from '@open-wc/testing'; | ||
import { SearchResponseDetails, } from '../../src/responses/search-response-details'; | ||
import { FavoritedSearchHit } from '../../src/models/hit-types/favorited-search-hit'; | ||
const itemSchema = { | ||
hit_type: 'item', | ||
field_properties: {}, | ||
}; | ||
const textSchema = { | ||
hit_type: 'text', | ||
field_properties: {}, | ||
}; | ||
const favSearchSchema = { | ||
hit_type: 'favorited_search', | ||
field_properties: {}, | ||
}; | ||
const responseBody = { | ||
@@ -33,10 +46,147 @@ hits: { | ||
}; | ||
const favSearchResponseBody = { | ||
hits: { | ||
total: 1, | ||
returned: 1, | ||
hits: [ | ||
{ | ||
hit_type: 'favorited_search', | ||
fields: { | ||
query: 'foo', | ||
mediatype: 'search', | ||
title: 'Foo', | ||
}, | ||
}, | ||
], | ||
}, | ||
}; | ||
const accountUploadsResponseBody = { | ||
page_elements: { | ||
uploads: { | ||
hits: { | ||
total: 2, | ||
returned: 2, | ||
hits: [ | ||
{ | ||
hit_type: 'item', | ||
fields: { | ||
identifier: 'foo', | ||
mediatype: 'texts', | ||
}, | ||
}, | ||
{ | ||
hit_type: 'item', | ||
fields: { | ||
identifier: 'bar', | ||
collection: ['baz'], | ||
}, | ||
}, | ||
], | ||
}, | ||
aggregations: { | ||
subject: new Aggregation({ | ||
buckets: [{ key: 'foo', doc_count: 1 }], | ||
}), | ||
}, | ||
}, | ||
}, | ||
account_extra_info: { | ||
account_details: { | ||
screenname: 'Foobar', | ||
user_item_identifier: '@foobar', | ||
user_since: '2010-01-02T03:04:05Z', | ||
}, | ||
policy_settings: { | ||
is_archive_user: true, | ||
preferences: [], | ||
privileges: [], | ||
}, | ||
user_item_metadata: { | ||
title: 'Foobar', | ||
description: 'Foo bar baz', | ||
}, | ||
}, | ||
}; | ||
const accountLendingResponseBody = { | ||
page_elements: { | ||
lending: { | ||
loans: [ | ||
{ | ||
fields: { | ||
identifier: 'foo', | ||
mediatype: 'texts', | ||
}, | ||
}, | ||
], | ||
waitlist: [ | ||
{ | ||
hit_type: 'item', | ||
fields: { | ||
identifier: 'bar', | ||
mediatype: 'texts', | ||
}, | ||
}, | ||
], | ||
loan_history: [ | ||
{ | ||
hit_type: 'item', | ||
fields: { | ||
identifier: 'baz', | ||
mediatype: 'texts', | ||
}, | ||
}, | ||
], | ||
}, | ||
}, | ||
account_extra_info: { | ||
account_details: { | ||
screenname: 'Foobar', | ||
user_item_identifier: '@foobar', | ||
user_since: '2010-01-02T03:04:05Z', | ||
}, | ||
policy_settings: { | ||
is_archive_user: true, | ||
preferences: [], | ||
privileges: [], | ||
}, | ||
user_item_metadata: { | ||
title: 'Foobar', | ||
description: 'Foo bar baz', | ||
}, | ||
}, | ||
}; | ||
const accountWebArchivesResponseBody = { | ||
page_elements: { | ||
web_archives: [ | ||
{ | ||
url: 'https://example.com/', | ||
captures: ['20100102030405', '20110203040506'], | ||
}, | ||
{ | ||
url: 'https://web.archive.org/save/', | ||
captures: [], // This one will be skipped due to empty captures | ||
}, | ||
], | ||
}, | ||
account_extra_info: { | ||
account_details: { | ||
screenname: 'Foobar', | ||
user_item_identifier: '@foobar', | ||
user_since: '2010-01-02T03:04:05Z', | ||
}, | ||
policy_settings: { | ||
is_archive_user: true, | ||
preferences: [], | ||
privileges: [], | ||
}, | ||
user_item_metadata: { | ||
title: 'Foobar', | ||
description: 'Foo bar baz', | ||
}, | ||
}, | ||
}; | ||
describe('SearchResponseDetails', () => { | ||
it('constructs item hits', () => { | ||
var _a, _b, _c; | ||
const responseSchema = { | ||
hit_type: 'item', | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(responseBody, responseSchema); | ||
const details = new SearchResponseDetails(responseBody, itemSchema); | ||
expect(details.results[0]).to.be.instanceOf(ItemHit); | ||
@@ -51,7 +201,3 @@ expect(details.results[0].identifier).to.equal('foo'); | ||
var _a, _b, _c; | ||
const responseSchema = { | ||
hit_type: 'text', | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(responseBody, responseSchema); | ||
const details = new SearchResponseDetails(responseBody, textSchema); | ||
expect(details.results[0]).to.be.instanceOf(TextHit); | ||
@@ -64,2 +210,9 @@ expect(details.results[0].identifier).to.equal('foo'); | ||
}); | ||
it('constructs favorited search hits', () => { | ||
var _a, _b; | ||
const details = new SearchResponseDetails(favSearchResponseBody, favSearchSchema); | ||
expect(details.results[0]).to.be.instanceOf(FavoritedSearchHit); | ||
expect((_a = details.results[0].query) === null || _a === void 0 ? void 0 : _a.value).to.equal('foo'); | ||
expect((_b = details.results[0].title) === null || _b === void 0 ? void 0 : _b.value).to.equal('Foo'); | ||
}); | ||
it('prefers hit-type specified on hit itself over schema hit-type', () => { | ||
@@ -87,7 +240,3 @@ var _a, _b, _c; | ||
}; | ||
const responseSchema = { | ||
hit_type: 'item', | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(responseBodyWithTextHit, responseSchema); | ||
const details = new SearchResponseDetails(responseBodyWithTextHit, itemSchema); | ||
expect(details.results[0]).to.be.instanceOf(TextHit); // From hit, not schema | ||
@@ -101,2 +250,7 @@ expect(details.results[0].identifier).to.equal('foo'); | ||
}); | ||
it('constructs item hits when hit type unspecified', () => { | ||
const details = new SearchResponseDetails(responseBody, {}); | ||
expect(details.results[0]).to.be.instanceOf(ItemHit); | ||
expect(details.results[0].identifier).to.equal('foo'); | ||
}); | ||
it('includes aggregations', () => { | ||
@@ -120,7 +274,3 @@ const aggsResponseBody = { | ||
}; | ||
const responseSchema = { | ||
hit_type: 'item', | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(aggsResponseBody, responseSchema); | ||
const details = new SearchResponseDetails(aggsResponseBody, itemSchema); | ||
expect(details.results.length).to.equal(0); | ||
@@ -139,7 +289,3 @@ expect(details.aggregations).to.deep.equal({ | ||
it('provides access to collection titles map', () => { | ||
const responseSchema = { | ||
hit_type: 'item', | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(responseBody, responseSchema); | ||
const details = new SearchResponseDetails(responseBody, itemSchema); | ||
expect(details.results.length).to.equal(2); | ||
@@ -151,7 +297,3 @@ expect(details.collectionTitles).to.deep.equal({ baz: 'Baz Collection' }); | ||
delete responseBodyWithoutTitles.collection_titles; | ||
const responseSchema = { | ||
hit_type: 'item', | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(responseBodyWithoutTitles, responseSchema); | ||
const details = new SearchResponseDetails(responseBodyWithoutTitles, itemSchema); | ||
expect(details.results.length).to.equal(2); | ||
@@ -161,7 +303,3 @@ expect(details.collectionTitles).to.be.undefined; | ||
it('provides access to collection extra info', () => { | ||
const responseSchema = { | ||
hit_type: 'item', | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(responseBody, responseSchema); | ||
const details = new SearchResponseDetails(responseBody, itemSchema); | ||
expect(details.results.length).to.equal(2); | ||
@@ -175,11 +313,56 @@ expect(details.collectionExtraInfo).to.deep.equal({ thumbnail_url: 'foo' }); | ||
delete responseBodyWithoutExtraInfo.collection_extra_info; | ||
const responseSchema = { | ||
hit_type: 'item', | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(responseBodyWithoutExtraInfo, responseSchema); | ||
const details = new SearchResponseDetails(responseBodyWithoutExtraInfo, itemSchema); | ||
expect(details.results.length).to.equal(2); | ||
expect(details.collectionExtraInfo).to.be.undefined; | ||
}); | ||
it('provides access to account extra info', () => { | ||
var _a, _b; | ||
const details = new SearchResponseDetails(accountUploadsResponseBody, itemSchema); | ||
expect((_b = (_a = details.accountExtraInfo) === null || _a === void 0 ? void 0 : _a.user_item_metadata) === null || _b === void 0 ? void 0 : _b.description).to.equal('Foo bar baz'); | ||
}); | ||
it('account extra info is optional', () => { | ||
const accountBodyWithoutExtraInfo = { | ||
...accountUploadsResponseBody, | ||
}; | ||
delete accountBodyWithoutExtraInfo.account_extra_info; | ||
const details = new SearchResponseDetails(accountBodyWithoutExtraInfo, itemSchema); | ||
expect(details.results.length).to.equal(2); | ||
expect(details.accountExtraInfo).to.be.undefined; | ||
}); | ||
it('provides access to hits from page element', () => { | ||
const details = new SearchResponseDetails(accountUploadsResponseBody, itemSchema); | ||
expect(details.results.length).to.equal(2); | ||
expect(details.results[0].identifier).to.equal('foo'); | ||
}); | ||
it('provides access to aggregations from page element', () => { | ||
var _a, _b; | ||
const details = new SearchResponseDetails(accountUploadsResponseBody, itemSchema); | ||
expect(details.aggregations).to.exist; | ||
expect((_b = (_a = details.aggregations) === null || _a === void 0 ? void 0 : _a.subject) === null || _b === void 0 ? void 0 : _b.buckets[0]).to.deep.equal({ | ||
key: 'foo', | ||
doc_count: 1, | ||
}); | ||
}); | ||
it('provides access to lending page elements', () => { | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; | ||
const details = new SearchResponseDetails(accountLendingResponseBody, itemSchema); | ||
expect(details.results.length, 'results length').to.equal(1); | ||
expect(details.totalResults, 'total').to.equal(1); | ||
expect(details.returnedCount, 'returned').to.equal(1); | ||
expect((_d = (_c = (_b = (_a = details.pageElements) === null || _a === void 0 ? void 0 : _a.lending) === null || _b === void 0 ? void 0 : _b.loans) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.identifier).to.equal('foo'); | ||
expect((_h = (_g = (_f = (_e = details.pageElements) === null || _e === void 0 ? void 0 : _e.lending) === null || _f === void 0 ? void 0 : _f.waitlist) === null || _g === void 0 ? void 0 : _g[0]) === null || _h === void 0 ? void 0 : _h.identifier).to.equal('bar'); | ||
expect((_m = (_l = (_k = (_j = details.pageElements) === null || _j === void 0 ? void 0 : _j.lending) === null || _k === void 0 ? void 0 : _k.loan_history) === null || _l === void 0 ? void 0 : _l[0]) === null || _m === void 0 ? void 0 : _m.identifier).to.equal('baz'); | ||
}); | ||
it('provides access to web archive page elements', () => { | ||
var _a, _b, _c, _d; | ||
const details = new SearchResponseDetails(accountWebArchivesResponseBody, itemSchema); | ||
expect(details.results.length, 'results length').to.equal(1); | ||
expect(details.totalResults, 'total').to.equal(1); | ||
expect(details.returnedCount, 'returned').to.equal(1); | ||
const webArchiveResult = details.results[0]; | ||
expect((_a = webArchiveResult.title) === null || _a === void 0 ? void 0 : _a.value).to.equal('https://example.com/'); | ||
expect((_c = (_b = webArchiveResult.capture_dates) === null || _b === void 0 ? void 0 : _b.values) === null || _c === void 0 ? void 0 : _c.length).to.equal(2); | ||
expect((_d = webArchiveResult.__href__) === null || _d === void 0 ? void 0 : _d.value).to.equal('https://web.archive.org/web/20100102030405/https%3A%2F%2Fexample.com%2F'); | ||
}); | ||
}); | ||
//# sourceMappingURL=search-response-details.test.js.map |
{ | ||
"name": "@internetarchive/search-service", | ||
"version": "1.2.5-alpha.24", | ||
"version": "1.2.5-alpha.25", | ||
"description": "A search service for the Internet Archive", | ||
@@ -5,0 +5,0 @@ "license": "AGPL-3.0-only", |
@@ -23,2 +23,7 @@ import type { ItemHit } from './item-hit'; | ||
/** | ||
* Type that includes all the fields present on any type of hit | ||
*/ | ||
type AllHitFields = ItemHit & TextHit & FavoritedSearchHit & WebArchiveHit; | ||
/** | ||
* Result is an expansive type definition encompassing all the optional | ||
@@ -29,5 +34,2 @@ * and required properties that may occur on any type of search result | ||
*/ | ||
export type SearchResult = Partial< | ||
ItemHit & TextHit & FavoritedSearchHit & WebArchiveHit | ||
> & | ||
HitInfo; | ||
export type SearchResult = Partial<AllHitFields> & HitInfo; |
@@ -65,8 +65,6 @@ import { Aggregation } from '../models/aggregation'; | ||
export type LendingSubElement = typeof LENDING_SUB_ELEMENTS[number]; | ||
export interface LendingPageElement | ||
extends Record<LendingSubElement, Record<string, unknown>[]> { | ||
loans: Record<string, unknown>[]; | ||
waitlist: Record<string, unknown>[]; | ||
loan_history: Record<string, unknown>[]; | ||
} | ||
export type LendingPageElement = Record< | ||
LendingSubElement, | ||
Record<string, unknown>[] | ||
>; | ||
@@ -102,6 +100,9 @@ export type WebArchivesPageElement = WebArchiveEntry[]; | ||
function fixWebCaptureDateFormatting(date: string): string { | ||
return `${date.slice(0, 4)}-${date.slice(4, 6)}-${date.slice( | ||
6, | ||
8 | ||
)}T${date.slice(8, 10)}:${date.slice(10, 12)}:${date.slice(12, 14)}Z`; | ||
const year = date.slice(0, 4); | ||
const month = date.slice(4, 6); | ||
const day = date.slice(6, 8); | ||
const hour = date.slice(8, 10); | ||
const minute = date.slice(10, 12); | ||
const second = date.slice(12, 14); | ||
return `${year}-${month}-${day}T${hour}:${minute}:${second}Z`; | ||
} | ||
@@ -120,2 +121,4 @@ | ||
const encodedUrl = encodeURIComponent(entry.url); | ||
const href = `https://web.archive.org/web/${entry.captures[0]}/${encodedUrl}`; | ||
results.push({ | ||
@@ -128,5 +131,3 @@ hit_type: 'web_archive', | ||
), | ||
__href__: `https://web.archive.org/web/${ | ||
entry.captures[0] | ||
}/${encodeURIComponent(entry.url)}`, | ||
__href__: href, | ||
}, | ||
@@ -133,0 +134,0 @@ }); |
@@ -7,2 +7,3 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { FavoritedSearchHit } from '../models/hit-types/favorited-search-hit'; | ||
import { WebArchiveHit } from '../models/hit-types/web-archive-hit'; | ||
import { CollectionExtraInfo } from './collection-extra-info'; | ||
@@ -17,4 +18,4 @@ import type { SearchHitSchema } from './search-hit-schema'; | ||
LENDING_SUB_ELEMENTS, | ||
WebArchivesPageElement, | ||
} from './page-elements'; | ||
import { WebArchiveHit } from '../models/hit-types/web-archive-hit'; | ||
@@ -111,20 +112,6 @@ /** | ||
this.returnedCount = firstPageElement.hits.returned ?? 0; | ||
} else if (this.pageElements?.['lending']) { | ||
const pageElements = this.pageElements['lending'] as LendingPageElement; | ||
hits = pageElements['loans'] ?? []; | ||
this.totalResults = hits.length ?? 0; | ||
this.returnedCount = this.totalResults; | ||
// For loans, we also need to build hit models for each sub-element | ||
for (const subElement of LENDING_SUB_ELEMENTS) { | ||
pageElements[subElement] = (pageElements[ | ||
subElement | ||
].map((hit: SearchResult) => | ||
SearchResponseDetails.createResult(hit.hit_type ?? schemaHitType, hit) | ||
) ?? []) as Record<string, unknown>[]; | ||
} | ||
} else if (this.pageElements?.['web_archives']) { | ||
hits = convertWebArchivesToSearchHits(this.pageElements['web_archives']); | ||
this.totalResults = hits.length; | ||
this.returnedCount = this.totalResults; | ||
} else if (this.pageElements?.lending) { | ||
hits = this.handleLendingPageElement(schemaHitType); | ||
} else if (this.pageElements?.web_archives) { | ||
hits = this.handleWebArchivesPageElement(); | ||
} | ||
@@ -172,2 +159,39 @@ | ||
/** | ||
* Special handling for when the 'lending' page element is present on the response. | ||
* @returns An array of raw hits representing current loans. | ||
*/ | ||
private handleLendingPageElement( | ||
schemaHitType: HitType | ||
): Record<string, unknown>[] { | ||
const pageElements = this.pageElements?.lending as LendingPageElement; | ||
const hits = pageElements.loans ?? []; | ||
this.totalResults = hits.length; | ||
this.returnedCount = this.totalResults; | ||
// For loans, we also need to build hit models for each sub-element | ||
for (const subElement of LENDING_SUB_ELEMENTS) { | ||
pageElements[subElement] = (pageElements[ | ||
subElement | ||
].map((hit: SearchResult) => | ||
SearchResponseDetails.createResult(hit.hit_type ?? schemaHitType, hit) | ||
) ?? []) as Record<string, unknown>[]; | ||
} | ||
return hits; | ||
} | ||
/** | ||
* Special handling for when the 'web_archives' page element is present on the response. | ||
* @returns An array of raw hits representing the web archive results. | ||
*/ | ||
private handleWebArchivesPageElement(): Record<string, unknown>[] { | ||
const hits = convertWebArchivesToSearchHits( | ||
this.pageElements?.web_archives as WebArchivesPageElement | ||
); | ||
this.totalResults = hits.length; | ||
this.returnedCount = this.totalResults; | ||
return hits; | ||
} | ||
/** | ||
* Returns a correctly-typed search result depending on the schema's hit_type. | ||
@@ -174,0 +198,0 @@ */ |
@@ -10,3 +10,20 @@ import { expect } from '@open-wc/testing'; | ||
} from '../../src/responses/search-response-details'; | ||
import { SearchHitSchema } from '../../src/responses/search-hit-schema'; | ||
import { FavoritedSearchHit } from '../../src/models/hit-types/favorited-search-hit'; | ||
const itemSchema: SearchHitSchema = { | ||
hit_type: 'item' as HitType, | ||
field_properties: {}, | ||
}; | ||
const textSchema: SearchHitSchema = { | ||
hit_type: 'text' as HitType, | ||
field_properties: {}, | ||
}; | ||
const favSearchSchema: SearchHitSchema = { | ||
hit_type: 'favorited_search' as HitType, | ||
field_properties: {}, | ||
}; | ||
const responseBody: SearchResponseBody = { | ||
@@ -39,10 +56,150 @@ hits: { | ||
const favSearchResponseBody: SearchResponseBody = { | ||
hits: { | ||
total: 1, | ||
returned: 1, | ||
hits: [ | ||
{ | ||
hit_type: 'favorited_search', | ||
fields: { | ||
query: 'foo', | ||
mediatype: 'search', | ||
title: 'Foo', | ||
}, | ||
}, | ||
], | ||
}, | ||
}; | ||
const accountUploadsResponseBody: SearchResponseBody = { | ||
page_elements: { | ||
uploads: { | ||
hits: { | ||
total: 2, | ||
returned: 2, | ||
hits: [ | ||
{ | ||
hit_type: 'item', | ||
fields: { | ||
identifier: 'foo', | ||
mediatype: 'texts', | ||
}, | ||
}, | ||
{ | ||
hit_type: 'item', | ||
fields: { | ||
identifier: 'bar', | ||
collection: ['baz'], | ||
}, | ||
}, | ||
], | ||
}, | ||
aggregations: { | ||
subject: new Aggregation({ | ||
buckets: [{ key: 'foo', doc_count: 1 }], | ||
}), | ||
}, | ||
}, | ||
}, | ||
account_extra_info: { | ||
account_details: { | ||
screenname: 'Foobar', | ||
user_item_identifier: '@foobar', | ||
user_since: '2010-01-02T03:04:05Z', | ||
}, | ||
policy_settings: { | ||
is_archive_user: true, | ||
preferences: [], | ||
privileges: [], | ||
}, | ||
user_item_metadata: { | ||
title: 'Foobar', | ||
description: 'Foo bar baz', | ||
}, | ||
}, | ||
}; | ||
const accountLendingResponseBody: SearchResponseBody = { | ||
page_elements: { | ||
lending: { | ||
loans: [ | ||
{ | ||
fields: { | ||
identifier: 'foo', | ||
mediatype: 'texts', | ||
}, | ||
}, | ||
], | ||
waitlist: [ | ||
{ | ||
hit_type: 'item', | ||
fields: { | ||
identifier: 'bar', | ||
mediatype: 'texts', | ||
}, | ||
}, | ||
], | ||
loan_history: [ | ||
{ | ||
hit_type: 'item', | ||
fields: { | ||
identifier: 'baz', | ||
mediatype: 'texts', | ||
}, | ||
}, | ||
], | ||
}, | ||
}, | ||
account_extra_info: { | ||
account_details: { | ||
screenname: 'Foobar', | ||
user_item_identifier: '@foobar', | ||
user_since: '2010-01-02T03:04:05Z', | ||
}, | ||
policy_settings: { | ||
is_archive_user: true, | ||
preferences: [], | ||
privileges: [], | ||
}, | ||
user_item_metadata: { | ||
title: 'Foobar', | ||
description: 'Foo bar baz', | ||
}, | ||
}, | ||
}; | ||
const accountWebArchivesResponseBody: SearchResponseBody = { | ||
page_elements: { | ||
web_archives: [ | ||
{ | ||
url: 'https://example.com/', | ||
captures: ['20100102030405', '20110203040506'], | ||
}, | ||
{ | ||
url: 'https://web.archive.org/save/', | ||
captures: [], // This one will be skipped due to empty captures | ||
}, | ||
], | ||
}, | ||
account_extra_info: { | ||
account_details: { | ||
screenname: 'Foobar', | ||
user_item_identifier: '@foobar', | ||
user_since: '2010-01-02T03:04:05Z', | ||
}, | ||
policy_settings: { | ||
is_archive_user: true, | ||
preferences: [], | ||
privileges: [], | ||
}, | ||
user_item_metadata: { | ||
title: 'Foobar', | ||
description: 'Foo bar baz', | ||
}, | ||
}, | ||
}; | ||
describe('SearchResponseDetails', () => { | ||
it('constructs item hits', () => { | ||
const responseSchema = { | ||
hit_type: 'item' as HitType, | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(responseBody, responseSchema); | ||
const details = new SearchResponseDetails(responseBody, itemSchema); | ||
expect(details.results[0]).to.be.instanceOf(ItemHit); | ||
@@ -57,8 +214,3 @@ expect(details.results[0].identifier).to.equal('foo'); | ||
it('constructs text hits', () => { | ||
const responseSchema = { | ||
hit_type: 'text' as HitType, | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(responseBody, responseSchema); | ||
const details = new SearchResponseDetails(responseBody, textSchema); | ||
expect(details.results[0]).to.be.instanceOf(TextHit); | ||
@@ -72,2 +224,12 @@ expect(details.results[0].identifier).to.equal('foo'); | ||
it('constructs favorited search hits', () => { | ||
const details = new SearchResponseDetails( | ||
favSearchResponseBody, | ||
favSearchSchema | ||
); | ||
expect(details.results[0]).to.be.instanceOf(FavoritedSearchHit); | ||
expect(details.results[0].query?.value).to.equal('foo'); | ||
expect(details.results[0].title?.value).to.equal('Foo'); | ||
}); | ||
it('prefers hit-type specified on hit itself over schema hit-type', () => { | ||
@@ -95,10 +257,5 @@ const responseBodyWithTextHit = { ...responseBody } as SearchResponseBody; | ||
const responseSchema = { | ||
hit_type: 'item' as HitType, | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails( | ||
responseBodyWithTextHit, | ||
responseSchema | ||
itemSchema | ||
); | ||
@@ -114,2 +271,11 @@ expect(details.results[0]).to.be.instanceOf(TextHit); // From hit, not schema | ||
it('constructs item hits when hit type unspecified', () => { | ||
const details = new SearchResponseDetails( | ||
responseBody, | ||
{} as SearchHitSchema | ||
); | ||
expect(details.results[0]).to.be.instanceOf(ItemHit); | ||
expect(details.results[0].identifier).to.equal('foo'); | ||
}); | ||
it('includes aggregations', () => { | ||
@@ -134,8 +300,3 @@ const aggsResponseBody: SearchResponseBody = { | ||
const responseSchema = { | ||
hit_type: 'item' as HitType, | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(aggsResponseBody, responseSchema); | ||
const details = new SearchResponseDetails(aggsResponseBody, itemSchema); | ||
expect(details.results.length).to.equal(0); | ||
@@ -155,8 +316,3 @@ expect(details.aggregations).to.deep.equal({ | ||
it('provides access to collection titles map', () => { | ||
const responseSchema = { | ||
hit_type: 'item' as HitType, | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(responseBody, responseSchema); | ||
const details = new SearchResponseDetails(responseBody, itemSchema); | ||
expect(details.results.length).to.equal(2); | ||
@@ -170,10 +326,5 @@ expect(details.collectionTitles).to.deep.equal({ baz: 'Baz Collection' }); | ||
const responseSchema = { | ||
hit_type: 'item' as HitType, | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails( | ||
responseBodyWithoutTitles, | ||
responseSchema | ||
itemSchema | ||
); | ||
@@ -185,8 +336,3 @@ expect(details.results.length).to.equal(2); | ||
it('provides access to collection extra info', () => { | ||
const responseSchema = { | ||
hit_type: 'item' as HitType, | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails(responseBody, responseSchema); | ||
const details = new SearchResponseDetails(responseBody, itemSchema); | ||
expect(details.results.length).to.equal(2); | ||
@@ -202,10 +348,5 @@ expect(details.collectionExtraInfo).to.deep.equal({ thumbnail_url: 'foo' }); | ||
const responseSchema = { | ||
hit_type: 'item' as HitType, | ||
field_properties: {}, | ||
}; | ||
const details = new SearchResponseDetails( | ||
responseBodyWithoutExtraInfo, | ||
responseSchema | ||
itemSchema | ||
); | ||
@@ -215,2 +356,84 @@ expect(details.results.length).to.equal(2); | ||
}); | ||
it('provides access to account extra info', () => { | ||
const details = new SearchResponseDetails( | ||
accountUploadsResponseBody, | ||
itemSchema | ||
); | ||
expect(details.accountExtraInfo?.user_item_metadata?.description).to.equal( | ||
'Foo bar baz' | ||
); | ||
}); | ||
it('account extra info is optional', () => { | ||
const accountBodyWithoutExtraInfo = { | ||
...accountUploadsResponseBody, | ||
} as SearchResponseBody; | ||
delete accountBodyWithoutExtraInfo.account_extra_info; | ||
const details = new SearchResponseDetails( | ||
accountBodyWithoutExtraInfo, | ||
itemSchema | ||
); | ||
expect(details.results.length).to.equal(2); | ||
expect(details.accountExtraInfo).to.be.undefined; | ||
}); | ||
it('provides access to hits from page element', () => { | ||
const details = new SearchResponseDetails( | ||
accountUploadsResponseBody, | ||
itemSchema | ||
); | ||
expect(details.results.length).to.equal(2); | ||
expect(details.results[0].identifier).to.equal('foo'); | ||
}); | ||
it('provides access to aggregations from page element', () => { | ||
const details = new SearchResponseDetails( | ||
accountUploadsResponseBody, | ||
itemSchema | ||
); | ||
expect(details.aggregations).to.exist; | ||
expect(details.aggregations?.subject?.buckets[0]).to.deep.equal({ | ||
key: 'foo', | ||
doc_count: 1, | ||
}); | ||
}); | ||
it('provides access to lending page elements', () => { | ||
const details = new SearchResponseDetails( | ||
accountLendingResponseBody, | ||
itemSchema | ||
); | ||
expect(details.results.length, 'results length').to.equal(1); | ||
expect(details.totalResults, 'total').to.equal(1); | ||
expect(details.returnedCount, 'returned').to.equal(1); | ||
expect(details.pageElements?.lending?.loans?.[0]?.identifier).to.equal( | ||
'foo' | ||
); | ||
expect(details.pageElements?.lending?.waitlist?.[0]?.identifier).to.equal( | ||
'bar' | ||
); | ||
expect( | ||
details.pageElements?.lending?.loan_history?.[0]?.identifier | ||
).to.equal('baz'); | ||
}); | ||
it('provides access to web archive page elements', () => { | ||
const details = new SearchResponseDetails( | ||
accountWebArchivesResponseBody, | ||
itemSchema | ||
); | ||
expect(details.results.length, 'results length').to.equal(1); | ||
expect(details.totalResults, 'total').to.equal(1); | ||
expect(details.returnedCount, 'returned').to.equal(1); | ||
const webArchiveResult = details.results[0]; | ||
expect(webArchiveResult.title?.value).to.equal('https://example.com/'); | ||
expect(webArchiveResult.capture_dates?.values?.length).to.equal(2); | ||
expect(webArchiveResult.__href__?.value).to.equal( | ||
'https://web.archive.org/web/20100102030405/https%3A%2F%2Fexample.com%2F' | ||
); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
967764
13840