From 77b9d26754a5bf4b9238127b65cefce169621c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Saracca?= Date: Fri, 17 Jan 2025 11:21:04 -0300 Subject: [PATCH 1/4] feat: send show type counts param always --- .../domain/models/CollectionItemSubset.ts | 7 +++++++ .../infra/repositories/CollectionsRepository.ts | 6 ++++-- .../CollectionItemsCountPerObjectTypePayload.ts | 5 +++++ .../transformers/collectionTransformers.ts | 13 ++++++++++++- 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 src/collections/infra/repositories/transformers/CollectionItemsCountPerObjectTypePayload.ts diff --git a/src/collections/domain/models/CollectionItemSubset.ts b/src/collections/domain/models/CollectionItemSubset.ts index aecd038f..279b2e98 100644 --- a/src/collections/domain/models/CollectionItemSubset.ts +++ b/src/collections/domain/models/CollectionItemSubset.ts @@ -6,6 +6,7 @@ export interface CollectionItemSubset { items: (CollectionPreview | DatasetPreview | FilePreview)[] facets: CollectionItemsFacet[] totalItemCount: number + countPerObjectType: CountPerObjectType } export interface CollectionItemsFacet { @@ -18,3 +19,9 @@ interface CollectionItemsFacetLabel { name: string count: number } + +interface CountPerObjectType { + dataverses: number + datasets: number + files: number +} diff --git a/src/collections/infra/repositories/CollectionsRepository.ts b/src/collections/infra/repositories/CollectionsRepository.ts index bee82863..e69be560 100644 --- a/src/collections/infra/repositories/CollectionsRepository.ts +++ b/src/collections/infra/repositories/CollectionsRepository.ts @@ -53,7 +53,8 @@ export enum GetCollectionItemsQueryParams { PER_PAGE = 'per_page', START = 'start', TYPE = 'type', - FILTERQUERY = 'fq' + FILTERQUERY = 'fq', + SHOW_TYPE_COUNTS = 'show_type_counts' } export class CollectionsRepository extends ApiRepository implements ICollectionsRepository { @@ -131,7 +132,8 @@ export class CollectionsRepository extends ApiRepository implements ICollections [GetCollectionItemsQueryParams.QUERY]: '*', [GetCollectionItemsQueryParams.SHOW_FACETS]: 'true', [GetCollectionItemsQueryParams.SORT]: SortType.DATE, - [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC + [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC, + [GetCollectionItemsQueryParams.SHOW_TYPE_COUNTS]: 'true' }) if (collectionId) { diff --git a/src/collections/infra/repositories/transformers/CollectionItemsCountPerObjectTypePayload.ts b/src/collections/infra/repositories/transformers/CollectionItemsCountPerObjectTypePayload.ts new file mode 100644 index 00000000..b740d447 --- /dev/null +++ b/src/collections/infra/repositories/transformers/CollectionItemsCountPerObjectTypePayload.ts @@ -0,0 +1,5 @@ +export interface CollectionItemsCountPerObjectTypePayload { + Dataverses: number + Datasets: number + Files: number +} diff --git a/src/collections/infra/repositories/transformers/collectionTransformers.ts b/src/collections/infra/repositories/transformers/collectionTransformers.ts index d4b4ca82..a1888c75 100644 --- a/src/collections/infra/repositories/transformers/collectionTransformers.ts +++ b/src/collections/infra/repositories/transformers/collectionTransformers.ts @@ -25,6 +25,7 @@ import { CollectionPreview } from '../../../domain/models/CollectionPreview' import { CollectionContact } from '../../../domain/models/CollectionContact' import { CollectionType } from '../../../domain/models/CollectionType' import { CollectionItemsFacetPayload } from './CollectionItemsFacetsPayload' +import { CollectionItemsCountPerObjectTypePayload } from './CollectionItemsCountPerObjectTypePayload' export const transformCollectionResponseToCollection = (response: AxiosResponse): Collection => { const collectionPayload = response.data.data @@ -84,6 +85,9 @@ export const transformCollectionItemsResponseToCollectionItemSubset = ( const responseDataPayload = response.data.data const itemsPayload = responseDataPayload.items const facetsPayload = responseDataPayload.facets as CollectionItemsFacetPayload + const countPerObjectTypePayload = responseDataPayload[ + 'total_count_per_object_type' + ] as CollectionItemsCountPerObjectTypePayload const items: (DatasetPreview | FilePreview | CollectionPreview)[] = [] @@ -116,10 +120,17 @@ export const transformCollectionItemsResponseToCollectionItemSubset = ( }) ) + const countPerObjectType = { + dataverses: countPerObjectTypePayload['Dataverses'], + datasets: countPerObjectTypePayload['Datasets'], + files: countPerObjectTypePayload['Files'] + } + return { items, facets, - totalItemCount: responseDataPayload.total_count + totalItemCount: responseDataPayload.total_count, + countPerObjectType } } From 60596184b488043d74691f5a11dcddacd5c0f3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Saracca?= Date: Fri, 17 Jan 2025 11:43:23 -0300 Subject: [PATCH 2/4] test: add integration and unit cases --- test/environment/.env | 4 +- .../collections/CollectionsRepository.test.ts | 48 +++++++++++++++++++ .../collections/CollectionsRepository.test.ts | 23 +++++++-- .../collections/GetCollectionItems.test.ts | 8 +++- 4 files changed, 76 insertions(+), 7 deletions(-) diff --git a/test/environment/.env b/test/environment/.env index 80e9a14e..5cee3e2c 100644 --- a/test/environment/.env +++ b/test/environment/.env @@ -1,6 +1,6 @@ POSTGRES_VERSION=13 DATAVERSE_DB_USER=dataverse SOLR_VERSION=9.3.0 -DATAVERSE_IMAGE_REGISTRY=docker.io -DATAVERSE_IMAGE_TAG=unstable +DATAVERSE_IMAGE_REGISTRY=ghcr.io +DATAVERSE_IMAGE_TAG=11127-search-api-counts DATAVERSE_BOOTSTRAP_TIMEOUT=5m diff --git a/test/integration/collections/CollectionsRepository.test.ts b/test/integration/collections/CollectionsRepository.test.ts index 042b5a26..98717f7b 100644 --- a/test/integration/collections/CollectionsRepository.test.ts +++ b/test/integration/collections/CollectionsRepository.test.ts @@ -417,6 +417,9 @@ describe('CollectionsRepository', () => { expect(actualCollectionPreview.type).toBe(CollectionItemType.COLLECTION) expect(actual.totalItemCount).toBe(3) + expect(actual.countPerObjectType.dataverses).toBe(1) + expect(actual.countPerObjectType.datasets).toBe(1) + expect(actual.countPerObjectType.files).toBe(1) expect(actual.facets).toEqual(expectedFacetsAll) @@ -438,6 +441,9 @@ describe('CollectionsRepository', () => { ) expect(actual.totalItemCount).toBe(1) expect((actual.items[0] as FilePreview).name).toBe(expectedFileName) + expect(actual.countPerObjectType.dataverses).toBe(0) + expect(actual.countPerObjectType.datasets).toBe(0) + expect(actual.countPerObjectType.files).toBe(1) const collectionSearchCriteriaForDataset = new CollectionSearchCriteria().withSearchText( 'This is the description' @@ -450,6 +456,9 @@ describe('CollectionsRepository', () => { ) expect(actual.totalItemCount).toBe(1) expect((actual.items[0] as DatasetPreview).title).toBe(expectedDatasetDescription) + expect(actual.countPerObjectType.dataverses).toBe(0) + expect(actual.countPerObjectType.datasets).toBe(1) + expect(actual.countPerObjectType.files).toBe(0) const collectionSearchCriteriaForDatasetAndCollection = new CollectionSearchCriteria().withSearchText('the') @@ -462,6 +471,9 @@ describe('CollectionsRepository', () => { expect(actual.totalItemCount).toBe(2) expect((actual.items[0] as DatasetPreview).title).toBe(expectedDatasetDescription) expect((actual.items[1] as CollectionPreview).name).toBe(expectedCollectionsName) + expect(actual.countPerObjectType.dataverses).toBe(1) + expect(actual.countPerObjectType.datasets).toBe(1) + expect(actual.countPerObjectType.files).toBe(0) // Test search text, limit and offset actual = await sut.getCollectionItems( @@ -473,6 +485,9 @@ describe('CollectionsRepository', () => { expect(actual.items.length).toBe(1) expect(actual.totalItemCount).toBe(2) expect((actual.items[0] as CollectionPreview).name).toBe(expectedCollectionsName) + expect(actual.countPerObjectType.dataverses).toBe(1) + expect(actual.countPerObjectType.datasets).toBe(1) + expect(actual.countPerObjectType.files).toBe(0) // Test type collection const collectionSearchCriteriaForCollectionType = @@ -487,6 +502,9 @@ describe('CollectionsRepository', () => { expect(actual.totalItemCount).toBe(1) expect((actual.items[0] as CollectionPreview).name).toBe(expectedCollectionsName) expect(actual.facets).toEqual(expectedFacetsFromCollectionOnly) + expect(actual.countPerObjectType.dataverses).toBe(1) + expect(actual.countPerObjectType.datasets).toBe(0) + expect(actual.countPerObjectType.files).toBe(0) // Test type dataset const collectionSearchCriteriaForDatasetType = new CollectionSearchCriteria().withItemTypes([ @@ -502,6 +520,9 @@ describe('CollectionsRepository', () => { expect(actual.totalItemCount).toBe(1) expect((actual.items[0] as DatasetPreview).title).toBe(expectedDatasetDescription) expect(actual.facets).toEqual(expectedFacetsFromDatasetOnly) + expect(actual.countPerObjectType.dataverses).toBe(0) + expect(actual.countPerObjectType.datasets).toBe(1) + expect(actual.countPerObjectType.files).toBe(0) // Test type file const collectionSearchCriteriaForFileType = new CollectionSearchCriteria().withItemTypes([ @@ -517,6 +538,9 @@ describe('CollectionsRepository', () => { expect(actual.totalItemCount).toBe(1) expect((actual.items[0] as FilePreview).name).toBe(expectedFileName) expect(actual.facets).toEqual(expectedFacetsFromFileOnly) + expect(actual.countPerObjectType.dataverses).toBe(0) + expect(actual.countPerObjectType.datasets).toBe(0) + expect(actual.countPerObjectType.files).toBe(1) // Test multiple types const collectionSearchCriteriaForMultiTypes = new CollectionSearchCriteria().withItemTypes([ @@ -534,6 +558,9 @@ describe('CollectionsRepository', () => { expect((actual.items[0] as FilePreview).name).toBe(expectedFileName) expect((actual.items[1] as CollectionPreview).name).toBe(expectedCollectionsName) expect(actual.facets).toEqual(expectedFacetsFromCollectionAndFile) + expect(actual.countPerObjectType.dataverses).toBe(1) + expect(actual.countPerObjectType.datasets).toBe(0) + expect(actual.countPerObjectType.files).toBe(1) // Test Sort by name ascending const collectionSearchCriteriaNameAscending = new CollectionSearchCriteria() @@ -551,6 +578,9 @@ describe('CollectionsRepository', () => { 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) + expect(actual.countPerObjectType.dataverses).toBe(1) + expect(actual.countPerObjectType.datasets).toBe(1) + expect(actual.countPerObjectType.files).toBe(1) // Test Sort by name descending const collectionSearchCriteriaNameDescending = new CollectionSearchCriteria() @@ -568,6 +598,9 @@ describe('CollectionsRepository', () => { 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) + expect(actual.countPerObjectType.dataverses).toBe(1) + expect(actual.countPerObjectType.datasets).toBe(1) + expect(actual.countPerObjectType.files).toBe(1) // Test Sort by date ascending const collectionSearchCriteriaDateAscending = new CollectionSearchCriteria() @@ -585,6 +618,9 @@ describe('CollectionsRepository', () => { 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) + expect(actual.countPerObjectType.dataverses).toBe(1) + expect(actual.countPerObjectType.datasets).toBe(1) + expect(actual.countPerObjectType.files).toBe(1) // Test Sort by date descending const collectionSearchCriteriaDateDescending = new CollectionSearchCriteria() @@ -602,6 +638,9 @@ describe('CollectionsRepository', () => { 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) + expect(actual.countPerObjectType.dataverses).toBe(1) + expect(actual.countPerObjectType.datasets).toBe(1) + expect(actual.countPerObjectType.files).toBe(1) // Test with Filter query related to the collection const collectionSearchCriteriaFilterQueryCollection = @@ -617,6 +656,9 @@ describe('CollectionsRepository', () => { expect(actual.totalItemCount).toBe(1) expect((actual.items[0] as CollectionPreview).name).toBe(expectedCollectionsName) expect(actual.facets).toEqual(expectedFacetsFromCollectionOnly) + expect(actual.countPerObjectType.dataverses).toBe(1) + expect(actual.countPerObjectType.datasets).toBe(0) + expect(actual.countPerObjectType.files).toBe(0) // Test with Filter query related to the dataset const collectionSearchCriteriaFilterQueryDataset = @@ -634,6 +676,9 @@ describe('CollectionsRepository', () => { expect(actual.totalItemCount).toBe(1) expect((actual.items[0] as DatasetPreview).title).toBe(expectedDatasetDescription) expect(actual.facets).toEqual(expectedFacetsFromDatasetOnly) + expect(actual.countPerObjectType.dataverses).toBe(0) + expect(actual.countPerObjectType.datasets).toBe(1) + expect(actual.countPerObjectType.files).toBe(0) // Test with Filter query related to the file const collectionSearchCriteriaFilterQuerieCollAndFile = @@ -650,6 +695,9 @@ describe('CollectionsRepository', () => { expect(actual.totalItemCount).toBe(1) expect((actual.items[0] as FilePreview).name).toBe(expectedFileName) expect(actual.facets).toEqual(expectedFacetsFromFileOnly) + expect(actual.countPerObjectType.dataverses).toBe(0) + expect(actual.countPerObjectType.datasets).toBe(0) + expect(actual.countPerObjectType.files).toBe(1) }) test('should return error when collection does not exist', async () => { diff --git a/test/unit/collections/CollectionsRepository.test.ts b/test/unit/collections/CollectionsRepository.test.ts index d7a0af31..0c4bfb94 100644 --- a/test/unit/collections/CollectionsRepository.test.ts +++ b/test/unit/collections/CollectionsRepository.test.ts @@ -373,11 +373,17 @@ describe('CollectionsRepository', () => { ] const testTotalCount = 2 const testFacets = createCollectionItemsFacetsModel() + const testCountPerObjectType = { + dataverses: 0, + datasets: 1, + files: 1 + } const testItemSubset: CollectionItemSubset = { items: testItems, facets: testFacets, - totalItemCount: testTotalCount + totalItemCount: testTotalCount, + countPerObjectType: testCountPerObjectType } const testItemPreviewsResponse = { @@ -390,7 +396,12 @@ describe('CollectionsRepository', () => { createFilePreviewPayload(), createCollectionPreviewPayload() ], - facets: createCollectionItemsFacetsPayload() + facets: createCollectionItemsFacetsPayload(), + total_count_per_object_type: { + Dataverses: 0, + Datasets: 1, + Files: 1 + } } } } @@ -407,7 +418,8 @@ describe('CollectionsRepository', () => { [GetCollectionItemsQueryParams.QUERY]: '*', [GetCollectionItemsQueryParams.SHOW_FACETS]: 'true', [GetCollectionItemsQueryParams.SORT]: SortType.DATE, - [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC + [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC, + [GetCollectionItemsQueryParams.SHOW_TYPE_COUNTS]: 'true' }) const expectedRequestConfigApiKey = { @@ -452,6 +464,7 @@ describe('CollectionsRepository', () => { [GetCollectionItemsQueryParams.SHOW_FACETS]: 'true', [GetCollectionItemsQueryParams.SORT]: SortType.DATE, [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC, + [GetCollectionItemsQueryParams.SHOW_TYPE_COUNTS]: 'true', [GetCollectionItemsQueryParams.PER_PAGE]: testLimit.toString(), [GetCollectionItemsQueryParams.START]: testOffset.toString() }) @@ -499,6 +512,7 @@ describe('CollectionsRepository', () => { [GetCollectionItemsQueryParams.SHOW_FACETS]: 'true', [GetCollectionItemsQueryParams.SORT]: SortType.DATE, [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC, + [GetCollectionItemsQueryParams.SHOW_TYPE_COUNTS]: 'true', [GetCollectionItemsQueryParams.SUBTREE]: testCollectionId }) @@ -542,7 +556,8 @@ describe('CollectionsRepository', () => { [GetCollectionItemsQueryParams.QUERY]: '*', [GetCollectionItemsQueryParams.SHOW_FACETS]: 'true', [GetCollectionItemsQueryParams.SORT]: SortType.DATE, - [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC + [GetCollectionItemsQueryParams.ORDER]: OrderType.DESC, + [GetCollectionItemsQueryParams.SHOW_TYPE_COUNTS]: 'true' }) const expectedRequestConfigApiKey = { diff --git a/test/unit/collections/GetCollectionItems.test.ts b/test/unit/collections/GetCollectionItems.test.ts index 8c83ae95..a1eb9936 100644 --- a/test/unit/collections/GetCollectionItems.test.ts +++ b/test/unit/collections/GetCollectionItems.test.ts @@ -18,11 +18,17 @@ describe('execute', () => { ] const testTotalCount = 3 const testFacets = createCollectionItemsFacetsModel() + const testCountPerObjectType = { + dataverses: 1, + datasets: 1, + files: 1 + } const testItemSubset: CollectionItemSubset = { items: testItems, facets: testFacets, - totalItemCount: testTotalCount + totalItemCount: testTotalCount, + countPerObjectType: testCountPerObjectType } beforeEach(() => { From 4967fdb9e65e9b023f096ca39cbf6ff499d03fee Mon Sep 17 00:00:00 2001 From: German Gonzalo Saracca Date: Tue, 4 Feb 2025 11:48:11 +0000 Subject: [PATCH 3/4] chore: switch to unstable image in tests --- test/environment/.env | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/environment/.env b/test/environment/.env index 5cee3e2c..80e9a14e 100644 --- a/test/environment/.env +++ b/test/environment/.env @@ -1,6 +1,6 @@ POSTGRES_VERSION=13 DATAVERSE_DB_USER=dataverse SOLR_VERSION=9.3.0 -DATAVERSE_IMAGE_REGISTRY=ghcr.io -DATAVERSE_IMAGE_TAG=11127-search-api-counts +DATAVERSE_IMAGE_REGISTRY=docker.io +DATAVERSE_IMAGE_TAG=unstable DATAVERSE_BOOTSTRAP_TIMEOUT=5m From 1816259cbb23f0bbcbc29bff70fbed74e1242733 Mon Sep 17 00:00:00 2001 From: German Gonzalo Saracca Date: Tue, 4 Feb 2025 11:59:05 +0000 Subject: [PATCH 4/4] fix: update metadata blocks tests to match Dataverse configuration --- .../metadataBlocks/GetAllFacetableMetadataFields.test.ts | 2 +- test/functional/metadataBlocks/GetAllMetadataBlocks.test.ts | 2 +- .../integration/metadataBlocks/MetadataBlocksRepository.test.ts | 2 +- .../metadataBlocks/MetadataFieldsInfoRepository.test.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/functional/metadataBlocks/GetAllFacetableMetadataFields.test.ts b/test/functional/metadataBlocks/GetAllFacetableMetadataFields.test.ts index 7b290672..4258ca39 100644 --- a/test/functional/metadataBlocks/GetAllFacetableMetadataFields.test.ts +++ b/test/functional/metadataBlocks/GetAllFacetableMetadataFields.test.ts @@ -18,7 +18,7 @@ describe('execute', () => { } catch (error) { throw new Error('Should not raise an error') } finally { - expect(metadataFieldInfos.length).toBe(59) + expect(metadataFieldInfos.length).toBe(64) expect(metadataFieldInfos[0].name).toBe('authorName') expect(metadataFieldInfos[0].displayName).toBe('Author Name') } diff --git a/test/functional/metadataBlocks/GetAllMetadataBlocks.test.ts b/test/functional/metadataBlocks/GetAllMetadataBlocks.test.ts index 27c4ce7f..a1399675 100644 --- a/test/functional/metadataBlocks/GetAllMetadataBlocks.test.ts +++ b/test/functional/metadataBlocks/GetAllMetadataBlocks.test.ts @@ -19,7 +19,7 @@ describe('execute', () => { throw new Error('Should not raise an error') } finally { expect(metadataBlocks).not.toBeNull() - expect(metadataBlocks.length).toBe(6) + expect(metadataBlocks.length).toBe(7) expect(metadataBlocks[0].metadataFields.title.name).toBe('title') } }) diff --git a/test/integration/metadataBlocks/MetadataBlocksRepository.test.ts b/test/integration/metadataBlocks/MetadataBlocksRepository.test.ts index 3cf9a002..0adab583 100644 --- a/test/integration/metadataBlocks/MetadataBlocksRepository.test.ts +++ b/test/integration/metadataBlocks/MetadataBlocksRepository.test.ts @@ -59,7 +59,7 @@ describe('MetadataBlocksRepository', () => { describe('getAllMetadataBlocks', () => { test('should return all metadata blocks', async () => { const actual = await sut.getAllMetadataBlocks() - expect(actual.length).toBe(6) + expect(actual.length).toBe(7) expect(actual[0].name).toBe(citationMetadataBlockName) expect(actual[0].metadataFields.title.name).toBe('title') }) diff --git a/test/integration/metadataBlocks/MetadataFieldsInfoRepository.test.ts b/test/integration/metadataBlocks/MetadataFieldsInfoRepository.test.ts index ffd2e394..de94eb7c 100644 --- a/test/integration/metadataBlocks/MetadataFieldsInfoRepository.test.ts +++ b/test/integration/metadataBlocks/MetadataFieldsInfoRepository.test.ts @@ -19,7 +19,7 @@ describe('getAllFacetableMetadataFields', () => { test('should return all facetable metadata fields', async () => { const actual = await sut.getAllFacetableMetadataFields() - expect(actual.length).toBe(59) + expect(actual.length).toBe(64) expect(actual[0].name).toBe('authorName') expect(actual[0].displayName).toBe('Author Name') })