diff --git a/src/datasets/domain/repositories/IDatasetsRepository.ts b/src/datasets/domain/repositories/IDatasetsRepository.ts index 6a7954d4..9c51935d 100644 --- a/src/datasets/domain/repositories/IDatasetsRepository.ts +++ b/src/datasets/domain/repositories/IDatasetsRepository.ts @@ -6,7 +6,7 @@ export interface IDatasetsRepository { getDatasetSummaryFieldNames(): Promise; getDataset(datasetId: number | string, datasetVersionId: string, includeDeaccessioned: boolean): Promise; getPrivateUrlDataset(token: string): Promise; - getDatasetCitation(datasetId: number, datasetVersionId: string): Promise; + getDatasetCitation(datasetId: number, datasetVersionId: string, includeDeaccessioned: boolean): Promise; getPrivateUrlDatasetCitation(token: string): Promise; getDatasetUserPermissions(datasetId: number | string): Promise; getDatasetLocks(datasetId: number | string): Promise; diff --git a/src/datasets/domain/useCases/GetDatasetCitation.ts b/src/datasets/domain/useCases/GetDatasetCitation.ts index e919b4b5..1783614d 100644 --- a/src/datasets/domain/useCases/GetDatasetCitation.ts +++ b/src/datasets/domain/useCases/GetDatasetCitation.ts @@ -12,7 +12,8 @@ export class GetDatasetCitation implements UseCase { async execute( datasetId: number, datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST, + includeDeaccessioned: boolean = false, ): Promise { - return await this.datasetsRepository.getDatasetCitation(datasetId, datasetVersionId); + return await this.datasetsRepository.getDatasetCitation(datasetId, datasetVersionId, includeDeaccessioned) } } diff --git a/src/datasets/infra/repositories/DatasetsRepository.ts b/src/datasets/infra/repositories/DatasetsRepository.ts index 55791700..01a01780 100644 --- a/src/datasets/infra/repositories/DatasetsRepository.ts +++ b/src/datasets/infra/repositories/DatasetsRepository.ts @@ -7,6 +7,7 @@ import { transformDatasetUserPermissionsResponseToDatasetUserPermissions } from import { DatasetLock } from '../../domain/models/DatasetLock'; import { transformDatasetLocksResponseToDatasetLocks } from './transformers/datasetLocksTransformers'; + export class DatasetsRepository extends ApiRepository implements IDatasetsRepository { private readonly datasetsResourceName: string = 'datasets'; @@ -45,10 +46,14 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi }); } - public async getDatasetCitation(datasetId: number, datasetVersionId: string): Promise { + + + public async getDatasetCitation(datasetId: number, datasetVersionId: string, + includeDeaccessioned: boolean): Promise { + return this.doGet( this.buildApiEndpoint(this.datasetsResourceName, `versions/${datasetVersionId}/citation`, datasetId), - true, + true, { includeDeaccessioned: includeDeaccessioned} ) .then((response) => response.data.data.message) .catch((error) => { diff --git a/test/integration/datasets/DatasetsRepository.test.ts b/test/integration/datasets/DatasetsRepository.test.ts index d6215363..bc813161 100644 --- a/test/integration/datasets/DatasetsRepository.test.ts +++ b/test/integration/datasets/DatasetsRepository.test.ts @@ -6,6 +6,8 @@ import { createDatasetViaApi, createPrivateUrlViaApi, publishDatasetViaApi, + deaccessionDatasetViaApi, + waitForNoLocks } from '../../testHelpers/datasets/datasetHelper'; import { ReadError } from '../../../src/core/domain/repositories/ReadError'; import { DatasetNotNumberedVersion, DatasetLockType } from '../../../src/datasets'; @@ -81,20 +83,54 @@ describe('DatasetsRepository', () => { const actualDatasetCitation = await sut.getDatasetCitation( TestConstants.TEST_CREATED_DATASET_ID, latestVersionId, + false, ); expect(typeof actualDatasetCitation).toBe('string'); }); test('should return error when dataset does not exist', async () => { let error: ReadError = undefined; - - await sut.getDatasetCitation(nonExistentTestDatasetId, latestVersionId).catch((e) => (error = e)); + await sut.getDatasetCitation(nonExistentTestDatasetId, latestVersionId,false).catch((e) => (error = e)); assert.match( error.message, `There was an error when reading the resource. Reason was: [404] Dataset with ID ${nonExistentTestDatasetId} not found.`, ); }); + test('should return citation when dataset is deaccessioned', async () => { + let createdDatasetId = undefined; + await createDatasetViaApi() + .then((response) => (createdDatasetId = response.data.data.id)) + .catch(() => { + assert.fail('Error while creating test Dataset'); + }); + // We publish the new test dataset we can deaccession it + await publishDatasetViaApi(createdDatasetId) + .then() + .catch(() => { + assert.fail('Error while publishing test Dataset'); + }); + + await waitForNoLocks(createdDatasetId, 10) + .then() + .catch(() => { + assert.fail('Error while waiting for no locks'); + }); + await deaccessionDatasetViaApi(createdDatasetId,'1.0') + .then() + .catch((error) => { + console.log(JSON.stringify(error)); + assert.fail('Error while deaccessioning test Dataset'); + }); + + const actualDatasetCitation = await sut.getDatasetCitation( + createdDatasetId, + latestVersionId, + true, + ); + expect(typeof actualDatasetCitation).toBe('string'); + + }); }); describe('Private URLs', () => { diff --git a/test/testHelpers/TestConstants.ts b/test/testHelpers/TestConstants.ts index 37dca855..d3356a7e 100644 --- a/test/testHelpers/TestConstants.ts +++ b/test/testHelpers/TestConstants.ts @@ -15,6 +15,13 @@ export class TestConstants { 'X-Dataverse-Key': TestConstants.TEST_DUMMY_API_KEY, }, }; + static readonly TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY_INCLUDE_DEACCESSIONED = { + params: { includeDeaccessioned: true }, + headers: { + 'Content-Type': 'application/json', + 'X-Dataverse-Key': TestConstants.TEST_DUMMY_API_KEY, + }, + }; static readonly TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE = { withCredentials: true, params: {}, @@ -22,6 +29,13 @@ export class TestConstants { 'Content-Type': 'application/json', }, }; + static readonly TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE_INCLUDE_DEACCESSIONED = { + withCredentials: true, + params: { includeDeaccessioned: true }, + headers: { + 'Content-Type': 'application/json', + }, + }; static readonly TEST_EXPECTED_UNAUTHENTICATED_REQUEST_CONFIG = { params: {}, headers: { diff --git a/test/testHelpers/datasets/datasetHelper.ts b/test/testHelpers/datasets/datasetHelper.ts index dc1119a9..f155641b 100644 --- a/test/testHelpers/datasets/datasetHelper.ts +++ b/test/testHelpers/datasets/datasetHelper.ts @@ -212,6 +212,15 @@ export const publishDatasetViaApi = async (datasetId: number): Promise => { + const data = { deaccessionReason: 'Test reason.' }; + return await axios.post( + `${TestConstants.TEST_API_URL}/datasets/${datasetId}/versions/${versionId}/deaccession`, + JSON.stringify(data), + DATAVERSE_API_REQUEST_HEADERS, + ); +}; + export const createPrivateUrlViaApi = async (datasetId: number): Promise => { return await axios.post( `${TestConstants.TEST_API_URL}/datasets/${datasetId}/privateUrl`, @@ -219,3 +228,30 @@ export const createPrivateUrlViaApi = async (datasetId: number): Promise => { + let hasLocks = true; + let retry = 0; + while (hasLocks && retry < maxRetries) { + await axios + .get(`${TestConstants.TEST_API_URL}/datasets/${datasetId}/locks`) + .then((response) => { + const nLocks = response.data.data.length; + if (nLocks == 0) { + hasLocks = false; + } + }) + .catch((error) => { + console.log( + `Error while waiting for no dataset locks: [${error.response.status}]${ + error.response.data ? ` ${error.response.data.message}` : '' + }`, + ); + }); + await new Promise((resolve) => setTimeout(resolve, delay)); + retry++; + } + if (hasLocks) { + throw new Error('Max retries reached.'); + } +}; diff --git a/test/unit/datasets/DatasetsRepository.test.ts b/test/unit/datasets/DatasetsRepository.test.ts index 34844403..684e21ad 100644 --- a/test/unit/datasets/DatasetsRepository.test.ts +++ b/test/unit/datasets/DatasetsRepository.test.ts @@ -232,29 +232,30 @@ describe('DatasetsRepository', () => { }); describe('getDatasetCitation', () => { + const testIncludeDeaccessioned = true; test('should return citation when response is successful', async () => { const axiosGetStub = sandbox.stub(axios, 'get').resolves(testCitationSuccessfulResponse); const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/datasets/${testDatasetModel.id}/versions/${testVersionId}/citation`; // API Key auth - let actual = await sut.getDatasetCitation(testDatasetModel.id, testVersionId); + let actual = await sut.getDatasetCitation(testDatasetModel.id, testVersionId, testIncludeDeaccessioned); assert.calledWithExactly( axiosGetStub, expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY, + TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY_INCLUDE_DEACCESSIONED, ); assert.match(actual, testCitation); // Session cookie auth ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.SESSION_COOKIE); - actual = await sut.getDatasetCitation(testDatasetModel.id, testVersionId); + actual = await sut.getDatasetCitation(testDatasetModel.id, testVersionId, testIncludeDeaccessioned); assert.calledWithExactly( axiosGetStub, expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE, + TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE_INCLUDE_DEACCESSIONED, ); assert.match(actual, testCitation); }); @@ -263,12 +264,12 @@ describe('DatasetsRepository', () => { const axiosGetStub = sandbox.stub(axios, 'get').rejects(TestConstants.TEST_ERROR_RESPONSE); let error: ReadError = undefined; - await sut.getDatasetCitation(1, testVersionId).catch((e) => (error = e)); + await sut.getDatasetCitation(1, testVersionId,testIncludeDeaccessioned).catch((e) => (error = e)); assert.calledWithExactly( axiosGetStub, `${TestConstants.TEST_API_URL}/datasets/${testDatasetModel.id}/versions/${testVersionId}/citation`, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY, + TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY_INCLUDE_DEACCESSIONED, ); expect(error).to.be.instanceOf(Error); }); diff --git a/test/unit/datasets/GetDatasetCitation.test.ts b/test/unit/datasets/GetDatasetCitation.test.ts index 3c48f009..580d96b1 100644 --- a/test/unit/datasets/GetDatasetCitation.test.ts +++ b/test/unit/datasets/GetDatasetCitation.test.ts @@ -23,7 +23,7 @@ describe('execute', () => { const actual = await sut.execute(testId); assert.match(actual, testCitation); - assert.calledWithExactly(getDatasetCitationStub, testId, DatasetNotNumberedVersion.LATEST); + assert.calledWithExactly(getDatasetCitationStub, testId, DatasetNotNumberedVersion.LATEST, false); }); test('should return error result on repository error', async () => {