diff --git a/src/collections/domain/models/CollectionItemSubset.ts b/src/collections/domain/models/CollectionItemSubset.ts index 81631bb8..aecd038f 100644 --- a/src/collections/domain/models/CollectionItemSubset.ts +++ b/src/collections/domain/models/CollectionItemSubset.ts @@ -4,5 +4,17 @@ import { CollectionPreview } from './CollectionPreview' export interface CollectionItemSubset { items: (CollectionPreview | DatasetPreview | FilePreview)[] + facets: CollectionItemsFacet[] totalItemCount: number } + +export interface CollectionItemsFacet { + name: string + friendlyName: string + labels: CollectionItemsFacetLabel[] +} + +interface CollectionItemsFacetLabel { + name: string + count: number +} diff --git a/src/collections/domain/models/CollectionSearchCriteria.ts b/src/collections/domain/models/CollectionSearchCriteria.ts index 998ab9a8..3f36735b 100644 --- a/src/collections/domain/models/CollectionSearchCriteria.ts +++ b/src/collections/domain/models/CollectionSearchCriteria.ts @@ -1,16 +1,73 @@ import { CollectionItemType } from './CollectionItemType' +export enum SortType { + NAME = 'name', + DATE = 'date' +} + +export enum OrderType { + ASC = 'asc', + DESC = 'desc' +} + +export type FilterQuery = `${string}:${string}` + export class CollectionSearchCriteria { constructor( public readonly searchText?: string, - public readonly itemTypes?: CollectionItemType[] + public readonly itemTypes?: CollectionItemType[], + public readonly sort?: SortType, + public readonly order?: OrderType, + public readonly filterQueries?: FilterQuery[] ) {} withSearchText(searchText: string | undefined): CollectionSearchCriteria { - return new CollectionSearchCriteria(searchText, this.itemTypes) + return new CollectionSearchCriteria( + searchText, + this.itemTypes, + this.sort, + this.order, + this.filterQueries + ) } withItemTypes(itemTypes: CollectionItemType[] | undefined): CollectionSearchCriteria { - return new CollectionSearchCriteria(this.searchText, itemTypes) + return new CollectionSearchCriteria( + this.searchText, + itemTypes, + this.sort, + this.order, + this.filterQueries + ) + } + + withSort(sort: SortType | undefined): CollectionSearchCriteria { + return new CollectionSearchCriteria( + this.searchText, + this.itemTypes, + sort, + this.order, + this.filterQueries + ) + } + + withOrder(order: OrderType | undefined): CollectionSearchCriteria { + return new CollectionSearchCriteria( + this.searchText, + this.itemTypes, + this.sort, + order, + this.filterQueries + ) + } + + withFilterQueries(filterQueries: FilterQuery[] | undefined): CollectionSearchCriteria { + return new CollectionSearchCriteria( + this.searchText, + this.itemTypes, + this.sort, + this.order, + filterQueries + ) } } diff --git a/src/collections/infra/repositories/CollectionsRepository.ts b/src/collections/infra/repositories/CollectionsRepository.ts index 8e3754a7..bee82863 100644 --- a/src/collections/infra/repositories/CollectionsRepository.ts +++ b/src/collections/infra/repositories/CollectionsRepository.ts @@ -11,7 +11,11 @@ import { CollectionFacet } from '../../domain/models/CollectionFacet' import { CollectionUserPermissions } from '../../domain/models/CollectionUserPermissions' import { transformCollectionUserPermissionsResponseToCollectionUserPermissions } from './transformers/collectionUserPermissionsTransformers' import { CollectionItemSubset } from '../../domain/models/CollectionItemSubset' -import { CollectionSearchCriteria } from '../../domain/models/CollectionSearchCriteria' +import { + CollectionSearchCriteria, + OrderType, + SortType +} from '../../domain/models/CollectionSearchCriteria' import { CollectionItemType } from '../../domain/models/CollectionItemType' export interface NewCollectionRequestPayload { @@ -40,12 +44,16 @@ export interface NewCollectionInputLevelRequestPayload { required: boolean } -export interface GetCollectionItemsQueryParams { - q: string - subtree?: string - per_page?: number - start?: number - type?: string +export enum GetCollectionItemsQueryParams { + QUERY = 'q', + SHOW_FACETS = 'show_facets', + SORT = 'sort', + ORDER = 'order', + SUBTREE = 'subtree', + PER_PAGE = 'per_page', + START = 'start', + TYPE = 'type', + FILTERQUERY = 'fq' } export class CollectionsRepository extends ApiRepository implements ICollectionsRepository { @@ -119,37 +127,30 @@ export class CollectionsRepository extends ApiRepository implements ICollections offset?: number, collectionSearchCriteria?: CollectionSearchCriteria ): Promise { - const queryParams: GetCollectionItemsQueryParams = { - q: '*' - } + const queryParams = new URLSearchParams({ + [GetCollectionItemsQueryParams.QUERY]: '*', + [GetCollectionItemsQueryParams.SHOW_FACETS]: 'true', + [GetCollectionItemsQueryParams.SORT]: SortType.DATE, + [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC + }) + if (collectionId) { - queryParams.subtree = collectionId + queryParams.set(GetCollectionItemsQueryParams.SUBTREE, collectionId) } + if (limit) { - queryParams.per_page = limit + queryParams.set(GetCollectionItemsQueryParams.PER_PAGE, limit.toString()) } + if (offset) { - queryParams.start = offset + queryParams.set(GetCollectionItemsQueryParams.START, offset.toString()) } + if (collectionSearchCriteria) { this.applyCollectionSearchCriteriaToQueryParams(queryParams, collectionSearchCriteria) } - let url = '/search?sort=date&order=desc' - - if (collectionSearchCriteria?.itemTypes) { - const itemTypesQueryString = collectionSearchCriteria.itemTypes - .map((itemType: CollectionItemType) => { - const mappedItemType = - itemType === CollectionItemType.COLLECTION ? 'dataverse' : itemType.toString() - return `type=${mappedItemType}` - }) - .join('&') - - url += `&${itemTypesQueryString}` - } - - return this.doGet(url, true, queryParams) + return this.doGet('/search', true, queryParams) .then((response) => transformCollectionItemsResponseToCollectionItemSubset(response)) .catch((error) => { throw error @@ -201,11 +202,42 @@ export class CollectionsRepository extends ApiRepository implements ICollections } private applyCollectionSearchCriteriaToQueryParams( - queryParams: GetCollectionItemsQueryParams, + queryParams: URLSearchParams, collectionSearchCriteria: CollectionSearchCriteria ) { if (collectionSearchCriteria.searchText) { - queryParams.q = encodeURIComponent(collectionSearchCriteria.searchText) + queryParams.set( + GetCollectionItemsQueryParams.QUERY, + encodeURIComponent(collectionSearchCriteria.searchText) + ) + } + + if (collectionSearchCriteria?.itemTypes) { + collectionSearchCriteria.itemTypes.forEach((itemType) => { + const mappedItemType = itemType === CollectionItemType.COLLECTION ? 'dataverse' : itemType + + queryParams.append(GetCollectionItemsQueryParams.TYPE, mappedItemType) + }) + } + + if (collectionSearchCriteria?.sort) { + queryParams.set(GetCollectionItemsQueryParams.SORT, collectionSearchCriteria.sort) + } + + if (collectionSearchCriteria?.order) { + queryParams.set(GetCollectionItemsQueryParams.ORDER, collectionSearchCriteria.order) + } + + if (collectionSearchCriteria?.filterQueries) { + collectionSearchCriteria.filterQueries.forEach((filterQuery) => { + const [filterQueryKey, filterQueryValue] = filterQuery.split(':') + + const filterQueryValueWithQuotes = `"${filterQueryValue}"` + + const filterQueryToSet = `${filterQueryKey}:${filterQueryValueWithQuotes}` + + queryParams.append(GetCollectionItemsQueryParams.FILTERQUERY, filterQueryToSet) + }) } } } diff --git a/src/collections/infra/repositories/transformers/CollectionItemsFacetsPayload.ts b/src/collections/infra/repositories/transformers/CollectionItemsFacetsPayload.ts new file mode 100644 index 00000000..adb5e74f --- /dev/null +++ b/src/collections/infra/repositories/transformers/CollectionItemsFacetsPayload.ts @@ -0,0 +1,6 @@ +export type CollectionItemsFacetPayload = [Record] + +export interface CollectionItemsFacetPayloadValue { + friendly: string + labels: Record[] +} diff --git a/src/collections/infra/repositories/transformers/collectionTransformers.ts b/src/collections/infra/repositories/transformers/collectionTransformers.ts index 34ffe390..d4b4ca82 100644 --- a/src/collections/infra/repositories/transformers/collectionTransformers.ts +++ b/src/collections/infra/repositories/transformers/collectionTransformers.ts @@ -9,7 +9,10 @@ import { transformPayloadToOwnerNode } from '../../../../core/infra/repositories import { transformHtmlToMarkdown } from '../../../../datasets/infra/repositories/transformers/datasetTransformers' import { CollectionFacet } from '../../../domain/models/CollectionFacet' import { CollectionFacetPayload } from './CollectionFacetPayload' -import { CollectionItemSubset } from '../../../domain/models/CollectionItemSubset' +import { + CollectionItemsFacet, + CollectionItemSubset +} from '../../../domain/models/CollectionItemSubset' import { DatasetPreview } from '../../../../datasets' import { FilePreview } from '../../../../files' import { DatasetPreviewPayload } from '../../../../datasets/infra/repositories/transformers/DatasetPreviewPayload' @@ -21,6 +24,7 @@ import { CollectionPreviewPayload } from './CollectionPreviewPayload' import { CollectionPreview } from '../../../domain/models/CollectionPreview' import { CollectionContact } from '../../../domain/models/CollectionContact' import { CollectionType } from '../../../domain/models/CollectionType' +import { CollectionItemsFacetPayload } from './CollectionItemsFacetsPayload' export const transformCollectionResponseToCollection = (response: AxiosResponse): Collection => { const collectionPayload = response.data.data @@ -79,7 +83,10 @@ export const transformCollectionItemsResponseToCollectionItemSubset = ( ): CollectionItemSubset => { const responseDataPayload = response.data.data const itemsPayload = responseDataPayload.items + const facetsPayload = responseDataPayload.facets as CollectionItemsFacetPayload + const items: (DatasetPreview | FilePreview | CollectionPreview)[] = [] + itemsPayload.forEach(function ( itemPayload: CollectionPreviewPayload | DatasetPreviewPayload | FilePreviewPayload ) { @@ -97,8 +104,21 @@ export const transformCollectionItemsResponseToCollectionItemSubset = ( ) } }) + + const facets: CollectionItemsFacet[] = Object.entries(facetsPayload[0]).map( + ([key, facetData]) => ({ + name: key, + friendlyName: facetData.friendly, + labels: facetData.labels.map((label: Record) => { + const [name, count] = Object.entries(label)[0] + return { name, count } + }) + }) + ) + return { - items: items, + items, + facets, totalItemCount: responseDataPayload.total_count } } diff --git a/src/core/infra/repositories/ApiRepository.ts b/src/core/infra/repositories/ApiRepository.ts index 980df121..fb0726ac 100644 --- a/src/core/infra/repositories/ApiRepository.ts +++ b/src/core/infra/repositories/ApiRepository.ts @@ -8,7 +8,7 @@ export abstract class ApiRepository { public async doGet( apiEndpoint: string, authRequired = false, - queryParams: object = {} + queryParams: object | URLSearchParams = {} ): Promise { return await axios .get(buildRequestUrl(apiEndpoint), buildRequestConfig(authRequired, queryParams)) diff --git a/src/core/infra/repositories/apiConfigBuilders.ts b/src/core/infra/repositories/apiConfigBuilders.ts index 5886d188..56a3eb54 100644 --- a/src/core/infra/repositories/apiConfigBuilders.ts +++ b/src/core/infra/repositories/apiConfigBuilders.ts @@ -4,7 +4,7 @@ import { ApiConstants } from './ApiConstants' export const buildRequestConfig = ( authRequired: boolean, - queryParams: object, + queryParams: object | URLSearchParams, contentType: string = ApiConstants.CONTENT_TYPE_APPLICATION_JSON, abortSignal?: AbortSignal ): AxiosRequestConfig => { diff --git a/test/integration/collections/CollectionsRepository.test.ts b/test/integration/collections/CollectionsRepository.test.ts index e4094730..e763e105 100644 --- a/test/integration/collections/CollectionsRepository.test.ts +++ b/test/integration/collections/CollectionsRepository.test.ts @@ -24,6 +24,10 @@ import { uploadFileViaApi } from '../../testHelpers/files/filesHelper' import { deleteUnpublishedDatasetViaApi } from '../../testHelpers/datasets/datasetHelper' import { PublicationStatus } from '../../../src/core/domain/models/PublicationStatus' import { CollectionType } from '../../../src/collections/domain/models/CollectionType' +import { + OrderType, + SortType +} from '../../../src/collections/domain/models/CollectionSearchCriteria' describe('CollectionsRepository', () => { const testCollectionAlias = 'collectionsRepositoryTestCollection' @@ -294,6 +298,68 @@ describe('CollectionsRepository', () => { const expectedFileName = 'test-file-1.txt' const expectedCollectionsName = 'Scientific Research' + //prettier-ignore + const expectedFacetsAll = [ + { + name: 'dvCategory', friendlyName: 'Dataverse Category', labels: [{ name: 'Laboratory', count: 1 }] + }, + { + name: 'publicationStatus', friendlyName: 'Publication Status', labels: [{ name: 'Unpublished', count: 3 },{ name: 'Draft', count: 2 }] + }, + { + name: 'authorName_ss', friendlyName: 'Author Name', labels: [{ name: 'Admin, Dataverse', count: 1 },{ name: 'Owner, Dataverse', count: 1 }] + }, + { + name: 'subject_ss', friendlyName: 'Subject', labels: [{ name: 'Medicine, Health and Life Sciences', count: 1 }] + }, + { + name: 'fileTypeGroupFacet', friendlyName: 'File Type', labels: [{ name: 'Text', count: 1 }] + }, + { + name: 'fileAccess', friendlyName: 'Access', labels: [{ name: 'Public', count: 1 }] + } + ] + //prettier-ignore + const expectedFacetsFromCollectionOnly = [ + { + name: 'dvCategory', friendlyName: 'Dataverse Category', labels: [{ name: 'Laboratory', count: 1 }] + }, + { + name: 'publicationStatus', friendlyName: 'Publication Status', labels: [{ name: 'Unpublished', count: 1 }] + } + ] + //prettier-ignore + const expectedFacetsFromDatasetOnly = [ + { + name: 'publicationStatus', friendlyName: 'Publication Status', labels: [{ name: 'Draft', count: 1 },{ name: 'Unpublished', count: 1 }] + }, + { + name: 'authorName_ss', friendlyName: 'Author Name', labels: [{ name: 'Admin, Dataverse', count: 1 },{ name: 'Owner, Dataverse', count: 1 }] + }, + { + name: 'subject_ss', friendlyName: 'Subject', labels: [{ name: 'Medicine, Health and Life Sciences', count: 1 }] + } + ] + //prettier-ignore + const expectedFacetsFromFileOnly = [ + { + name: 'publicationStatus', friendlyName: 'Publication Status', labels: [{ name: 'Draft', count: 1 },{ name: 'Unpublished', count: 1 }] + }, + { name: 'fileTypeGroupFacet', friendlyName: 'File Type', labels: [{ name: 'Text', count: 1 }] }, + { name: 'fileAccess', friendlyName: 'Access', labels: [{ name: 'Public', count: 1 }] } + ] + //prettier-ignore + const expectedFacetsFromCollectionAndFile = [ + { + name: 'dvCategory', friendlyName: 'Dataverse Category', labels: [{ name: 'Laboratory', count: 1 }] + }, + { + name: 'publicationStatus', friendlyName: 'Publication Status', labels: [{ name: 'Unpublished', count: 2 },{ name: 'Draft', count: 1 }] + }, + { name: 'fileTypeGroupFacet', friendlyName: 'File Type', labels: [{ name: 'Text', count: 1 }] }, + { name: 'fileAccess', friendlyName: 'Access', labels: [{ name: 'Public', count: 1 }] } + ] + expect(actualFilePreview.checksum?.type).toBe('MD5') expect(actualFilePreview.checksum?.value).toBe(expectedFileMd5) expect(actualFilePreview.datasetCitation).toContain(expectedDatasetCitationFragment) @@ -347,6 +413,8 @@ describe('CollectionsRepository', () => { expect(actual.totalItemCount).toBe(3) + expect(actual.facets).toEqual(expectedFacetsAll) + // Test limit and offset actual = await sut.getCollectionItems(testCollectionAlias, 1, 1) expect((actual.items[0] as DatasetPreview).persistentId).toBe(testDatasetIds.persistentId) @@ -413,6 +481,7 @@ describe('CollectionsRepository', () => { expect(actual.items.length).toBe(1) expect(actual.totalItemCount).toBe(1) expect((actual.items[0] as CollectionPreview).name).toBe(expectedCollectionsName) + expect(actual.facets).toEqual(expectedFacetsFromCollectionOnly) // Test type dataset const collectionSearchCriteriaForDatasetType = new CollectionSearchCriteria().withItemTypes([ @@ -427,6 +496,7 @@ describe('CollectionsRepository', () => { expect(actual.items.length).toBe(1) expect(actual.totalItemCount).toBe(1) expect((actual.items[0] as DatasetPreview).title).toBe(expectedDatasetDescription) + expect(actual.facets).toEqual(expectedFacetsFromDatasetOnly) // Test type file const collectionSearchCriteriaForFileType = new CollectionSearchCriteria().withItemTypes([ @@ -441,6 +511,7 @@ describe('CollectionsRepository', () => { expect(actual.items.length).toBe(1) expect(actual.totalItemCount).toBe(1) expect((actual.items[0] as FilePreview).name).toBe(expectedFileName) + expect(actual.facets).toEqual(expectedFacetsFromFileOnly) // Test multiple types const collectionSearchCriteriaForMultiTypes = new CollectionSearchCriteria().withItemTypes([ @@ -457,6 +528,123 @@ describe('CollectionsRepository', () => { expect(actual.totalItemCount).toBe(2) expect((actual.items[0] as FilePreview).name).toBe(expectedFileName) expect((actual.items[1] as CollectionPreview).name).toBe(expectedCollectionsName) + expect(actual.facets).toEqual(expectedFacetsFromCollectionAndFile) + + // Test Sort by name ascending + const collectionSearchCriteriaNameAscending = new CollectionSearchCriteria() + .withSort(SortType.NAME) + .withOrder(OrderType.ASC) + + actual = await sut.getCollectionItems( + testCollectionAlias, + undefined, + undefined, + collectionSearchCriteriaNameAscending + ) + expect(actual.items.length).toBe(3) + expect(actual.totalItemCount).toBe(3) + expect((actual.items[0] as DatasetPreview).type).toBe(CollectionItemType.DATASET) + expect((actual.items[1] as CollectionPreview).type).toBe(CollectionItemType.COLLECTION) + expect((actual.items[2] as FilePreview).type).toBe(CollectionItemType.FILE) + + // Test Sort by name descending + const collectionSearchCriteriaNameDescending = new CollectionSearchCriteria() + .withSort(SortType.NAME) + .withOrder(OrderType.DESC) + + actual = await sut.getCollectionItems( + testCollectionAlias, + undefined, + undefined, + collectionSearchCriteriaNameDescending + ) + expect(actual.items.length).toBe(3) + expect(actual.totalItemCount).toBe(3) + expect((actual.items[0] as FilePreview).type).toBe(CollectionItemType.FILE) + expect((actual.items[1] as CollectionPreview).type).toBe(CollectionItemType.COLLECTION) + expect((actual.items[2] as DatasetPreview).type).toBe(CollectionItemType.DATASET) + + // Test Sort by date ascending + const collectionSearchCriteriaDateAscending = new CollectionSearchCriteria() + .withSort(SortType.DATE) + .withOrder(OrderType.ASC) + + actual = await sut.getCollectionItems( + testCollectionAlias, + undefined, + undefined, + collectionSearchCriteriaDateAscending + ) + expect(actual.items.length).toBe(3) + expect(actual.totalItemCount).toBe(3) + expect((actual.items[0] as CollectionPreview).type).toBe(CollectionItemType.COLLECTION) + expect((actual.items[1] as DatasetPreview).type).toBe(CollectionItemType.DATASET) + expect((actual.items[2] as FilePreview).type).toBe(CollectionItemType.FILE) + + // Test Sort by date descending + const collectionSearchCriteriaDateDescending = new CollectionSearchCriteria() + .withSort(SortType.DATE) + .withOrder(OrderType.DESC) + + actual = await sut.getCollectionItems( + testCollectionAlias, + undefined, + undefined, + collectionSearchCriteriaDateDescending + ) + expect(actual.items.length).toBe(3) + expect(actual.totalItemCount).toBe(3) + expect((actual.items[0] as FilePreview).type).toBe(CollectionItemType.FILE) + expect((actual.items[1] as DatasetPreview).type).toBe(CollectionItemType.DATASET) + expect((actual.items[2] as CollectionPreview).type).toBe(CollectionItemType.COLLECTION) + + // Test with Filter query related to the collection + const collectionSearchCriteriaFilterQueryCollection = + new CollectionSearchCriteria().withFilterQueries(['dvCategory:Laboratory']) + + actual = await sut.getCollectionItems( + testCollectionAlias, + undefined, + undefined, + collectionSearchCriteriaFilterQueryCollection + ) + expect(actual.items.length).toBe(1) + expect(actual.totalItemCount).toBe(1) + expect((actual.items[0] as CollectionPreview).name).toBe(expectedCollectionsName) + expect(actual.facets).toEqual(expectedFacetsFromCollectionOnly) + + // Test with Filter query related to the dataset + const collectionSearchCriteriaFilterQueryDataset = + new CollectionSearchCriteria().withFilterQueries([ + 'subject_ss:Medicine, Health and Life Sciences' + ]) + + actual = await sut.getCollectionItems( + testCollectionAlias, + undefined, + undefined, + collectionSearchCriteriaFilterQueryDataset + ) + expect(actual.items.length).toBe(1) + expect(actual.totalItemCount).toBe(1) + expect((actual.items[0] as DatasetPreview).title).toBe(expectedDatasetDescription) + expect(actual.facets).toEqual(expectedFacetsFromDatasetOnly) + + // Test with Filter query related to the file + const collectionSearchCriteriaFilterQuerieCollAndFile = + new CollectionSearchCriteria().withFilterQueries(['fileAccess:Public']) + + actual = await sut.getCollectionItems( + testCollectionAlias, + undefined, + undefined, + collectionSearchCriteriaFilterQuerieCollAndFile + ) + + expect(actual.items.length).toBe(1) + expect(actual.totalItemCount).toBe(1) + expect((actual.items[0] as FilePreview).name).toBe(expectedFileName) + expect(actual.facets).toEqual(expectedFacetsFromFileOnly) }) test('should return error when collection does not exist', async () => { diff --git a/test/testHelpers/collections/collectionItemsFacetsHelper.ts b/test/testHelpers/collections/collectionItemsFacetsHelper.ts new file mode 100644 index 00000000..c1754dee --- /dev/null +++ b/test/testHelpers/collections/collectionItemsFacetsHelper.ts @@ -0,0 +1,38 @@ +import { CollectionItemsFacet } from '../../../src/collections/domain/models/CollectionItemSubset' +import { CollectionItemsFacetPayload } from '../../../src/collections/infra/repositories/transformers/CollectionItemsFacetsPayload' + +export const createCollectionItemsFacetsModel = (): CollectionItemsFacet[] => { + return [ + { + name: 'facet1', + friendlyName: 'Facet 1', + labels: [ + { name: 'Label 1', count: 5 }, + { name: 'Label 2', count: 4 } + ] + }, + { + name: 'facet2', + friendlyName: 'Facet 2', + labels: [ + { name: 'Label 3', count: 8 }, + { name: 'Label 4', count: 9 } + ] + } + ] +} + +export const createCollectionItemsFacetsPayload = (): CollectionItemsFacetPayload => { + return [ + { + facet1: { + friendly: 'Facet 1', + labels: [{ 'Label 1': 5 }, { 'Label 2': 4 }] + }, + facet2: { + friendly: 'Facet 2', + labels: [{ 'Label 3': 8 }, { 'Label 4': 9 }] + } + } + ] +} diff --git a/test/unit/collections/CollectionsRepository.test.ts b/test/unit/collections/CollectionsRepository.test.ts index d9c97dd2..d7a0af31 100644 --- a/test/unit/collections/CollectionsRepository.test.ts +++ b/test/unit/collections/CollectionsRepository.test.ts @@ -1,4 +1,7 @@ -import { CollectionsRepository } from '../../../src/collections/infra/repositories/CollectionsRepository' +import { + CollectionsRepository, + GetCollectionItemsQueryParams +} from '../../../src/collections/infra/repositories/CollectionsRepository' import axios from 'axios' import { ApiConfig, @@ -31,6 +34,14 @@ import { createCollectionPreviewModel, createCollectionPreviewPayload } from '../../testHelpers/collections/collectionPreviewHelper' +import { + createCollectionItemsFacetsModel, + createCollectionItemsFacetsPayload +} from '../../testHelpers/collections/collectionItemsFacetsHelper' +import { + OrderType, + SortType +} from '../../../src/collections/domain/models/CollectionSearchCriteria' describe('CollectionsRepository', () => { const sut: CollectionsRepository = new CollectionsRepository() @@ -361,9 +372,11 @@ describe('CollectionsRepository', () => { createCollectionPreviewModel() ] const testTotalCount = 2 + const testFacets = createCollectionItemsFacetsModel() const testItemSubset: CollectionItemSubset = { items: testItems, + facets: testFacets, totalItemCount: testTotalCount } @@ -376,12 +389,13 @@ describe('CollectionsRepository', () => { createDatasetPreviewPayload(), createFilePreviewPayload(), createCollectionPreviewPayload() - ] + ], + facets: createCollectionItemsFacetsPayload() } } } - const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/search?sort=date&order=desc` + const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/search` test('should return item previews when response is successful', async () => { jest.spyOn(axios, 'get').mockResolvedValue(testItemPreviewsResponse) @@ -389,9 +403,12 @@ describe('CollectionsRepository', () => { // API Key auth let actual = await sut.getCollectionItems() - const expectedRequestParams = { - q: '*' - } + const expectedRequestParams = new URLSearchParams({ + [GetCollectionItemsQueryParams.QUERY]: '*', + [GetCollectionItemsQueryParams.SHOW_FACETS]: 'true', + [GetCollectionItemsQueryParams.SORT]: SortType.DATE, + [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC + }) const expectedRequestConfigApiKey = { params: expectedRequestParams, @@ -430,11 +447,14 @@ describe('CollectionsRepository', () => { // API Key auth let actual = await sut.getCollectionItems(undefined, testLimit, testOffset) - const expectedRequestParamsWithPagination = { - q: '*', - per_page: testLimit, - start: testOffset - } + const expectedRequestParamsWithPagination = new URLSearchParams({ + [GetCollectionItemsQueryParams.QUERY]: '*', + [GetCollectionItemsQueryParams.SHOW_FACETS]: 'true', + [GetCollectionItemsQueryParams.SORT]: SortType.DATE, + [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC, + [GetCollectionItemsQueryParams.PER_PAGE]: testLimit.toString(), + [GetCollectionItemsQueryParams.START]: testOffset.toString() + }) const expectedRequestConfigApiKeyWithPagination = { params: expectedRequestParamsWithPagination, @@ -474,10 +494,13 @@ describe('CollectionsRepository', () => { // API Key auth let actual = await sut.getCollectionItems(testCollectionId, undefined, undefined) - const expectedRequestParamsWithCollectionId = { - q: '*', - subtree: testCollectionId - } + const expectedRequestParamsWithCollectionId = new URLSearchParams({ + [GetCollectionItemsQueryParams.QUERY]: '*', + [GetCollectionItemsQueryParams.SHOW_FACETS]: 'true', + [GetCollectionItemsQueryParams.SORT]: SortType.DATE, + [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC, + [GetCollectionItemsQueryParams.SUBTREE]: testCollectionId + }) const expectedRequestConfigApiKeyWithCollectionId = { params: expectedRequestParamsWithCollectionId, @@ -515,9 +538,12 @@ describe('CollectionsRepository', () => { let error = undefined as unknown as ReadError await sut.getCollectionItems().catch((e) => (error = e)) - const expectedRequestParams = { - q: '*' - } + const expectedRequestParams = new URLSearchParams({ + [GetCollectionItemsQueryParams.QUERY]: '*', + [GetCollectionItemsQueryParams.SHOW_FACETS]: 'true', + [GetCollectionItemsQueryParams.SORT]: SortType.DATE, + [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC + }) const expectedRequestConfigApiKey = { params: expectedRequestParams, diff --git a/test/unit/collections/GetCollectionItems.test.ts b/test/unit/collections/GetCollectionItems.test.ts index 28622f51..8c83ae95 100644 --- a/test/unit/collections/GetCollectionItems.test.ts +++ b/test/unit/collections/GetCollectionItems.test.ts @@ -5,6 +5,7 @@ import { createDatasetPreviewModel } from '../../testHelpers/datasets/datasetPre import { createFilePreviewModel } from '../../testHelpers/files/filePreviewHelper' import { CollectionItemSubset } from '../../../src/collections/domain/models/CollectionItemSubset' import { createCollectionPreviewModel } from '../../testHelpers/collections/collectionPreviewHelper' +import { createCollectionItemsFacetsModel } from '../../testHelpers/collections/collectionItemsFacetsHelper' describe('execute', () => { let collectionRepositoryStub: ICollectionsRepository @@ -16,9 +17,11 @@ describe('execute', () => { createCollectionPreviewModel() ] const testTotalCount = 3 + const testFacets = createCollectionItemsFacetsModel() const testItemSubset: CollectionItemSubset = { items: testItems, + facets: testFacets, totalItemCount: testTotalCount }