From bc026243af8f78cd7936fe2f15e1b53c4e52e8e3 Mon Sep 17 00:00:00 2001 From: GPortas Date: Tue, 22 Oct 2024 15:08:08 +0100 Subject: [PATCH 1/6] Added: UpdateCollection use case (pending data access logic) --- .../repositories/ICollectionsRepository.ts | 4 +++ .../domain/useCases/UpdateCollection.ts | 26 +++++++++++++++++ src/collections/index.ts | 5 +++- .../repositories/CollectionsRepository.ts | 7 +++++ .../unit/collections/UpdateCollection.test.ts | 28 +++++++++++++++++++ 5 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/collections/domain/useCases/UpdateCollection.ts create mode 100644 test/unit/collections/UpdateCollection.test.ts diff --git a/src/collections/domain/repositories/ICollectionsRepository.ts b/src/collections/domain/repositories/ICollectionsRepository.ts index d5812852..c024779a 100644 --- a/src/collections/domain/repositories/ICollectionsRepository.ts +++ b/src/collections/domain/repositories/ICollectionsRepository.ts @@ -22,4 +22,8 @@ export interface ICollectionsRepository { offset?: number, collectionSearchCriteria?: CollectionSearchCriteria ): Promise + updateCollection( + collectionIdOrAlias: number | string, + updatedCollection: CollectionDTO + ): Promise } diff --git a/src/collections/domain/useCases/UpdateCollection.ts b/src/collections/domain/useCases/UpdateCollection.ts new file mode 100644 index 00000000..f1068086 --- /dev/null +++ b/src/collections/domain/useCases/UpdateCollection.ts @@ -0,0 +1,26 @@ +import { UseCase } from '../../../core/domain/useCases/UseCase' +import { CollectionDTO } from '../dtos/CollectionDTO' +import { ICollectionsRepository } from '../repositories/ICollectionsRepository' + +export class UpdateCollection implements UseCase { + private collectionsRepository: ICollectionsRepository + + constructor(collectionsRepository: ICollectionsRepository) { + this.collectionsRepository = collectionsRepository + } + + /** + * Updates an existing collection, given a collection identifier and a CollectionDTO including the updated collection data. + * + * @param {number | string} [collectionIdOrAlias] - A generic collection identifier, which can be either a string (for queries by CollectionAlias), or a number (for queries by CollectionId) + * @param {CollectionDTO} [newCollection] - CollectionDTO object including the updated collection data. + * @returns {Promise} -This method does not return anything upon successful completion. + * @throws {WriteError} - If there are errors while writing data. + */ + async execute( + collectionIdOrAlias: number | string, + updatedCollection: CollectionDTO + ): Promise { + return await this.collectionsRepository.updateCollection(collectionIdOrAlias, updatedCollection) + } +} diff --git a/src/collections/index.ts b/src/collections/index.ts index 02b68df1..b148b55d 100644 --- a/src/collections/index.ts +++ b/src/collections/index.ts @@ -4,6 +4,7 @@ import { GetCollectionFacets } from './domain/useCases/GetCollectionFacets' import { GetCollectionUserPermissions } from './domain/useCases/GetCollectionUserPermissions' import { GetCollectionItems } from './domain/useCases/GetCollectionItems' import { PublishCollection } from './domain/useCases/PublishCollection' +import { UpdateCollection } from './domain/useCases/UpdateCollection' import { CollectionsRepository } from './infra/repositories/CollectionsRepository' @@ -15,6 +16,7 @@ const getCollectionFacets = new GetCollectionFacets(collectionsRepository) const getCollectionUserPermissions = new GetCollectionUserPermissions(collectionsRepository) const getCollectionItems = new GetCollectionItems(collectionsRepository) const publishCollection = new PublishCollection(collectionsRepository) +const updateCollection = new UpdateCollection(collectionsRepository) export { getCollection, @@ -22,7 +24,8 @@ export { getCollectionFacets, getCollectionUserPermissions, getCollectionItems, - publishCollection + publishCollection, + updateCollection } export { Collection, CollectionInputLevel } from './domain/models/Collection' export { CollectionFacet } from './domain/models/CollectionFacet' diff --git a/src/collections/infra/repositories/CollectionsRepository.ts b/src/collections/infra/repositories/CollectionsRepository.ts index 167a749e..fd77323e 100644 --- a/src/collections/infra/repositories/CollectionsRepository.ts +++ b/src/collections/infra/repositories/CollectionsRepository.ts @@ -185,6 +185,13 @@ export class CollectionsRepository extends ApiRepository implements ICollections }) } + public updateCollection( + collectionIdOrAlias: string | number, + updatedCollection: CollectionDTO + ): Promise { + throw new Error('Method not implemented ' + collectionIdOrAlias + ' ' + updatedCollection.alias) + } + private applyCollectionSearchCriteriaToQueryParams( queryParams: GetCollectionItemsQueryParams, collectionSearchCriteria: CollectionSearchCriteria diff --git a/test/unit/collections/UpdateCollection.test.ts b/test/unit/collections/UpdateCollection.test.ts new file mode 100644 index 00000000..60d734d6 --- /dev/null +++ b/test/unit/collections/UpdateCollection.test.ts @@ -0,0 +1,28 @@ +import { UpdateCollection } from '../../../src/collections/domain/useCases/UpdateCollection' +import { createCollectionDTO } from '../../testHelpers/collections/collectionHelper' +import { WriteError } from '../../../src' +import { ICollectionsRepository } from '../../../src/collections/domain/repositories/ICollectionsRepository' + +describe('execute', () => { + const testCollection = createCollectionDTO() + + test('should return undefined when repository call is successful', async () => { + const collectionsRepositoryStub = {} + collectionsRepositoryStub.updateCollection = jest.fn().mockResolvedValue(undefined) + + const sut = new UpdateCollection(collectionsRepositoryStub) + + const actual = await sut.execute(1, testCollection) + + expect(actual).toEqual(undefined) + }) + + test('should throw WriteError when the repository raises an error', async () => { + const collectionsRepositoryStub = {} + const testWriteError = new WriteError('Test error') + collectionsRepositoryStub.updateCollection = jest.fn().mockRejectedValue(testWriteError) + + const sut = new UpdateCollection(collectionsRepositoryStub) + await expect(sut.execute(1, testCollection)).rejects.toThrow(testWriteError) + }) +}) From 0beeb41a23ed606ef76ac5a910c1d68a3dc31264 Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 23 Oct 2024 10:23:48 +0100 Subject: [PATCH 2/6] Added: updateCollection use case data access (pending refactor) --- .../repositories/CollectionsRepository.ts | 39 +++++++++++- test/environment/.env | 4 +- .../collections/CollectionsRepository.test.ts | 63 +++++++++++++++++++ .../collections/CollectionsRepository.test.ts | 58 +++++++++++++++++ 4 files changed, 160 insertions(+), 4 deletions(-) diff --git a/src/collections/infra/repositories/CollectionsRepository.ts b/src/collections/infra/repositories/CollectionsRepository.ts index fd77323e..99f3e54b 100644 --- a/src/collections/infra/repositories/CollectionsRepository.ts +++ b/src/collections/infra/repositories/CollectionsRepository.ts @@ -185,11 +185,46 @@ export class CollectionsRepository extends ApiRepository implements ICollections }) } - public updateCollection( + public async updateCollection( collectionIdOrAlias: string | number, updatedCollection: CollectionDTO ): Promise { - throw new Error('Method not implemented ' + collectionIdOrAlias + ' ' + updatedCollection.alias) + const dataverseContacts: NewCollectionContactRequestPayload[] = updatedCollection.contacts.map( + (contact) => ({ + contactEmail: contact + }) + ) + + const inputLevelsRequestBody: NewCollectionInputLevelRequestPayload[] = + updatedCollection.inputLevels?.map((inputLevel) => ({ + datasetFieldTypeName: inputLevel.datasetFieldName, + include: inputLevel.include, + required: inputLevel.required + })) + + const requestBody: NewCollectionRequestPayload = { + alias: updatedCollection.alias, + name: updatedCollection.name, + dataverseContacts: dataverseContacts, + dataverseType: updatedCollection.type, + ...(updatedCollection.description && { + description: updatedCollection.description + }), + ...(updatedCollection.affiliation && { + affiliation: updatedCollection.affiliation + }), + metadataBlocks: { + metadataBlockNames: updatedCollection.metadataBlockNames, + facetIds: updatedCollection.facetIds, + inputLevels: inputLevelsRequestBody + } + } + + return this.doPut(`/${this.collectionsResourceName}/${collectionIdOrAlias}`, requestBody) + .then(() => undefined) + .catch((error) => { + throw error + }) } private applyCollectionSearchCriteriaToQueryParams( diff --git a/test/environment/.env b/test/environment/.env index 80e9a14e..6e32dcbb 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=10904-edit-dataverse-collection DATAVERSE_BOOTSTRAP_TIMEOUT=5m diff --git a/test/integration/collections/CollectionsRepository.test.ts b/test/integration/collections/CollectionsRepository.test.ts index be293662..e77245ef 100644 --- a/test/integration/collections/CollectionsRepository.test.ts +++ b/test/integration/collections/CollectionsRepository.test.ts @@ -464,4 +464,67 @@ describe('CollectionsRepository', () => { ).rejects.toThrow(expectedError) }) }) + + describe('updateCollection', () => { + const testUpdatedCollectionAlias = 'updateCollection-test-updatedAlias' + + afterAll(async () => { + await deleteCollectionViaApi(testUpdatedCollectionAlias) + }) + + test('should update the collection', async () => { + // First we create a test collection using a CollectionDTO and createCollection method + const collectionDTO = createCollectionDTO('updatedCollection-test-originalAlias') + const testUpdateCollectionId = await sut.createCollection(collectionDTO) + const createdCollection = await sut.getCollection(testUpdateCollectionId) + expect(createdCollection.id).toBe(testUpdateCollectionId) + expect(createdCollection.alias).toBe(collectionDTO.alias) + expect(createdCollection.name).toBe(collectionDTO.name) + expect(createdCollection.affiliation).toBe(collectionDTO.affiliation) + expect(createdCollection.inputLevels?.length).toBe(1) + const inputLevel = createdCollection.inputLevels?.[0] + expect(inputLevel?.datasetFieldName).toBe('geographicCoverage') + expect(inputLevel?.include).toBe(true) + expect(inputLevel?.required).toBe(true) + + // Now we update CollectionDTO and verify updates are correctly persisted after calling updateCollection method + collectionDTO.alias = testUpdatedCollectionAlias + const updatedCollectionName = 'updatedCollectionName' + collectionDTO.name = updatedCollectionName + const updatedCollectionAffiliation = 'updatedCollectionAffiliation' + collectionDTO.affiliation = updatedCollectionAffiliation + const updatedInputLevels = [ + { + datasetFieldName: 'country', + required: false, + include: true + } + ] + collectionDTO.inputLevels = updatedInputLevels + await sut.updateCollection(testUpdateCollectionId, collectionDTO) + const updatedCollection = await sut.getCollection(testUpdateCollectionId) + expect(updatedCollection.id).toBe(testUpdateCollectionId) + expect(updatedCollection.alias).toBe(testUpdatedCollectionAlias) + expect(updatedCollection.name).toBe(updatedCollectionName) + expect(updatedCollection.affiliation).toBe(updatedCollectionAffiliation) + expect(updatedCollection.inputLevels?.length).toBe(1) + const updatedInputLevel = updatedCollection.inputLevels?.[0] + expect(updatedInputLevel?.datasetFieldName).toBe('country') + expect(updatedInputLevel?.include).toBe(true) + expect(updatedInputLevel?.required).toBe(false) + }) + + test('should return error when collection does not exist', async () => { + const expectedError = new WriteError( + `[404] Can't find dataverse with identifier='${TestConstants.TEST_DUMMY_COLLECTION_ID}'` + ) + const testCollectionAlias = 'updateCollection-not-found-test' + await expect( + sut.updateCollection( + TestConstants.TEST_DUMMY_COLLECTION_ID, + createCollectionDTO(testCollectionAlias) + ) + ).rejects.toThrow(expectedError) + }) + }) }) diff --git a/test/unit/collections/CollectionsRepository.test.ts b/test/unit/collections/CollectionsRepository.test.ts index c1bdf958..ecad1c4c 100644 --- a/test/unit/collections/CollectionsRepository.test.ts +++ b/test/unit/collections/CollectionsRepository.test.ts @@ -191,6 +191,64 @@ describe('CollectionsRepository', () => { }) }) + describe('updateCollection', () => { + const testUpdatedCollection = createCollectionDTO() + const testAlias = 'testCollectionAlias' + + const testCreatedCollectionId = 1 + const testCreateCollectionResponse = { + data: { + status: 'OK', + data: { + id: testCreatedCollectionId + } + } + } + + const expectedUpdatedCollectionRequestPayloadJson = JSON.stringify( + createNewCollectionRequestPayload() + ) + const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/dataverses/${testAlias}` + + test('should call the API with a correct request payload', async () => { + jest.spyOn(axios, 'put').mockResolvedValue(testCreateCollectionResponse) + + // API Key auth + await sut.updateCollection(testAlias, testUpdatedCollection) + + expect(axios.put).toHaveBeenCalledWith( + expectedApiEndpoint, + expectedUpdatedCollectionRequestPayloadJson, + TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY + ) + + // Session cookie auth + ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.SESSION_COOKIE) + + await sut.updateCollection(testAlias, testUpdatedCollection) + + expect(axios.put).toHaveBeenCalledWith( + expectedApiEndpoint, + expectedUpdatedCollectionRequestPayloadJson, + TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE + ) + }) + + test('should return error result on error response', async () => { + jest.spyOn(axios, 'put').mockRejectedValue(TestConstants.TEST_ERROR_RESPONSE) + + let error = undefined as unknown as WriteError + await sut.updateCollection(testAlias, testUpdatedCollection).catch((e) => (error = e)) + + expect(axios.put).toHaveBeenCalledWith( + expectedApiEndpoint, + expectedUpdatedCollectionRequestPayloadJson, + TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY + ) + expect(error).toBeInstanceOf(Error) + }) + }) + describe('getCollectionFacets', () => { const testFacetsSuccessfulResponse = { data: { From 08a0f06474f758809df993fb5b060924c19f8bea Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 23 Oct 2024 10:33:18 +0100 Subject: [PATCH 3/6] Refactor: CollectionsRepository --- .../repositories/CollectionsRepository.ts | 85 ++++++------------- 1 file changed, 27 insertions(+), 58 deletions(-) diff --git a/src/collections/infra/repositories/CollectionsRepository.ts b/src/collections/infra/repositories/CollectionsRepository.ts index 99f3e54b..263b9399 100644 --- a/src/collections/infra/repositories/CollectionsRepository.ts +++ b/src/collections/infra/repositories/CollectionsRepository.ts @@ -67,42 +67,13 @@ export class CollectionsRepository extends ApiRepository implements ICollections collectionDTO: CollectionDTO, parentCollectionId: number | string = ROOT_COLLECTION_ALIAS ): Promise { - const dataverseContacts: NewCollectionContactRequestPayload[] = collectionDTO.contacts.map( - (contact) => ({ - contactEmail: contact - }) - ) - - const inputLevelsRequestBody: NewCollectionInputLevelRequestPayload[] = - collectionDTO.inputLevels?.map((inputLevel) => ({ - datasetFieldTypeName: inputLevel.datasetFieldName, - include: inputLevel.include, - required: inputLevel.required - })) - - const requestBody: NewCollectionRequestPayload = { - alias: collectionDTO.alias, - name: collectionDTO.name, - dataverseContacts: dataverseContacts, - dataverseType: collectionDTO.type, - ...(collectionDTO.description && { - description: collectionDTO.description - }), - ...(collectionDTO.affiliation && { - affiliation: collectionDTO.affiliation - }), - metadataBlocks: { - metadataBlockNames: collectionDTO.metadataBlockNames, - facetIds: collectionDTO.facetIds, - inputLevels: inputLevelsRequestBody - } - } + const requestBody = this.createCreateOrUpdateRequestBody(collectionDTO); return this.doPost(`/${this.collectionsResourceName}/${parentCollectionId}`, requestBody) .then((response) => response.data.data.id) .catch((error) => { - throw error - }) + throw error; + }); } public async getCollectionFacets( @@ -189,42 +160,40 @@ export class CollectionsRepository extends ApiRepository implements ICollections collectionIdOrAlias: string | number, updatedCollection: CollectionDTO ): Promise { - const dataverseContacts: NewCollectionContactRequestPayload[] = updatedCollection.contacts.map( - (contact) => ({ - contactEmail: contact - }) - ) + const requestBody = this.createCreateOrUpdateRequestBody(updatedCollection); + + return this.doPut(`/${this.collectionsResourceName}/${collectionIdOrAlias}`, requestBody) + .then(() => undefined) + .catch((error) => { + throw error; + }); + } + + private createCreateOrUpdateRequestBody(collectionDTO: CollectionDTO): NewCollectionRequestPayload { + const dataverseContacts: NewCollectionContactRequestPayload[] = collectionDTO.contacts.map((contact) => ({ + contactEmail: contact + })); const inputLevelsRequestBody: NewCollectionInputLevelRequestPayload[] = - updatedCollection.inputLevels?.map((inputLevel) => ({ + collectionDTO.inputLevels?.map((inputLevel) => ({ datasetFieldTypeName: inputLevel.datasetFieldName, include: inputLevel.include, required: inputLevel.required - })) + })); - const requestBody: NewCollectionRequestPayload = { - alias: updatedCollection.alias, - name: updatedCollection.name, + return { + alias: collectionDTO.alias, + name: collectionDTO.name, dataverseContacts: dataverseContacts, - dataverseType: updatedCollection.type, - ...(updatedCollection.description && { - description: updatedCollection.description - }), - ...(updatedCollection.affiliation && { - affiliation: updatedCollection.affiliation - }), + dataverseType: collectionDTO.type, + ...(collectionDTO.description && { description: collectionDTO.description }), + ...(collectionDTO.affiliation && { affiliation: collectionDTO.affiliation }), metadataBlocks: { - metadataBlockNames: updatedCollection.metadataBlockNames, - facetIds: updatedCollection.facetIds, + metadataBlockNames: collectionDTO.metadataBlockNames, + facetIds: collectionDTO.facetIds, inputLevels: inputLevelsRequestBody } - } - - return this.doPut(`/${this.collectionsResourceName}/${collectionIdOrAlias}`, requestBody) - .then(() => undefined) - .catch((error) => { - throw error - }) + }; } private applyCollectionSearchCriteriaToQueryParams( From 78331c01dcbb94d9c3b0366d2e713dd1d7320450 Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 23 Oct 2024 10:55:21 +0100 Subject: [PATCH 4/6] Added: UpdateCollection functional test --- .../collections/UpdateCollection.test.ts | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 test/functional/collections/UpdateCollection.test.ts diff --git a/test/functional/collections/UpdateCollection.test.ts b/test/functional/collections/UpdateCollection.test.ts new file mode 100644 index 00000000..cffec841 --- /dev/null +++ b/test/functional/collections/UpdateCollection.test.ts @@ -0,0 +1,48 @@ +import { ApiConfig, WriteError, createCollection, getCollection, updateCollection } from '../../../src' +import { TestConstants } from '../../testHelpers/TestConstants' +import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig' +import { createCollectionDTO } from '../../testHelpers/collections/collectionHelper' + +describe('execute', () => { + beforeEach(async () => { + ApiConfig.init( + TestConstants.TEST_API_URL, + DataverseApiAuthMechanism.API_KEY, + process.env.TEST_API_KEY + ) + }) + + test('should successfully update a new collection', async () => { + const testNewCollectionAlias = 'updateCollection-functional-test' + const testNewCollection = createCollectionDTO(testNewCollectionAlias) + await createCollection.execute(testNewCollection) + const testNewName = 'Updated Name' + testNewCollection.name = testNewName + expect.assertions(1) + try { + await updateCollection.execute(testNewCollectionAlias, testNewCollection) + } catch (error) { + throw new Error('Collection should be updated') + } finally { + const updatedCollection = await getCollection.execute(testNewCollectionAlias) + expect(updatedCollection.name).toBe(testNewName) + } + }) + + test('should throw an error when the parent collection does not exist', async () => { + const testNewCollection = createCollectionDTO() + expect.assertions(2) + let writeError: WriteError + try { + await updateCollection.execute(TestConstants.TEST_DUMMY_COLLECTION_ID, testNewCollection) + throw new Error('Use case should throw an error') + } catch (error) { + writeError = error + } finally { + expect(writeError).toBeInstanceOf(WriteError) + expect(writeError.message).toEqual( + `There was an error when writing the resource. Reason was: [404] Can't find dataverse with identifier='${TestConstants.TEST_DUMMY_COLLECTION_ID}'` + ) + } + }) +}) From 513b3126a6bd3a0c288e702b250368fb5eb0bcc4 Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 23 Oct 2024 10:55:58 +0100 Subject: [PATCH 5/6] Added: docs for updateCollection --- docs/useCases.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/useCases.md b/docs/useCases.md index 3630da65..b2a0c4ae 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -16,6 +16,7 @@ The different use cases currently available in the package are classified below, - [List All Collection Items](#list-all-collection-items) - [Collections write use cases](#collections-write-use-cases) - [Create a Collection](#create-a-collection) + - [Update a Collection](#update-a-collection) - [Publish a Collection](#publish-a-collection) - [Datasets](#Datasets) - [Datasets read use cases](#datasets-read-use-cases) @@ -232,6 +233,34 @@ The above example creates the new collection in the `root` collection since no c The use case returns a number, which is the identifier of the created collection. +#### Update a Collection + +Updates an existing collection, given a collection identifier and a [CollectionDTO](../src/collections/domain/dtos/CollectionDTO.ts) including the updated collection data. + +##### Example call: + +```typescript +import { updateCollection } from '@iqss/dataverse-client-javascript' + +/* ... */ + +const collectionIdOrAlias = 12345 +const collectionDTO: CollectionDTO = { + alias: alias, + name: 'Updated Collection Name', + contacts: ['dataverse@test.com'], + type: CollectionType.DEPARTMENT +} + +updateCollection.execute(collectionIdOrAlias, collectionDTO) + +/* ... */ +``` + +_See [use case](../src/collections/domain/useCases/UpdateCollection.ts) implementation_. + +The `collectionIdOrAlias` is a generic collection identifier, which can be either a string (for queries by CollectionAlias), or a number (for queries by CollectionId). + #### Publish a Collection Publishes a Collection, given the collection identifier. From 09f115845094098dc45c21f59be9c8f48ab8d6d0 Mon Sep 17 00:00:00 2001 From: GPortas Date: Wed, 23 Oct 2024 10:56:16 +0100 Subject: [PATCH 6/6] Added: formatting --- .../repositories/CollectionsRepository.ts | 28 +++--- .../collections/UpdateCollection.test.ts | 86 ++++++++++--------- 2 files changed, 62 insertions(+), 52 deletions(-) diff --git a/src/collections/infra/repositories/CollectionsRepository.ts b/src/collections/infra/repositories/CollectionsRepository.ts index 263b9399..84623409 100644 --- a/src/collections/infra/repositories/CollectionsRepository.ts +++ b/src/collections/infra/repositories/CollectionsRepository.ts @@ -67,13 +67,13 @@ export class CollectionsRepository extends ApiRepository implements ICollections collectionDTO: CollectionDTO, parentCollectionId: number | string = ROOT_COLLECTION_ALIAS ): Promise { - const requestBody = this.createCreateOrUpdateRequestBody(collectionDTO); + const requestBody = this.createCreateOrUpdateRequestBody(collectionDTO) return this.doPost(`/${this.collectionsResourceName}/${parentCollectionId}`, requestBody) .then((response) => response.data.data.id) .catch((error) => { - throw error; - }); + throw error + }) } public async getCollectionFacets( @@ -160,26 +160,30 @@ export class CollectionsRepository extends ApiRepository implements ICollections collectionIdOrAlias: string | number, updatedCollection: CollectionDTO ): Promise { - const requestBody = this.createCreateOrUpdateRequestBody(updatedCollection); + const requestBody = this.createCreateOrUpdateRequestBody(updatedCollection) return this.doPut(`/${this.collectionsResourceName}/${collectionIdOrAlias}`, requestBody) .then(() => undefined) .catch((error) => { - throw error; - }); + throw error + }) } - private createCreateOrUpdateRequestBody(collectionDTO: CollectionDTO): NewCollectionRequestPayload { - const dataverseContacts: NewCollectionContactRequestPayload[] = collectionDTO.contacts.map((contact) => ({ - contactEmail: contact - })); + private createCreateOrUpdateRequestBody( + collectionDTO: CollectionDTO + ): NewCollectionRequestPayload { + const dataverseContacts: NewCollectionContactRequestPayload[] = collectionDTO.contacts.map( + (contact) => ({ + contactEmail: contact + }) + ) const inputLevelsRequestBody: NewCollectionInputLevelRequestPayload[] = collectionDTO.inputLevels?.map((inputLevel) => ({ datasetFieldTypeName: inputLevel.datasetFieldName, include: inputLevel.include, required: inputLevel.required - })); + })) return { alias: collectionDTO.alias, @@ -193,7 +197,7 @@ export class CollectionsRepository extends ApiRepository implements ICollections facetIds: collectionDTO.facetIds, inputLevels: inputLevelsRequestBody } - }; + } } private applyCollectionSearchCriteriaToQueryParams( diff --git a/test/functional/collections/UpdateCollection.test.ts b/test/functional/collections/UpdateCollection.test.ts index cffec841..4fbde611 100644 --- a/test/functional/collections/UpdateCollection.test.ts +++ b/test/functional/collections/UpdateCollection.test.ts @@ -1,48 +1,54 @@ -import { ApiConfig, WriteError, createCollection, getCollection, updateCollection } from '../../../src' +import { + ApiConfig, + WriteError, + createCollection, + getCollection, + updateCollection +} from '../../../src' import { TestConstants } from '../../testHelpers/TestConstants' import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig' import { createCollectionDTO } from '../../testHelpers/collections/collectionHelper' describe('execute', () => { - beforeEach(async () => { - ApiConfig.init( - TestConstants.TEST_API_URL, - DataverseApiAuthMechanism.API_KEY, - process.env.TEST_API_KEY - ) - }) + beforeEach(async () => { + ApiConfig.init( + TestConstants.TEST_API_URL, + DataverseApiAuthMechanism.API_KEY, + process.env.TEST_API_KEY + ) + }) - test('should successfully update a new collection', async () => { - const testNewCollectionAlias = 'updateCollection-functional-test' - const testNewCollection = createCollectionDTO(testNewCollectionAlias) - await createCollection.execute(testNewCollection) - const testNewName = 'Updated Name' - testNewCollection.name = testNewName - expect.assertions(1) - try { - await updateCollection.execute(testNewCollectionAlias, testNewCollection) - } catch (error) { - throw new Error('Collection should be updated') - } finally { - const updatedCollection = await getCollection.execute(testNewCollectionAlias) - expect(updatedCollection.name).toBe(testNewName) - } - }) + test('should successfully update a new collection', async () => { + const testNewCollectionAlias = 'updateCollection-functional-test' + const testNewCollection = createCollectionDTO(testNewCollectionAlias) + await createCollection.execute(testNewCollection) + const testNewName = 'Updated Name' + testNewCollection.name = testNewName + expect.assertions(1) + try { + await updateCollection.execute(testNewCollectionAlias, testNewCollection) + } catch (error) { + throw new Error('Collection should be updated') + } finally { + const updatedCollection = await getCollection.execute(testNewCollectionAlias) + expect(updatedCollection.name).toBe(testNewName) + } + }) - test('should throw an error when the parent collection does not exist', async () => { - const testNewCollection = createCollectionDTO() - expect.assertions(2) - let writeError: WriteError - try { - await updateCollection.execute(TestConstants.TEST_DUMMY_COLLECTION_ID, testNewCollection) - throw new Error('Use case should throw an error') - } catch (error) { - writeError = error - } finally { - expect(writeError).toBeInstanceOf(WriteError) - expect(writeError.message).toEqual( - `There was an error when writing the resource. Reason was: [404] Can't find dataverse with identifier='${TestConstants.TEST_DUMMY_COLLECTION_ID}'` - ) - } - }) + test('should throw an error when the parent collection does not exist', async () => { + const testNewCollection = createCollectionDTO() + expect.assertions(2) + let writeError: WriteError + try { + await updateCollection.execute(TestConstants.TEST_DUMMY_COLLECTION_ID, testNewCollection) + throw new Error('Use case should throw an error') + } catch (error) { + writeError = error + } finally { + expect(writeError).toBeInstanceOf(WriteError) + expect(writeError.message).toEqual( + `There was an error when writing the resource. Reason was: [404] Can't find dataverse with identifier='${TestConstants.TEST_DUMMY_COLLECTION_ID}'` + ) + } + }) })