diff --git a/.gitignore b/.gitignore index a26c4941..dbc1d777 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ node_modules # intellij .idea +# Visual Studio +/.vscode + # unit tests coverage diff --git a/docs/useCases.md b/docs/useCases.md index 184f989b..0d3df7df 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -506,15 +506,16 @@ publishDataset.execute(datasetId, versionUpdateType) _See [use case](../src/datasets/domain/useCases/PublishDataset.ts) implementation_. The above example publishes the dataset with the specified identifier and performs a minor version update. If the response -is successful, the use case does not return the dataset object, but the HTTP status code `200`. Otherwise, it throws an error. -If you want to perform a major version update, you must set the `versionUpdateType` parameter to `VersionUpdateType.MAJOR`. - +is successful, the use case does not return the dataset object, but the HTTP status code `200`. Otherwise, it throws an error.\ +If you want to perform a major version update, you must set the `versionUpdateType` parameter to `VersionUpdateType.MAJOR`.\ +Superusers can pass `VersionUpdateType.UPDATE_CURRENT` to update metadata without changing the version number. This will overwrite the latest published version and therefore will only work for a dataset that has been published at least once. \*Note that this will only work also if there were no file changes in the update.\ The `datasetId` parameter can be a string, for persistent identifiers, or a number, for numeric identifiers. The `versionUpdateType` parameter can be a [VersionUpdateType](../src/datasets/domain/models/VersionUpdateType.ts) enum value, which can be one of the following: - `VersionUpdateType.MINOR` - `VersionUpdateType.MAJOR` +- `VersionUpdateType.UPDATE_CURRENT` ## Files diff --git a/src/datasets/domain/models/Dataset.ts b/src/datasets/domain/models/Dataset.ts index f242a728..32d68e03 100644 --- a/src/datasets/domain/models/Dataset.ts +++ b/src/datasets/domain/models/Dataset.ts @@ -186,5 +186,6 @@ interface Software extends DatasetMetadataSubField { export enum VersionUpdateType { MAJOR = 'major', - MINOR = 'minor' + MINOR = 'minor', + UPDATE_CURRENT = 'updatecurrent' } diff --git a/src/datasets/domain/useCases/PublishDataset.ts b/src/datasets/domain/useCases/PublishDataset.ts index 13aa0488..2b7e9c04 100644 --- a/src/datasets/domain/useCases/PublishDataset.ts +++ b/src/datasets/domain/useCases/PublishDataset.ts @@ -13,7 +13,7 @@ export class PublishDataset implements UseCase { * Publishes a dataset, given its identifier and the type of version update type. * * @param {number | string} [datasetId] - The dataset identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers). - * @param {VersionUpdateType} versionUpdateType - Specifies the type of version update, 'major' or 'minor'. + * @param {VersionUpdateType} versionUpdateType - Specifies the type of version update, 'major', 'minor' or 'updatecurrent' * @returns {Promise} - This method does not return anything upon successful completion. */ async execute(datasetId: number | string, versionUpdateType: VersionUpdateType): Promise { diff --git a/test/functional/datasets/PublishDataset.test.ts b/test/functional/datasets/PublishDataset.test.ts index 190fdbb6..9bdbfdb6 100644 --- a/test/functional/datasets/PublishDataset.test.ts +++ b/test/functional/datasets/PublishDataset.test.ts @@ -2,6 +2,7 @@ import { ApiConfig, createDataset, publishDataset, + updateDataset, VersionUpdateType, WriteError } from '../../../src' @@ -72,6 +73,28 @@ describe('execute', () => { await deletePublishedDatasetViaApi(createdDatasetIdentifiers.persistentId) }) + test('should successfully publish a dataset with update current version', async () => { + const createdDatasetIdentifiers = await createDataset.execute(testNewDataset) + + const firstPublishResponse = await publishDataset.execute( + createdDatasetIdentifiers.persistentId, + VersionUpdateType.MAJOR + ) + await waitForNoLocks(createdDatasetIdentifiers.numericId, 10) + + await updateDataset.execute(createdDatasetIdentifiers.numericId, testNewDataset) + + const secondPublishResponse = await publishDataset.execute( + createdDatasetIdentifiers.persistentId, + VersionUpdateType.UPDATE_CURRENT + ) + await waitForNoLocks(createdDatasetIdentifiers.numericId, 10) + + expect(firstPublishResponse).toBeUndefined() + expect(secondPublishResponse).toBeUndefined() + await deletePublishedDatasetViaApi(createdDatasetIdentifiers.persistentId) + }) + test('should throw an error when trying to publish a dataset that does not exist', async () => { const nonExistentTestDatasetId = 'non-existent-dataset' const expectedError = new WriteError( @@ -82,4 +105,16 @@ describe('execute', () => { publishDataset.execute(nonExistentTestDatasetId, VersionUpdateType.MAJOR) ).rejects.toThrow(expectedError) }) + + test('should throw an error when trying to publish with the current version a dataset that has never been published before', async () => { + const createdDatasetIdentifiers = await createDataset.execute(testNewDataset) + + await waitForNoLocks(createdDatasetIdentifiers.numericId, 10) + + await expect( + publishDataset.execute(createdDatasetIdentifiers.numericId, VersionUpdateType.UPDATE_CURRENT) + ).rejects.toBeInstanceOf(WriteError) + + await deletePublishedDatasetViaApi(createdDatasetIdentifiers.persistentId) + }) }) diff --git a/test/integration/datasets/DatasetsRepository.test.ts b/test/integration/datasets/DatasetsRepository.test.ts index 7ddd8b6c..2fc0e1e7 100644 --- a/test/integration/datasets/DatasetsRepository.test.ts +++ b/test/integration/datasets/DatasetsRepository.test.ts @@ -516,6 +516,64 @@ describe('DatasetsRepository', () => { }) }) + describe('publish dataset with current version', () => { + let testDatasetIds: CreatedDatasetIdentifiers + + beforeEach(async () => { + testDatasetIds = await createDataset.execute(TestConstants.TEST_NEW_DATASET_DTO) + }) + + afterEach(async () => { + await deletePublishedDatasetViaApi(testDatasetIds.persistentId) + }) + + test('should update current dataset version keeping same version number', async () => { + const expectedMajorVersion = 1 + + await waitForNoLocks(testDatasetIds.numericId, 10) + + // Dataset is in draft, so we need to publish it first + await sut.publishDataset(testDatasetIds.numericId, VersionUpdateType.MAJOR) + await waitForNoLocks(testDatasetIds.numericId, 10) + + const datasetAfterFirstPublish = await sut.getDataset( + testDatasetIds.numericId, + DatasetNotNumberedVersion.LATEST, + false + ) + + // Update dataset + const metadataBlocksRepository = new MetadataBlocksRepository() + const citationMetadataBlock = await metadataBlocksRepository.getMetadataBlockByName( + 'citation' + ) + await sut.updateDataset(testDatasetIds.numericId, TestConstants.TEST_NEW_DATASET_DTO, [ + citationMetadataBlock + ]) + + // Update current version + await sut.publishDataset(testDatasetIds.numericId, VersionUpdateType.UPDATE_CURRENT) + await waitForNoLocks(testDatasetIds.numericId, 10) + + const datasetAfterUpdatingCurrentVersion = await sut.getDataset( + testDatasetIds.numericId, + DatasetNotNumberedVersion.LATEST, + false + ) + + expect(datasetAfterFirstPublish.versionInfo.majorNumber).toBe(expectedMajorVersion) + expect(datasetAfterUpdatingCurrentVersion.versionInfo.majorNumber).toBe(expectedMajorVersion) + }) + + test('should return error when trying to publish with the current version a dataset that has never been published before', async () => { + await waitForNoLocks(testDatasetIds.numericId, 10) + + await expect( + sut.publishDataset(testDatasetIds.numericId, VersionUpdateType.UPDATE_CURRENT) + ).rejects.toBeInstanceOf(WriteError) + }) + }) + describe('updateDataset', () => { test('should update an existing dataset with the provided dataset citation fields', async () => { const testDataset = {