From 9a313b55d3166b6eafd30f0abf0eeeed1eccd64c Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 28 May 2025 16:55:07 +0100 Subject: [PATCH 01/18] Stash: GetSearchServices WIP --- src/search/domain/models/SearchService.ts | 4 ++++ .../repositories/ISearchServicesRepository.ts | 5 +++++ .../domain/useCases/GetSearchServices.ts | 20 +++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 src/search/domain/models/SearchService.ts create mode 100644 src/search/domain/repositories/ISearchServicesRepository.ts create mode 100644 src/search/domain/useCases/GetSearchServices.ts diff --git a/src/search/domain/models/SearchService.ts b/src/search/domain/models/SearchService.ts new file mode 100644 index 00000000..b895878e --- /dev/null +++ b/src/search/domain/models/SearchService.ts @@ -0,0 +1,4 @@ +export interface SearchService { + name: string + displayName: string +} diff --git a/src/search/domain/repositories/ISearchServicesRepository.ts b/src/search/domain/repositories/ISearchServicesRepository.ts new file mode 100644 index 00000000..f41a477a --- /dev/null +++ b/src/search/domain/repositories/ISearchServicesRepository.ts @@ -0,0 +1,5 @@ +import { SearchService } from '../models/SearchService' + +export interface ISearchServicesRepository { + getSearchServices(): Promise +} diff --git a/src/search/domain/useCases/GetSearchServices.ts b/src/search/domain/useCases/GetSearchServices.ts new file mode 100644 index 00000000..9fa0a0c0 --- /dev/null +++ b/src/search/domain/useCases/GetSearchServices.ts @@ -0,0 +1,20 @@ +import { UseCase } from '../../../core/domain/useCases/UseCase' +import { SearchService } from '../models/SearchService' +import { ISearchServicesRepository } from '../repositories/ISearchServicesRepository' + +export class GetSearchServices implements UseCase { + private searchServicesRepository: ISearchServicesRepository + + constructor(searchServicesRepository: ISearchServicesRepository) { + this.searchServicesRepository = searchServicesRepository + } + + /** + * Returns all search services available in the installation. + * + * @returns {Promise} + */ + async execute(): Promise { + return await this.searchServicesRepository.getSearchServices() + } +} From b0e2c665403caedaba7f8a01595a225d354fd3c4 Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 28 May 2025 17:02:51 +0100 Subject: [PATCH 02/18] Stash: SearchServicesRepository WIP --- src/search/index.ts | 8 ++++++++ .../infra/repositories/SearchServicesRepository.ts | 9 +++++++++ 2 files changed, 17 insertions(+) create mode 100644 src/search/index.ts create mode 100644 src/search/infra/repositories/SearchServicesRepository.ts diff --git a/src/search/index.ts b/src/search/index.ts new file mode 100644 index 00000000..3efd674e --- /dev/null +++ b/src/search/index.ts @@ -0,0 +1,8 @@ +import { GetSearchServices } from './domain/useCases/GetSearchServices' +import { SearchServicesRepository } from './infra/repositories/SearchServicesRepository' + +const searchServicesRepository = new SearchServicesRepository() + +const getSearchServices = new GetSearchServices(searchServicesRepository) + +export { getSearchServices } diff --git a/src/search/infra/repositories/SearchServicesRepository.ts b/src/search/infra/repositories/SearchServicesRepository.ts new file mode 100644 index 00000000..a1ea03e8 --- /dev/null +++ b/src/search/infra/repositories/SearchServicesRepository.ts @@ -0,0 +1,9 @@ +import { ApiRepository } from '../../../core/infra/repositories/ApiRepository' +import { SearchService } from '../../domain/models/SearchService' +import { ISearchServicesRepository } from '../../domain/repositories/ISearchServicesRepository' + +export class SearchServicesRepository extends ApiRepository implements ISearchServicesRepository { + public async getSearchServices(): Promise { + throw new Error('Method not implemented.') + } +} From e6dfcfdefb6f71b7b81f1b9cbf085d9fa1d5d827 Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 28 May 2025 17:31:02 +0100 Subject: [PATCH 03/18] Added: search services repository logic --- .../repositories/SearchServicesRepository.ts | 7 +++++- .../transformers/SearchServicePayload.ts | 4 ++++ .../transformers/searchServiceTransformers.ts | 24 +++++++++++++++++++ test/environment/.env | 2 +- .../search/SearchServicesRepository.test.ts | 24 +++++++++++++++++++ 5 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 src/search/infra/repositories/transformers/SearchServicePayload.ts create mode 100644 src/search/infra/repositories/transformers/searchServiceTransformers.ts create mode 100644 test/integration/search/SearchServicesRepository.test.ts diff --git a/src/search/infra/repositories/SearchServicesRepository.ts b/src/search/infra/repositories/SearchServicesRepository.ts index a1ea03e8..5c375f4a 100644 --- a/src/search/infra/repositories/SearchServicesRepository.ts +++ b/src/search/infra/repositories/SearchServicesRepository.ts @@ -1,9 +1,14 @@ import { ApiRepository } from '../../../core/infra/repositories/ApiRepository' import { SearchService } from '../../domain/models/SearchService' import { ISearchServicesRepository } from '../../domain/repositories/ISearchServicesRepository' +import { transformSearchServicesResponseToSearchServices } from './transformers/searchServiceTransformers' export class SearchServicesRepository extends ApiRepository implements ISearchServicesRepository { public async getSearchServices(): Promise { - throw new Error('Method not implemented.') + return this.doGet(`/searchServices/`) + .then((response) => transformSearchServicesResponseToSearchServices(response)) + .catch((error) => { + throw error + }) } } diff --git a/src/search/infra/repositories/transformers/SearchServicePayload.ts b/src/search/infra/repositories/transformers/SearchServicePayload.ts new file mode 100644 index 00000000..b5b45fc4 --- /dev/null +++ b/src/search/infra/repositories/transformers/SearchServicePayload.ts @@ -0,0 +1,4 @@ +export interface SearchServicePayload { + name: string + displayName: string +} diff --git a/src/search/infra/repositories/transformers/searchServiceTransformers.ts b/src/search/infra/repositories/transformers/searchServiceTransformers.ts new file mode 100644 index 00000000..722d9138 --- /dev/null +++ b/src/search/infra/repositories/transformers/searchServiceTransformers.ts @@ -0,0 +1,24 @@ +import { AxiosResponse } from 'axios' +import { SearchService } from '../../../domain/models/SearchService' +import { SearchServicePayload } from './SearchServicePayload' + +export const transformSearchServicesResponseToSearchServices = ( + response: AxiosResponse +): SearchService[] => { + const searchServicesPayload = response.data.data + const searchServices: SearchService[] = [] + searchServicesPayload.forEach(function (searchServicePayload: SearchServicePayload) { + searchServices.push(transformSearchServicePayloadToSearchService(searchServicePayload)) + }) + + return searchServices +} + +const transformSearchServicePayloadToSearchService = ( + searchServicePayload: SearchServicePayload +): SearchService => { + return { + name: searchServicePayload.name, + displayName: searchServicePayload.displayName + } +} diff --git a/test/environment/.env b/test/environment/.env index 0c691d9b..06f82c89 100644 --- a/test/environment/.env +++ b/test/environment/.env @@ -1,6 +1,6 @@ POSTGRES_VERSION=13 DATAVERSE_DB_USER=dataverse SOLR_VERSION=9.8.0 -DATAVERSE_IMAGE_REGISTRY=docker.io +DATAVERSE_IMAGE_REGISTRY=ghcr.io DATAVERSE_IMAGE_TAG=unstable DATAVERSE_BOOTSTRAP_TIMEOUT=5m diff --git a/test/integration/search/SearchServicesRepository.test.ts b/test/integration/search/SearchServicesRepository.test.ts new file mode 100644 index 00000000..829e0e5b --- /dev/null +++ b/test/integration/search/SearchServicesRepository.test.ts @@ -0,0 +1,24 @@ +import { ApiConfig } from '../../../src' +import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig' +import { SearchServicesRepository } from '../../../src/search/infra/repositories/SearchServicesRepository' +import { TestConstants } from '../../testHelpers/TestConstants' + +// TODO +describe.skip('SearchServicesRepository', () => { + const sut: SearchServicesRepository = new SearchServicesRepository() + + afterAll(async () => { + ApiConfig.init( + TestConstants.TEST_API_URL, + DataverseApiAuthMechanism.API_KEY, + process.env.TEST_API_KEY + ) + }) + + describe('getSearchServices', () => { + test('should return search services', async () => { + const actual = await sut.getSearchServices() + expect(actual.length).toEqual(2) + }) + }) +}) From 6eca761b1c06ca8c2f33af536458702243b02715 Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 28 May 2025 17:32:19 +0100 Subject: [PATCH 04/18] Fixed: search services endpoint --- src/search/infra/repositories/SearchServicesRepository.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search/infra/repositories/SearchServicesRepository.ts b/src/search/infra/repositories/SearchServicesRepository.ts index 5c375f4a..343fb686 100644 --- a/src/search/infra/repositories/SearchServicesRepository.ts +++ b/src/search/infra/repositories/SearchServicesRepository.ts @@ -5,7 +5,7 @@ import { transformSearchServicesResponseToSearchServices } from './transformers/ export class SearchServicesRepository extends ApiRepository implements ISearchServicesRepository { public async getSearchServices(): Promise { - return this.doGet(`/searchServices/`) + return this.doGet(`/search/services`) .then((response) => transformSearchServicesResponseToSearchServices(response)) .catch((error) => { throw error From 34cb64e41854a6e305952c3362b3be362f3a14c4 Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 28 May 2025 17:33:53 +0100 Subject: [PATCH 05/18] Changed: registry --- test/environment/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/environment/.env b/test/environment/.env index 06f82c89..0c691d9b 100644 --- a/test/environment/.env +++ b/test/environment/.env @@ -1,6 +1,6 @@ POSTGRES_VERSION=13 DATAVERSE_DB_USER=dataverse SOLR_VERSION=9.8.0 -DATAVERSE_IMAGE_REGISTRY=ghcr.io +DATAVERSE_IMAGE_REGISTRY=docker.io DATAVERSE_IMAGE_TAG=unstable DATAVERSE_BOOTSTRAP_TIMEOUT=5m From 05b99a70bada5c35907be3ddcd5613f27f78391f Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 28 May 2025 17:40:31 +0100 Subject: [PATCH 06/18] Changed: temporarily commented test steps in deploy_pr action --- .github/workflows/deploy_pr.yml | 69 +++++++++++++++++---------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/.github/workflows/deploy_pr.yml b/.github/workflows/deploy_pr.yml index f8cba6dd..183a254b 100644 --- a/.github/workflows/deploy_pr.yml +++ b/.github/workflows/deploy_pr.yml @@ -3,50 +3,51 @@ name: deploy_pr on: pull_request jobs: - test-unit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 19 + # test-unit: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v3 + # - uses: actions/setup-node@v3 + # with: + # node-version: 19 - - name: Install npm dependencies - run: npm ci + # - name: Install npm dependencies + # run: npm ci - - name: Run unit tests - run: npm run test:unit + # - name: Run unit tests + # run: npm run test:unit - test-integration: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 19 + # test-integration: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v3 + # - uses: actions/setup-node@v3 + # with: + # node-version: 19 - - name: Install npm dependencies - run: npm ci + # - name: Install npm dependencies + # run: npm ci - - name: Run integration tests - run: npm run test:integration + # - name: Run integration tests + # run: npm run test:integration - test-functional: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 19 + # test-functional: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v3 + # - uses: actions/setup-node@v3 + # with: + # node-version: 19 - - name: Install npm dependencies - run: npm ci + # - name: Install npm dependencies + # run: npm ci - - name: Run functional tests - run: npm run test:functional + # - name: Run functional tests + # run: npm run test:functional publish-gpr: - needs: [test-unit, test-integration, test-functional] + #needs: [test-unit, test-integration, test-functional] + needs: [] runs-on: ubuntu-latest permissions: packages: write From 566cc9e7ce8be612ecc4309ead9e8f1ae8a23419 Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 28 May 2025 17:47:21 +0100 Subject: [PATCH 07/18] Added: support for searchServiceName in getCollectionItems (testless) --- .../domain/repositories/ICollectionsRepository.ts | 3 ++- src/collections/domain/useCases/GetCollectionItems.ts | 8 +++++--- .../infra/repositories/CollectionsRepository.ts | 10 ++++++++-- test/unit/collections/GetCollectionItems.test.ts | 9 +++++++-- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/collections/domain/repositories/ICollectionsRepository.ts b/src/collections/domain/repositories/ICollectionsRepository.ts index c8fc6549..35b63fb0 100644 --- a/src/collections/domain/repositories/ICollectionsRepository.ts +++ b/src/collections/domain/repositories/ICollectionsRepository.ts @@ -25,7 +25,8 @@ export interface ICollectionsRepository { collectionId?: string, limit?: number, offset?: number, - collectionSearchCriteria?: CollectionSearchCriteria + collectionSearchCriteria?: CollectionSearchCriteria, + searchServiceName?: string ): Promise getMyDataCollectionItems( roleIds: number[], diff --git a/src/collections/domain/useCases/GetCollectionItems.ts b/src/collections/domain/useCases/GetCollectionItems.ts index aa3e2c55..3c4f2d54 100644 --- a/src/collections/domain/useCases/GetCollectionItems.ts +++ b/src/collections/domain/useCases/GetCollectionItems.ts @@ -10,7 +10,7 @@ export class GetCollectionItems implements UseCase { this.collectionsRepository = collectionsRepository } - /** + /** TODO: document searchServiceName * Returns an instance of CollectionItemSubset that contains reduced information for each item that the calling user can access in the installation. * If the collectionId parameter is not set, the use case will return items starting from the root collection. * @@ -24,13 +24,15 @@ export class GetCollectionItems implements UseCase { collectionId?: string, limit?: number, offset?: number, - collectionSearchCriteria?: CollectionSearchCriteria + collectionSearchCriteria?: CollectionSearchCriteria, + searchServiceName?: string ): Promise { return await this.collectionsRepository.getCollectionItems( collectionId, limit, offset, - collectionSearchCriteria + collectionSearchCriteria, + searchServiceName ) } } diff --git a/src/collections/infra/repositories/CollectionsRepository.ts b/src/collections/infra/repositories/CollectionsRepository.ts index 2be641b0..bfe33037 100644 --- a/src/collections/infra/repositories/CollectionsRepository.ts +++ b/src/collections/infra/repositories/CollectionsRepository.ts @@ -63,7 +63,8 @@ export enum GetCollectionItemsQueryParams { START = 'start', TYPE = 'type', FILTERQUERY = 'fq', - SHOW_TYPE_COUNTS = 'show_type_counts' + SHOW_TYPE_COUNTS = 'show_type_counts', + SEARCH_SERVICE_NAME = 'search_service' } export enum GetMyDataCollectionItemsQueryParams { @@ -155,7 +156,8 @@ export class CollectionsRepository extends ApiRepository implements ICollections collectionId?: string, limit?: number, offset?: number, - collectionSearchCriteria?: CollectionSearchCriteria + collectionSearchCriteria?: CollectionSearchCriteria, + searchServiceName?: string ): Promise { const queryParams = new URLSearchParams({ [GetCollectionItemsQueryParams.QUERY]: '*', @@ -177,6 +179,10 @@ export class CollectionsRepository extends ApiRepository implements ICollections queryParams.set(GetCollectionItemsQueryParams.START, offset.toString()) } + if (searchServiceName) { + queryParams.set(GetCollectionItemsQueryParams.SEARCH_SERVICE_NAME, searchServiceName) + } + if (collectionSearchCriteria) { this.applyCollectionSearchCriteriaToQueryParams(queryParams, collectionSearchCriteria) } diff --git a/test/unit/collections/GetCollectionItems.test.ts b/test/unit/collections/GetCollectionItems.test.ts index cf2e7448..adbeefa8 100644 --- a/test/unit/collections/GetCollectionItems.test.ts +++ b/test/unit/collections/GetCollectionItems.test.ts @@ -60,6 +60,7 @@ describe('execute', () => { collectionId, undefined, undefined, + undefined, undefined ) expect(actual).toEqual(testItemSubset) @@ -75,6 +76,7 @@ describe('execute', () => { undefined, limit, undefined, + undefined, undefined ) expect(actual).toEqual(testItemSubset) @@ -90,6 +92,7 @@ describe('execute', () => { undefined, undefined, offset, + undefined, undefined ) expect(actual).toEqual(testItemSubset) @@ -112,7 +115,8 @@ describe('execute', () => { undefined, undefined, undefined, - searchCriteria + searchCriteria, + undefined ) expect(actual).toEqual(testItemSubset) }) @@ -133,7 +137,8 @@ describe('execute', () => { collectionId, limit, offset, - searchCriteria + searchCriteria, + undefined ) expect(actual).toEqual(testItemSubset) }) From f042d8daaf1b0b83f7d8e81dcda5997e24a97861 Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 28 May 2025 18:03:27 +0100 Subject: [PATCH 08/18] Added: SCORE to SortType --- src/collections/domain/models/CollectionSearchCriteria.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/collections/domain/models/CollectionSearchCriteria.ts b/src/collections/domain/models/CollectionSearchCriteria.ts index 3f36735b..13454e43 100644 --- a/src/collections/domain/models/CollectionSearchCriteria.ts +++ b/src/collections/domain/models/CollectionSearchCriteria.ts @@ -2,7 +2,8 @@ import { CollectionItemType } from './CollectionItemType' export enum SortType { NAME = 'name', - DATE = 'date' + DATE = 'date', + SCORE = 'score' } export enum OrderType { From e29b28eae3f4d0624a35f87119a9639eea1aa4b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Saracca?= Date: Wed, 28 May 2025 14:25:23 -0300 Subject: [PATCH 09/18] export search module --- src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.ts b/src/index.ts index 2abdf089..823db36e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,3 +7,4 @@ export * from './collections' export * from './metadataBlocks' export * from './files' export * from './contactInfo' +export * from './search' From 0c891f8123d8d867d32794959c2357a478f65933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Saracca?= Date: Fri, 6 Jun 2025 11:56:58 -0300 Subject: [PATCH 10/18] keep showTypeCounts as last arg --- .../repositories/ICollectionsRepository.ts | 4 +-- .../domain/useCases/GetCollectionItems.ts | 8 ++--- .../repositories/CollectionsRepository.ts | 4 +-- .../collections/CollectionsRepository.test.ts | 1 + .../collections/GetCollectionItems.test.ts | 31 ++++++++++--------- 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/collections/domain/repositories/ICollectionsRepository.ts b/src/collections/domain/repositories/ICollectionsRepository.ts index 0653aad4..13d6feee 100644 --- a/src/collections/domain/repositories/ICollectionsRepository.ts +++ b/src/collections/domain/repositories/ICollectionsRepository.ts @@ -27,8 +27,8 @@ export interface ICollectionsRepository { limit?: number, offset?: number, collectionSearchCriteria?: CollectionSearchCriteria, - showTypeCounts?: boolean, - searchServiceName?: string + searchServiceName?: string, + showTypeCounts?: boolean ): Promise getMyDataCollectionItems( roleIds: number[], diff --git a/src/collections/domain/useCases/GetCollectionItems.ts b/src/collections/domain/useCases/GetCollectionItems.ts index 6c57cafc..504d8c7f 100644 --- a/src/collections/domain/useCases/GetCollectionItems.ts +++ b/src/collections/domain/useCases/GetCollectionItems.ts @@ -26,16 +26,16 @@ export class GetCollectionItems implements UseCase { limit?: number, offset?: number, collectionSearchCriteria?: CollectionSearchCriteria, - showTypeCounts = false, - searchServiceName?: string + searchServiceName?: string, + showTypeCounts = false ): Promise { return await this.collectionsRepository.getCollectionItems( collectionId, limit, offset, collectionSearchCriteria, - showTypeCounts, - searchServiceName + searchServiceName, + showTypeCounts ) } } diff --git a/src/collections/infra/repositories/CollectionsRepository.ts b/src/collections/infra/repositories/CollectionsRepository.ts index e2351909..59607298 100644 --- a/src/collections/infra/repositories/CollectionsRepository.ts +++ b/src/collections/infra/repositories/CollectionsRepository.ts @@ -158,8 +158,8 @@ export class CollectionsRepository extends ApiRepository implements ICollections limit?: number, offset?: number, collectionSearchCriteria?: CollectionSearchCriteria, - showTypeCounts?: boolean, - searchServiceName?: string + searchServiceName?: string, + showTypeCounts?: boolean ): Promise { const queryParams = new URLSearchParams({ [GetCollectionItemsQueryParams.QUERY]: '*', diff --git a/test/integration/collections/CollectionsRepository.test.ts b/test/integration/collections/CollectionsRepository.test.ts index b741537a..1c0bb714 100644 --- a/test/integration/collections/CollectionsRepository.test.ts +++ b/test/integration/collections/CollectionsRepository.test.ts @@ -771,6 +771,7 @@ describe('CollectionsRepository', () => { undefined, undefined, undefined, + undefined, true ) expect(actual.countPerObjectType?.collections).toBe(1) diff --git a/test/unit/collections/GetCollectionItems.test.ts b/test/unit/collections/GetCollectionItems.test.ts index e9c645c1..79159da7 100644 --- a/test/unit/collections/GetCollectionItems.test.ts +++ b/test/unit/collections/GetCollectionItems.test.ts @@ -55,8 +55,8 @@ describe('execute', () => { undefined, undefined, undefined, - false, - undefined + undefined, + false ) expect(actual).toEqual(testItemSubset) }) @@ -72,8 +72,8 @@ describe('execute', () => { limit, undefined, undefined, - false, - undefined + undefined, + false ) expect(actual).toEqual(testItemSubset) }) @@ -89,8 +89,8 @@ describe('execute', () => { undefined, offset, undefined, - false, - undefined + undefined, + false ) expect(actual).toEqual(testItemSubset) }) @@ -106,7 +106,7 @@ describe('execute', () => { undefined, undefined, searchCriteria, - false + undefined ) expect(collectionRepositoryStub.getCollectionItems).toHaveBeenCalledWith( @@ -114,8 +114,8 @@ describe('execute', () => { undefined, undefined, searchCriteria, - false, - undefined + undefined, + false ) expect(actual).toEqual(testItemSubset) }) @@ -140,6 +140,7 @@ describe('execute', () => { undefined, undefined, undefined, + undefined, showTypeCounts ) @@ -148,8 +149,8 @@ describe('execute', () => { undefined, undefined, undefined, - showTypeCounts, - undefined + undefined, + showTypeCounts ) expect(actual).toEqual(testItemSubsetWithCount) }) @@ -169,8 +170,8 @@ describe('execute', () => { limit, offset, searchCriteria, - false, - undefined + undefined, + false ) expect(collectionRepositoryStub.getCollectionItems).toHaveBeenCalledWith( @@ -178,8 +179,8 @@ describe('execute', () => { limit, offset, searchCriteria, - false, - undefined + undefined, + false ) expect(actual).toEqual(testItemSubset) }) From e03fa2154b0a3f9d9dd4e4c12cb1e674f5200eef Mon Sep 17 00:00:00 2001 From: GPortas Date: Fri, 11 Jul 2025 17:06:28 +0100 Subject: [PATCH 11/18] Changed: uncommented deploy_pr test steps --- .github/workflows/deploy_pr.yml | 69 ++++++++++++++++----------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/.github/workflows/deploy_pr.yml b/.github/workflows/deploy_pr.yml index 183a254b..f8cba6dd 100644 --- a/.github/workflows/deploy_pr.yml +++ b/.github/workflows/deploy_pr.yml @@ -3,51 +3,50 @@ name: deploy_pr on: pull_request jobs: - # test-unit: - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v3 - # - uses: actions/setup-node@v3 - # with: - # node-version: 19 + test-unit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 19 - # - name: Install npm dependencies - # run: npm ci + - name: Install npm dependencies + run: npm ci - # - name: Run unit tests - # run: npm run test:unit + - name: Run unit tests + run: npm run test:unit - # test-integration: - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v3 - # - uses: actions/setup-node@v3 - # with: - # node-version: 19 + test-integration: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 19 - # - name: Install npm dependencies - # run: npm ci + - name: Install npm dependencies + run: npm ci - # - name: Run integration tests - # run: npm run test:integration + - name: Run integration tests + run: npm run test:integration - # test-functional: - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v3 - # - uses: actions/setup-node@v3 - # with: - # node-version: 19 + test-functional: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 19 - # - name: Install npm dependencies - # run: npm ci + - name: Install npm dependencies + run: npm ci - # - name: Run functional tests - # run: npm run test:functional + - name: Run functional tests + run: npm run test:functional publish-gpr: - #needs: [test-unit, test-integration, test-functional] - needs: [] + needs: [test-unit, test-integration, test-functional] runs-on: ubuntu-latest permissions: packages: write From 4b5334c3ba86119849dc5c49151acdd7eaadbca8 Mon Sep 17 00:00:00 2001 From: GPortas Date: Tue, 15 Jul 2025 13:02:17 +0100 Subject: [PATCH 12/18] Added: missing docs for GetCollectionItems use case --- docs/useCases.md | 2 ++ src/collections/domain/useCases/GetCollectionItems.ts | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/useCases.md b/docs/useCases.md index 2ccee9fc..33c8f643 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -222,6 +222,8 @@ This use case supports the following optional parameters depending on the search - **limit**: (number) Limit for pagination. - **offset**: (number) Offset for pagination. - **collectionSearchCriteria**: ([CollectionSearchCriteria](../src/collections/domain/models/CollectionSearchCriteria.ts)) Supports filtering the collection items by different properties. +- **searchServiceName**: The search service name on which to execute the search (Optional). +- **showTypeCounts**: If true, the response will include the count per object type (Optional). #### List My Data Collection Items diff --git a/src/collections/domain/useCases/GetCollectionItems.ts b/src/collections/domain/useCases/GetCollectionItems.ts index 504d8c7f..2d8cd10b 100644 --- a/src/collections/domain/useCases/GetCollectionItems.ts +++ b/src/collections/domain/useCases/GetCollectionItems.ts @@ -10,7 +10,7 @@ export class GetCollectionItems implements UseCase { this.collectionsRepository = collectionsRepository } - /** TODO: document searchServiceName + /** * Returns an instance of CollectionItemSubset that contains reduced information for each item that the calling user can access in the installation. * If the collectionId parameter is not set, the use case will return items starting from the root collection. * @@ -18,6 +18,7 @@ export class GetCollectionItems implements UseCase { * @param {number} [limit] - Limit for pagination (optional). * @param {number} [offset] - Offset for pagination (optional). * @param {CollectionSearchCriteria} [collectionSearchCriteria] - Supports filtering the collection items by different properties (optional). + * @param {string} [searchServiceName] - The search service name on which to execute the search (optional). * @param {boolean} [showTypeCounts] - If true, the response will include the count per object type (optional). * @returns {Promise} */ From 4d61527a4f58c3035cace35b7492387080129f40 Mon Sep 17 00:00:00 2001 From: GPortas Date: Tue, 15 Jul 2025 13:09:25 +0100 Subject: [PATCH 13/18] Added: use case docs for GetSearchServices --- docs/useCases.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/useCases.md b/docs/useCases.md index 33c8f643..aa6b56f5 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -85,6 +85,8 @@ The different use cases currently available in the package are classified below, - [Get Application Terms of Use](#get-application-terms-of-use) - [Contact](#Contact) - [Send Feedback to Object Contacts](#send-feedback-to-object-contacts) +- [Search](#Search) + - [Get Search Services](#get-search-services) ## Collections @@ -1993,3 +1995,25 @@ In ContactDTO, it takes the following information: - **subject**: the email subject line. - **body**: the email body to send. - **fromEmail**: the email to list in the reply-to field. + +## Search + +#### Get Search Services + +Returns all [Search Services](../src/search/domain/models/SearchService.ts) available in the installation. + +##### Example call: + +```typescript +import { getSearchServices } from '@iqss/dataverse-client-javascript' + +/* ... */ + +getSearchServices.execute().then((searchServices: SearchService[]) => { + /* ... */ +}) + +/* ... */ +``` + +_See [use case](../src/search/domain/useCases/GetSearchServices.ts) implementation_. From c355cab14edacf4187bac6c4b9e9e602a50208a8 Mon Sep 17 00:00:00 2001 From: GPortas Date: Tue, 15 Jul 2025 13:15:38 +0100 Subject: [PATCH 14/18] Added: unit tests for GetSearchServices use case --- .../testHelpers/search/searchServiceHelper.ts | 8 ++++++ test/unit/search/GetSearchServices.test.ts | 25 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 test/testHelpers/search/searchServiceHelper.ts create mode 100644 test/unit/search/GetSearchServices.test.ts diff --git a/test/testHelpers/search/searchServiceHelper.ts b/test/testHelpers/search/searchServiceHelper.ts new file mode 100644 index 00000000..b8e1f255 --- /dev/null +++ b/test/testHelpers/search/searchServiceHelper.ts @@ -0,0 +1,8 @@ +import { SearchService } from "../../../src/search/domain/models/SearchService" + +export const createSearchServiceModelArray = (count: number): SearchService[] => { + return Array.from({ length: count }, (_, index) => ({ + name: `role${index + 1}`, + displayName: `Role ${index + 1}`, + })) +} diff --git a/test/unit/search/GetSearchServices.test.ts b/test/unit/search/GetSearchServices.test.ts new file mode 100644 index 00000000..ea3e9a1b --- /dev/null +++ b/test/unit/search/GetSearchServices.test.ts @@ -0,0 +1,25 @@ +import { ReadError } from '../../../src' +import { ISearchServicesRepository } from '../../../src/search/domain/repositories/ISearchServicesRepository' +import { GetSearchServices } from '../../../src/search/domain/useCases/GetSearchServices' +import { createSearchServiceModelArray } from '../../testHelpers/search/searchServiceHelper' + +describe('execute', () => { + test('should return search services array on repository success', async () => { + const searchServicesRepositoryStub: ISearchServicesRepository = {} as ISearchServicesRepository + const testServices = createSearchServiceModelArray(5) + searchServicesRepositoryStub.getSearchServices = jest.fn().mockResolvedValue(testServices) + const sut = new GetSearchServices(searchServicesRepositoryStub) + + const actual = await sut.execute() + + expect(actual).toEqual(testServices) + }) + + test('should return error result on repository error', async () => { + const searchServicesRepositoryStub: ISearchServicesRepository = {} as ISearchServicesRepository + searchServicesRepositoryStub.getSearchServices = jest.fn().mockRejectedValue(new ReadError()) + const sut = new GetSearchServices(searchServicesRepositoryStub) + + await expect(sut.execute()).rejects.toThrow(ReadError) + }) +}) From 7dbd02d6cf706bf9e82e2942a9ff6269be56f514 Mon Sep 17 00:00:00 2001 From: GPortas Date: Tue, 15 Jul 2025 13:25:07 +0100 Subject: [PATCH 15/18] Added: reformat --- .../repositories/transformers/searchServiceTransformers.ts | 1 + test/integration/search/SearchServicesRepository.test.ts | 3 +-- test/testHelpers/search/searchServiceHelper.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/search/infra/repositories/transformers/searchServiceTransformers.ts b/src/search/infra/repositories/transformers/searchServiceTransformers.ts index 722d9138..b89c881d 100644 --- a/src/search/infra/repositories/transformers/searchServiceTransformers.ts +++ b/src/search/infra/repositories/transformers/searchServiceTransformers.ts @@ -5,6 +5,7 @@ import { SearchServicePayload } from './SearchServicePayload' export const transformSearchServicesResponseToSearchServices = ( response: AxiosResponse ): SearchService[] => { + console.log(response) const searchServicesPayload = response.data.data const searchServices: SearchService[] = [] searchServicesPayload.forEach(function (searchServicePayload: SearchServicePayload) { diff --git a/test/integration/search/SearchServicesRepository.test.ts b/test/integration/search/SearchServicesRepository.test.ts index 829e0e5b..9b4b302b 100644 --- a/test/integration/search/SearchServicesRepository.test.ts +++ b/test/integration/search/SearchServicesRepository.test.ts @@ -3,8 +3,7 @@ import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ import { SearchServicesRepository } from '../../../src/search/infra/repositories/SearchServicesRepository' import { TestConstants } from '../../testHelpers/TestConstants' -// TODO -describe.skip('SearchServicesRepository', () => { +describe('SearchServicesRepository', () => { const sut: SearchServicesRepository = new SearchServicesRepository() afterAll(async () => { diff --git a/test/testHelpers/search/searchServiceHelper.ts b/test/testHelpers/search/searchServiceHelper.ts index b8e1f255..afa55193 100644 --- a/test/testHelpers/search/searchServiceHelper.ts +++ b/test/testHelpers/search/searchServiceHelper.ts @@ -1,8 +1,8 @@ -import { SearchService } from "../../../src/search/domain/models/SearchService" +import { SearchService } from '../../../src/search/domain/models/SearchService' export const createSearchServiceModelArray = (count: number): SearchService[] => { return Array.from({ length: count }, (_, index) => ({ name: `role${index + 1}`, - displayName: `Role ${index + 1}`, + displayName: `Role ${index + 1}` })) } From 439aa62deb49a4d40c927edcf602f3cf3072eb8f Mon Sep 17 00:00:00 2001 From: GPortas Date: Tue, 15 Jul 2025 13:50:48 +0100 Subject: [PATCH 16/18] Stash: SearchServicesRepository IT WIP --- .../repositories/transformers/searchServiceTransformers.ts | 1 - test/integration/search/SearchServicesRepository.test.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/search/infra/repositories/transformers/searchServiceTransformers.ts b/src/search/infra/repositories/transformers/searchServiceTransformers.ts index b89c881d..722d9138 100644 --- a/src/search/infra/repositories/transformers/searchServiceTransformers.ts +++ b/src/search/infra/repositories/transformers/searchServiceTransformers.ts @@ -5,7 +5,6 @@ import { SearchServicePayload } from './SearchServicePayload' export const transformSearchServicesResponseToSearchServices = ( response: AxiosResponse ): SearchService[] => { - console.log(response) const searchServicesPayload = response.data.data const searchServices: SearchService[] = [] searchServicesPayload.forEach(function (searchServicePayload: SearchServicePayload) { diff --git a/test/integration/search/SearchServicesRepository.test.ts b/test/integration/search/SearchServicesRepository.test.ts index 9b4b302b..3e971d2c 100644 --- a/test/integration/search/SearchServicesRepository.test.ts +++ b/test/integration/search/SearchServicesRepository.test.ts @@ -6,7 +6,7 @@ import { TestConstants } from '../../testHelpers/TestConstants' describe('SearchServicesRepository', () => { const sut: SearchServicesRepository = new SearchServicesRepository() - afterAll(async () => { + beforeAll(async () => { ApiConfig.init( TestConstants.TEST_API_URL, DataverseApiAuthMechanism.API_KEY, From 84350c6f06fe1bfd6ca119edb48b066539f44be9 Mon Sep 17 00:00:00 2001 From: GPortas Date: Tue, 15 Jul 2025 18:07:33 +0100 Subject: [PATCH 17/18] Added: missing search services tests --- .../transformers/searchServiceTransformers.ts | 2 +- .../search/GetSearchServices.test.ts | 23 +++++++++++++++++++ .../search/SearchServicesRepository.test.ts | 4 +++- 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 test/functional/search/GetSearchServices.test.ts diff --git a/src/search/infra/repositories/transformers/searchServiceTransformers.ts b/src/search/infra/repositories/transformers/searchServiceTransformers.ts index 722d9138..2d379e7c 100644 --- a/src/search/infra/repositories/transformers/searchServiceTransformers.ts +++ b/src/search/infra/repositories/transformers/searchServiceTransformers.ts @@ -5,7 +5,7 @@ import { SearchServicePayload } from './SearchServicePayload' export const transformSearchServicesResponseToSearchServices = ( response: AxiosResponse ): SearchService[] => { - const searchServicesPayload = response.data.data + const searchServicesPayload = response.data.data.services const searchServices: SearchService[] = [] searchServicesPayload.forEach(function (searchServicePayload: SearchServicePayload) { searchServices.push(transformSearchServicePayloadToSearchService(searchServicePayload)) diff --git a/test/functional/search/GetSearchServices.test.ts b/test/functional/search/GetSearchServices.test.ts new file mode 100644 index 00000000..af70aae9 --- /dev/null +++ b/test/functional/search/GetSearchServices.test.ts @@ -0,0 +1,23 @@ +import { ApiConfig, getSearchServices } from '../../../src' +import { TestConstants } from '../../testHelpers/TestConstants' +import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig' +import { SearchService } from '../../../src/search/domain/models/SearchService' + +describe('execute', () => { + beforeEach(async () => { + ApiConfig.init( + TestConstants.TEST_API_URL, + DataverseApiAuthMechanism.API_KEY, + process.env.TEST_API_KEY + ) + }) + + test('should successfully return search services', async () => { + const searchServices: SearchService[] = await getSearchServices.execute() + + expect(searchServices).toBeDefined() + expect(searchServices.length).toBe(1) + expect(searchServices[0].name).toBe('solr') + expect(searchServices[0].displayName).toBe('Dataverse Standard Search') + }) +}) diff --git a/test/integration/search/SearchServicesRepository.test.ts b/test/integration/search/SearchServicesRepository.test.ts index 3e971d2c..198eb0b3 100644 --- a/test/integration/search/SearchServicesRepository.test.ts +++ b/test/integration/search/SearchServicesRepository.test.ts @@ -17,7 +17,9 @@ describe('SearchServicesRepository', () => { describe('getSearchServices', () => { test('should return search services', async () => { const actual = await sut.getSearchServices() - expect(actual.length).toEqual(2) + expect(actual.length).toEqual(1) + expect(actual[0].name).toEqual('solr') + expect(actual[0].displayName).toEqual('Dataverse Standard Search') }) }) }) From 011c4adf97d7285e7898da875e5f0b42b32bc786 Mon Sep 17 00:00:00 2001 From: GPortas Date: Tue, 15 Jul 2025 18:12:01 +0100 Subject: [PATCH 18/18] Added: missing export in search subdomain --- src/search/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/search/index.ts b/src/search/index.ts index 3efd674e..56735ae0 100644 --- a/src/search/index.ts +++ b/src/search/index.ts @@ -6,3 +6,5 @@ const searchServicesRepository = new SearchServicesRepository() const getSearchServices = new GetSearchServices(searchServicesRepository) export { getSearchServices } + +export { SearchService } from './domain/models/SearchService'