From 23d9b41d46311037ff2941f57c46b02979dbe86d Mon Sep 17 00:00:00 2001 From: GPortas Date: Mon, 25 Sep 2023 17:27:15 +0100 Subject: [PATCH 1/5] Added: deleted, tabularData and fileAccessRequest file properties --- src/files/domain/models/File.ts | 3 +++ .../infra/repositories/transformers/fileTransformers.ts | 4 ++++ test/integration/environment/.env | 2 +- test/integration/files/FilesRepository.test.ts | 2 +- test/testHelpers/files/filesHelper.ts | 6 ++++++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/files/domain/models/File.ts b/src/files/domain/models/File.ts index e5b0746f..26d57985 100644 --- a/src/files/domain/models/File.ts +++ b/src/files/domain/models/File.ts @@ -27,6 +27,9 @@ export interface File { tabularTags?: string[]; creationDate?: Date; publicationDate?: Date; + deleted: boolean; + tabularData: boolean; + fileAccessRequest?: boolean; } export interface FileEmbargo { diff --git a/src/files/infra/repositories/transformers/fileTransformers.ts b/src/files/infra/repositories/transformers/fileTransformers.ts index c860e456..a28d1711 100644 --- a/src/files/infra/repositories/transformers/fileTransformers.ts +++ b/src/files/infra/repositories/transformers/fileTransformers.ts @@ -44,6 +44,10 @@ const transformFilePayloadToFile = (filePayload: any): File => { ...(filePayload.dataFile.tabularTags && { tabularTags: filePayload.dataFile.tabularTags }), ...(filePayload.dataFile.creationDate && { creationDate: new Date(filePayload.dataFile.creationDate) }), ...(filePayload.dataFile.publicationDate && { publicationDate: new Date(filePayload.dataFile.publicationDate) }), + ...(filePayload.dataFile.publicationDate && { publicationDate: new Date(filePayload.dataFile.publicationDate) }), + deleted: filePayload.dataFile.deleted, + tabularData: filePayload.dataFile.tabularData, + ...(filePayload.dataFile.fileAccessRequest && { fileAccessRequest: filePayload.dataFile.fileAccessRequest }), }; }; diff --git a/test/integration/environment/.env b/test/integration/environment/.env index 5478afd6..510a9a20 100644 --- a/test/integration/environment/.env +++ b/test/integration/environment/.env @@ -2,5 +2,5 @@ POSTGRES_VERSION=13 DATAVERSE_DB_USER=dataverse SOLR_VERSION=8.11.1 DATAVERSE_IMAGE_REGISTRY=ghcr.io -DATAVERSE_IMAGE_TAG=9834-files-api-extension-file-counts +DATAVERSE_IMAGE_TAG=9852-files-api-deaccessioned-datasets DATAVERSE_BOOTSTRAP_TIMEOUT=5m diff --git a/test/integration/files/FilesRepository.test.ts b/test/integration/files/FilesRepository.test.ts index a463cb0b..aa75fe25 100644 --- a/test/integration/files/FilesRepository.test.ts +++ b/test/integration/files/FilesRepository.test.ts @@ -301,7 +301,7 @@ describe('FilesRepository', () => { assert.match( error.message, - `There was an error when reading the resource. Reason was: [404] File with ID ${nonExistentFiledId} not found.`, + `There was an error when reading the resource. Reason was: [404] File not found for given id.`, ); }); }); diff --git a/test/testHelpers/files/filesHelper.ts b/test/testHelpers/files/filesHelper.ts index 2da10fe7..f2618061 100644 --- a/test/testHelpers/files/filesHelper.ts +++ b/test/testHelpers/files/filesHelper.ts @@ -27,6 +27,9 @@ export const createFileModel = (): File => { type: 'MD5', value: '29e413e0c881e17314ce8116fed4d1a7', }, + deleted: false, + tabularData: false, + fileAccessRequest: true, }; }; @@ -58,6 +61,9 @@ export const createFilePayload = (): any => { type: 'MD5', value: '29e413e0c881e17314ce8116fed4d1a7', }, + deleted: false, + tabularData: false, + fileAccessRequest: true, }, }; }; From 50190233c45f234d95bda396c3940ae5e37874d9 Mon Sep 17 00:00:00 2001 From: GPortas Date: Mon, 25 Sep 2023 17:31:48 +0100 Subject: [PATCH 2/5] Removed: duplicated line in file transformer --- src/files/infra/repositories/transformers/fileTransformers.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/files/infra/repositories/transformers/fileTransformers.ts b/src/files/infra/repositories/transformers/fileTransformers.ts index a28d1711..61065920 100644 --- a/src/files/infra/repositories/transformers/fileTransformers.ts +++ b/src/files/infra/repositories/transformers/fileTransformers.ts @@ -44,7 +44,6 @@ const transformFilePayloadToFile = (filePayload: any): File => { ...(filePayload.dataFile.tabularTags && { tabularTags: filePayload.dataFile.tabularTags }), ...(filePayload.dataFile.creationDate && { creationDate: new Date(filePayload.dataFile.creationDate) }), ...(filePayload.dataFile.publicationDate && { publicationDate: new Date(filePayload.dataFile.publicationDate) }), - ...(filePayload.dataFile.publicationDate && { publicationDate: new Date(filePayload.dataFile.publicationDate) }), deleted: filePayload.dataFile.deleted, tabularData: filePayload.dataFile.tabularData, ...(filePayload.dataFile.fileAccessRequest && { fileAccessRequest: filePayload.dataFile.fileAccessRequest }), From fe85f2fed031d0d9725224b2116ea7dac77a3fb8 Mon Sep 17 00:00:00 2001 From: GPortas Date: Mon, 25 Sep 2023 18:46:18 +0100 Subject: [PATCH 3/5] Added: includeDeaccessioned optional param to GetDatasetFiles use case --- .../domain/repositories/IFilesRepository.ts | 1 + src/files/domain/useCases/GetDatasetFiles.ts | 10 ++- .../infra/repositories/FilesRepository.ts | 6 +- .../integration/files/FilesRepository.test.ts | 50 ++++++++++--- test/unit/files/FilesRepository.test.ts | 73 ++++++++----------- test/unit/files/GetDatasetFiles.test.ts | 2 +- 6 files changed, 88 insertions(+), 54 deletions(-) diff --git a/src/files/domain/repositories/IFilesRepository.ts b/src/files/domain/repositories/IFilesRepository.ts index 85a24bec..4455d10f 100644 --- a/src/files/domain/repositories/IFilesRepository.ts +++ b/src/files/domain/repositories/IFilesRepository.ts @@ -8,6 +8,7 @@ export interface IFilesRepository { getDatasetFiles( datasetId: number | string, datasetVersionId: string, + includeDeaccessioned: boolean, limit?: number, offset?: number, fileCriteria?: FileCriteria, diff --git a/src/files/domain/useCases/GetDatasetFiles.ts b/src/files/domain/useCases/GetDatasetFiles.ts index eb6d1150..4d2941bd 100644 --- a/src/files/domain/useCases/GetDatasetFiles.ts +++ b/src/files/domain/useCases/GetDatasetFiles.ts @@ -14,10 +14,18 @@ export class GetDatasetFiles implements UseCase { async execute( datasetId: number | string, datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST, + includeDeaccessioned: boolean = false, limit?: number, offset?: number, fileCriteria?: FileCriteria, ): Promise { - return await this.filesRepository.getDatasetFiles(datasetId, datasetVersionId, limit, offset, fileCriteria); + return await this.filesRepository.getDatasetFiles( + datasetId, + datasetVersionId, + includeDeaccessioned, + limit, + offset, + fileCriteria, + ); } } diff --git a/src/files/infra/repositories/FilesRepository.ts b/src/files/infra/repositories/FilesRepository.ts index d9d2bf45..f1a91802 100644 --- a/src/files/infra/repositories/FilesRepository.ts +++ b/src/files/infra/repositories/FilesRepository.ts @@ -11,6 +11,7 @@ import { FileCounts } from '../../domain/models/FileCounts'; import { transformFileCountsResponseToFileCounts } from './transformers/fileCountsTransformers'; export interface GetFilesQueryParams { + includeDeaccessioned: boolean; limit?: number; offset?: number; orderCriteria?: string; @@ -28,11 +29,14 @@ export class FilesRepository extends ApiRepository implements IFilesRepository { public async getDatasetFiles( datasetId: number | string, datasetVersionId: string, + includeDeaccessioned: boolean, limit?: number, offset?: number, fileCriteria?: FileCriteria, ): Promise { - const queryParams: GetFilesQueryParams = {}; + const queryParams: GetFilesQueryParams = { + includeDeaccessioned: includeDeaccessioned, + }; if (limit !== undefined) { queryParams.limit = limit; } diff --git a/test/integration/files/FilesRepository.test.ts b/test/integration/files/FilesRepository.test.ts index aa75fe25..e145a637 100644 --- a/test/integration/files/FilesRepository.test.ts +++ b/test/integration/files/FilesRepository.test.ts @@ -62,7 +62,11 @@ describe('FilesRepository', () => { fail(`Tests beforeAll(): Error while uploading file ${testTabFile4Name}`); }); // Categorize one of the uploaded test files - const currentTestFiles = await sut.getDatasetFiles(TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId); + const currentTestFiles = await sut.getDatasetFiles( + TestConstants.TEST_CREATED_DATASET_ID, + latestDatasetVersionId, + false, + ); const testFile = currentTestFiles[0]; setFileCategoriesViaApi(testFile.id, [testCategoryName]) .then() @@ -80,7 +84,7 @@ describe('FilesRepository', () => { describe('by numeric id', () => { test('should return all files filtering by dataset id and version id', async () => { - const actual = await sut.getDatasetFiles(TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId); + const actual = await sut.getDatasetFiles(TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId, false); assert.match(actual.length, 4); assert.match(actual[0].name, testTextFile1Name); assert.match(actual[1].name, testTextFile2Name); @@ -92,6 +96,7 @@ describe('FilesRepository', () => { const actual = await sut.getDatasetFiles( TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId, + false, 3, 3, undefined, @@ -104,6 +109,7 @@ describe('FilesRepository', () => { let actual = await sut.getDatasetFiles( TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId, + false, undefined, undefined, testFileCriteria, @@ -118,7 +124,7 @@ describe('FilesRepository', () => { let error: ReadError = undefined; const nonExistentTestDatasetId = 100; - await sut.getDatasetFiles(nonExistentTestDatasetId, latestDatasetVersionId).catch((e) => (error = e)); + await sut.getDatasetFiles(nonExistentTestDatasetId, latestDatasetVersionId, false).catch((e) => (error = e)); assert.match( error.message, @@ -133,7 +139,7 @@ describe('FilesRepository', () => { TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId, ); - const actual = await sut.getDatasetFiles(testDataset.persistentId, latestDatasetVersionId); + const actual = await sut.getDatasetFiles(testDataset.persistentId, latestDatasetVersionId, false); assert.match(actual.length, 4); assert.match(actual[0].name, testTextFile1Name); assert.match(actual[1].name, testTextFile2Name); @@ -146,7 +152,14 @@ describe('FilesRepository', () => { TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId, ); - const actual = await sut.getDatasetFiles(testDataset.persistentId, latestDatasetVersionId, 3, 3, undefined); + const actual = await sut.getDatasetFiles( + testDataset.persistentId, + latestDatasetVersionId, + false, + 3, + 3, + undefined, + ); assert.match(actual.length, 1); assert.match(actual[0].name, testTabFile4Name); }); @@ -159,6 +172,7 @@ describe('FilesRepository', () => { let actual = await sut.getDatasetFiles( testDataset.persistentId, latestDatasetVersionId, + false, undefined, undefined, testFileCriteria, @@ -173,7 +187,7 @@ describe('FilesRepository', () => { let error: ReadError = undefined; const testWrongPersistentId = 'wrongPersistentId'; - await sut.getDatasetFiles(testWrongPersistentId, latestDatasetVersionId).catch((e) => (error = e)); + await sut.getDatasetFiles(testWrongPersistentId, latestDatasetVersionId, false).catch((e) => (error = e)); assert.match( error.message, @@ -233,7 +247,11 @@ describe('FilesRepository', () => { describe('getFileDownloadCount', () => { test('should return count filtering by file id and version id', async () => { - const currentTestFiles = await sut.getDatasetFiles(TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId); + const currentTestFiles = await sut.getDatasetFiles( + TestConstants.TEST_CREATED_DATASET_ID, + latestDatasetVersionId, + false, + ); const testFile = currentTestFiles[0]; const actual = await sut.getFileDownloadCount(testFile.id); assert.match(actual, 0); @@ -253,7 +271,11 @@ describe('FilesRepository', () => { describe('getFileUserPermissions', () => { test('should return user permissions filtering by file id and version id', async () => { - const currentTestFiles = await sut.getDatasetFiles(TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId); + const currentTestFiles = await sut.getDatasetFiles( + TestConstants.TEST_CREATED_DATASET_ID, + latestDatasetVersionId, + false, + ); const testFile = currentTestFiles[0]; const actual = await sut.getFileUserPermissions(testFile.id); assert.match(actual.canDownloadFile, true); @@ -274,14 +296,22 @@ describe('FilesRepository', () => { describe('getFileDataTables', () => { test('should return data tables filtering by tabular file id and version id', async () => { - const currentTestFiles = await sut.getDatasetFiles(TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId); + const currentTestFiles = await sut.getDatasetFiles( + TestConstants.TEST_CREATED_DATASET_ID, + latestDatasetVersionId, + false, + ); const testFile = currentTestFiles[3]; const actual = await sut.getFileDataTables(testFile.id); assert.match(actual[0].varQuantity, 3); }); test('should return error when file is not tabular and version id', async () => { - const currentTestFiles = await sut.getDatasetFiles(TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId); + const currentTestFiles = await sut.getDatasetFiles( + TestConstants.TEST_CREATED_DATASET_ID, + latestDatasetVersionId, + false, + ); const testFile = currentTestFiles[0]; let error: ReadError = undefined; diff --git a/test/unit/files/FilesRepository.test.ts b/test/unit/files/FilesRepository.test.ts index d61a394c..1ffea6ff 100644 --- a/test/unit/files/FilesRepository.test.ts +++ b/test/unit/files/FilesRepository.test.ts @@ -45,7 +45,8 @@ describe('FilesRepository', () => { .withContentType(testContentType) .withAccessStatus(FileAccessStatus.PUBLIC); - const expectedRequestParams = { + const expectedRequestParamsWithOptional = { + includeDeaccessioned: false, limit: testLimit, offset: testOffset, orderCriteria: testFileCriteria.orderCriteria.toString(), @@ -53,6 +54,20 @@ describe('FilesRepository', () => { contentType: testFileCriteria.contentType, accessStatus: testFileCriteria.accessStatus.toString(), }; + const expectedRequestConfigApiKeyWithOptional = { + params: expectedRequestParamsWithOptional, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers, + }; + const expectedRequestConfigApiKey = { + params: { includeDeaccessioned: false }, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers, + }; + const expectedRequestConfigSessionCookie = { + params: { includeDeaccessioned: false }, + withCredentials: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE.withCredentials, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE.headers, + }; + const expectedFiles = [testFile]; describe('by numeric id and version id', () => { @@ -61,25 +76,17 @@ describe('FilesRepository', () => { const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/datasets/${testDatasetId}/versions/${testDatasetVersionId}/files`; // API Key auth - let actual = await sut.getDatasetFiles(testDatasetId, testDatasetVersionId); + let actual = await sut.getDatasetFiles(testDatasetId, testDatasetVersionId, false); - assert.calledWithExactly( - axiosGetStub, - expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY, - ); + assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigApiKey); assert.match(actual, expectedFiles); // Session cookie auth ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.SESSION_COOKIE); - actual = await sut.getDatasetFiles(testDatasetId, testDatasetVersionId); + actual = await sut.getDatasetFiles(testDatasetId, testDatasetVersionId, false); - assert.calledWithExactly( - axiosGetStub, - expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE, - ); + assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigSessionCookie); assert.match(actual, expectedFiles); }); @@ -89,20 +96,16 @@ describe('FilesRepository', () => { const actual = await sut.getDatasetFiles( testDatasetId, testDatasetVersionId, + false, testLimit, testOffset, testFileCriteria, ); - const expectedRequestConfig = { - params: expectedRequestParams, - headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers, - }; - assert.calledWithExactly( axiosGetStub, `${TestConstants.TEST_API_URL}/datasets/${testDatasetId}/versions/${testDatasetVersionId}/files`, - expectedRequestConfig, + expectedRequestConfigApiKeyWithOptional, ); assert.match(actual, [testFile]); }); @@ -111,12 +114,12 @@ describe('FilesRepository', () => { const axiosGetStub = sandbox.stub(axios, 'get').rejects(TestConstants.TEST_ERROR_RESPONSE); let error: ReadError = undefined; - await sut.getDatasetFiles(testDatasetId, testDatasetVersionId).catch((e) => (error = e)); + await sut.getDatasetFiles(testDatasetId, testDatasetVersionId, false).catch((e) => (error = e)); assert.calledWithExactly( axiosGetStub, `${TestConstants.TEST_API_URL}/datasets/${testDatasetId}/versions/${testDatasetVersionId}/files`, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY, + expectedRequestConfigApiKey, ); expect(error).to.be.instanceOf(Error); }); @@ -128,25 +131,17 @@ describe('FilesRepository', () => { const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/datasets/:persistentId/versions/${testDatasetVersionId}/files?persistentId=${TestConstants.TEST_DUMMY_PERSISTENT_ID}`; // API Key auth - let actual = await sut.getDatasetFiles(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId); + let actual = await sut.getDatasetFiles(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId, false); - assert.calledWithExactly( - axiosGetStub, - expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY, - ); + assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigApiKey); assert.match(actual, expectedFiles); // Session cookie auth ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.SESSION_COOKIE); - actual = await sut.getDatasetFiles(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId); + actual = await sut.getDatasetFiles(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId, false); - assert.calledWithExactly( - axiosGetStub, - expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE, - ); + assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigSessionCookie); assert.match(actual, expectedFiles); }); @@ -156,20 +151,16 @@ describe('FilesRepository', () => { const actual = await sut.getDatasetFiles( TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId, + false, testLimit, testOffset, testFileCriteria, ); - const expectedRequestConfig = { - params: expectedRequestParams, - headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers, - }; - assert.calledWithExactly( axiosGetStub, `${TestConstants.TEST_API_URL}/datasets/:persistentId/versions/${testDatasetVersionId}/files?persistentId=${TestConstants.TEST_DUMMY_PERSISTENT_ID}`, - expectedRequestConfig, + expectedRequestConfigApiKeyWithOptional, ); assert.match(actual, [testFile]); }); @@ -179,13 +170,13 @@ describe('FilesRepository', () => { let error: ReadError = undefined; await sut - .getDatasetFiles(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId) + .getDatasetFiles(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId, false) .catch((e) => (error = e)); assert.calledWithExactly( axiosGetStub, `${TestConstants.TEST_API_URL}/datasets/:persistentId/versions/${testDatasetVersionId}/files?persistentId=${TestConstants.TEST_DUMMY_PERSISTENT_ID}`, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY, + expectedRequestConfigApiKey, ); expect(error).to.be.instanceOf(Error); }); diff --git a/test/unit/files/GetDatasetFiles.test.ts b/test/unit/files/GetDatasetFiles.test.ts index 98494bea..840e4bdb 100644 --- a/test/unit/files/GetDatasetFiles.test.ts +++ b/test/unit/files/GetDatasetFiles.test.ts @@ -23,7 +23,7 @@ describe('execute', () => { const actual = await sut.execute(1); assert.match(actual, testFiles); - assert.calledWithExactly(getDatasetFilesStub, 1, DatasetNotNumberedVersion.LATEST, undefined, undefined, undefined); + assert.calledWithExactly(getDatasetFilesStub, 1, DatasetNotNumberedVersion.LATEST, false, undefined, undefined, undefined); }); test('should return error result on repository error', async () => { From a19b362a161282dea34be50962e2a95d41a8e5d9 Mon Sep 17 00:00:00 2001 From: GPortas Date: Mon, 25 Sep 2023 19:11:49 +0100 Subject: [PATCH 4/5] Added: includeDeaccessioned optional param to GetDatasetFileCounts use case --- .../domain/repositories/IFilesRepository.ts | 6 +- .../domain/useCases/GetDatasetFileCounts.ts | 3 +- .../infra/repositories/FilesRepository.ts | 9 +- .../integration/files/FilesRepository.test.ts | 8 +- test/unit/files/FilesRepository.test.ts | 109 ++++++++++-------- test/unit/files/GetDatasetFileCounts.test.ts | 2 +- 6 files changed, 85 insertions(+), 52 deletions(-) diff --git a/src/files/domain/repositories/IFilesRepository.ts b/src/files/domain/repositories/IFilesRepository.ts index 4455d10f..51fbfa3c 100644 --- a/src/files/domain/repositories/IFilesRepository.ts +++ b/src/files/domain/repositories/IFilesRepository.ts @@ -14,7 +14,11 @@ export interface IFilesRepository { fileCriteria?: FileCriteria, ): Promise; - getDatasetFileCounts(datasetId: number | string, datasetVersionId: string): Promise; + getDatasetFileCounts( + datasetId: number | string, + datasetVersionId: string, + includeDeaccessioned: boolean, + ): Promise; getFileDownloadCount(fileId: number | string): Promise; diff --git a/src/files/domain/useCases/GetDatasetFileCounts.ts b/src/files/domain/useCases/GetDatasetFileCounts.ts index 6e73a889..00803570 100644 --- a/src/files/domain/useCases/GetDatasetFileCounts.ts +++ b/src/files/domain/useCases/GetDatasetFileCounts.ts @@ -13,7 +13,8 @@ export class GetDatasetFileCounts implements UseCase { async execute( datasetId: number | string, datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST, + includeDeaccessioned: boolean = false, ): Promise { - return await this.filesRepository.getDatasetFileCounts(datasetId, datasetVersionId); + return await this.filesRepository.getDatasetFileCounts(datasetId, datasetVersionId, includeDeaccessioned); } } diff --git a/src/files/infra/repositories/FilesRepository.ts b/src/files/infra/repositories/FilesRepository.ts index f1a91802..72562a38 100644 --- a/src/files/infra/repositories/FilesRepository.ts +++ b/src/files/infra/repositories/FilesRepository.ts @@ -57,10 +57,17 @@ export class FilesRepository extends ApiRepository implements IFilesRepository { }); } - public async getDatasetFileCounts(datasetId: string | number, datasetVersionId: string): Promise { + public async getDatasetFileCounts( + datasetId: string | number, + datasetVersionId: string, + includeDeaccessioned: boolean, + ): Promise { return this.doGet( this.buildApiEndpoint(this.datasetsResourceName, `versions/${datasetVersionId}/files/counts`, datasetId), true, + { + includeDeaccessioned: includeDeaccessioned, + }, ) .then((response) => transformFileCountsResponseToFileCounts(response)) .catch((error) => { diff --git a/test/integration/files/FilesRepository.test.ts b/test/integration/files/FilesRepository.test.ts index e145a637..ce041180 100644 --- a/test/integration/files/FilesRepository.test.ts +++ b/test/integration/files/FilesRepository.test.ts @@ -225,7 +225,11 @@ describe('FilesRepository', () => { }; test('should return file count filtering by numeric id', async () => { - const actual = await sut.getDatasetFileCounts(TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId); + const actual = await sut.getDatasetFileCounts( + TestConstants.TEST_CREATED_DATASET_ID, + latestDatasetVersionId, + false, + ); assert.match(actual.total, expectedFileCounts.total); expect(actual.perContentType).to.have.deep.members(expectedFileCounts.perContentType); expect(actual.perAccessStatus).to.have.deep.members(expectedFileCounts.perAccessStatus); @@ -237,7 +241,7 @@ describe('FilesRepository', () => { TestConstants.TEST_CREATED_DATASET_ID, latestDatasetVersionId, ); - const actual = await sut.getDatasetFileCounts(testDataset.persistentId, latestDatasetVersionId); + const actual = await sut.getDatasetFileCounts(testDataset.persistentId, latestDatasetVersionId, false); assert.match(actual.total, expectedFileCounts.total); expect(actual.perContentType).to.have.deep.members(expectedFileCounts.perContentType); expect(actual.perAccessStatus).to.have.deep.members(expectedFileCounts.perAccessStatus); diff --git a/test/unit/files/FilesRepository.test.ts b/test/unit/files/FilesRepository.test.ts index 1ffea6ff..1950556b 100644 --- a/test/unit/files/FilesRepository.test.ts +++ b/test/unit/files/FilesRepository.test.ts @@ -15,9 +15,11 @@ import { createFileCountsModel, createFileCountsPayload } from '../../testHelper describe('FilesRepository', () => { const sandbox: SinonSandbox = createSandbox(); const sut: FilesRepository = new FilesRepository(); + const testFile = createFileModel(); const testDatasetVersionId = DatasetNotNumberedVersion.LATEST; const testDatasetId = 1; + const testIncludeDeaccessioned = false; beforeEach(() => { ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.API_KEY, TestConstants.TEST_DUMMY_API_KEY); @@ -45,8 +47,17 @@ describe('FilesRepository', () => { .withContentType(testContentType) .withAccessStatus(FileAccessStatus.PUBLIC); + const expectedRequestConfigApiKey = { + params: { includeDeaccessioned: testIncludeDeaccessioned }, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers, + }; + const expectedRequestConfigSessionCookie = { + params: { includeDeaccessioned: testIncludeDeaccessioned }, + withCredentials: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE.withCredentials, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE.headers, + }; const expectedRequestParamsWithOptional = { - includeDeaccessioned: false, + includeDeaccessioned: testIncludeDeaccessioned, limit: testLimit, offset: testOffset, orderCriteria: testFileCriteria.orderCriteria.toString(), @@ -58,15 +69,6 @@ describe('FilesRepository', () => { params: expectedRequestParamsWithOptional, headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers, }; - const expectedRequestConfigApiKey = { - params: { includeDeaccessioned: false }, - headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers, - }; - const expectedRequestConfigSessionCookie = { - params: { includeDeaccessioned: false }, - withCredentials: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE.withCredentials, - headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE.headers, - }; const expectedFiles = [testFile]; @@ -76,7 +78,7 @@ describe('FilesRepository', () => { const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/datasets/${testDatasetId}/versions/${testDatasetVersionId}/files`; // API Key auth - let actual = await sut.getDatasetFiles(testDatasetId, testDatasetVersionId, false); + let actual = await sut.getDatasetFiles(testDatasetId, testDatasetVersionId, testIncludeDeaccessioned); assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigApiKey); assert.match(actual, expectedFiles); @@ -84,7 +86,7 @@ describe('FilesRepository', () => { // Session cookie auth ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.SESSION_COOKIE); - actual = await sut.getDatasetFiles(testDatasetId, testDatasetVersionId, false); + actual = await sut.getDatasetFiles(testDatasetId, testDatasetVersionId, testIncludeDeaccessioned); assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigSessionCookie); assert.match(actual, expectedFiles); @@ -96,7 +98,7 @@ describe('FilesRepository', () => { const actual = await sut.getDatasetFiles( testDatasetId, testDatasetVersionId, - false, + testIncludeDeaccessioned, testLimit, testOffset, testFileCriteria, @@ -114,7 +116,9 @@ describe('FilesRepository', () => { const axiosGetStub = sandbox.stub(axios, 'get').rejects(TestConstants.TEST_ERROR_RESPONSE); let error: ReadError = undefined; - await sut.getDatasetFiles(testDatasetId, testDatasetVersionId, false).catch((e) => (error = e)); + await sut + .getDatasetFiles(testDatasetId, testDatasetVersionId, testIncludeDeaccessioned) + .catch((e) => (error = e)); assert.calledWithExactly( axiosGetStub, @@ -131,7 +135,11 @@ describe('FilesRepository', () => { const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/datasets/:persistentId/versions/${testDatasetVersionId}/files?persistentId=${TestConstants.TEST_DUMMY_PERSISTENT_ID}`; // API Key auth - let actual = await sut.getDatasetFiles(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId, false); + let actual = await sut.getDatasetFiles( + TestConstants.TEST_DUMMY_PERSISTENT_ID, + testDatasetVersionId, + testIncludeDeaccessioned, + ); assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigApiKey); assert.match(actual, expectedFiles); @@ -139,7 +147,11 @@ describe('FilesRepository', () => { // Session cookie auth ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.SESSION_COOKIE); - actual = await sut.getDatasetFiles(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId, false); + actual = await sut.getDatasetFiles( + TestConstants.TEST_DUMMY_PERSISTENT_ID, + testDatasetVersionId, + testIncludeDeaccessioned, + ); assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigSessionCookie); assert.match(actual, expectedFiles); @@ -151,7 +163,7 @@ describe('FilesRepository', () => { const actual = await sut.getDatasetFiles( TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId, - false, + testIncludeDeaccessioned, testLimit, testOffset, testFileCriteria, @@ -170,7 +182,7 @@ describe('FilesRepository', () => { let error: ReadError = undefined; await sut - .getDatasetFiles(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId, false) + .getDatasetFiles(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId, testIncludeDeaccessioned) .catch((e) => (error = e)); assert.calledWithExactly( @@ -190,6 +202,17 @@ describe('FilesRepository', () => { data: createFileCountsPayload(), }, }; + + const expectedRequestConfigApiKey = { + params: { includeDeaccessioned: testIncludeDeaccessioned }, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers, + }; + const expectedRequestConfigSessionCookie = { + params: { includeDeaccessioned: testIncludeDeaccessioned }, + withCredentials: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE.withCredentials, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE.headers, + }; + const expectedCount = createFileCountsModel(); describe('by numeric id and version id', () => { @@ -198,25 +221,17 @@ describe('FilesRepository', () => { const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/datasets/${testDatasetId}/versions/${testDatasetVersionId}/files/counts`; // API Key auth - let actual = await sut.getDatasetFileCounts(testDatasetId, testDatasetVersionId); + let actual = await sut.getDatasetFileCounts(testDatasetId, testDatasetVersionId, testIncludeDeaccessioned); - assert.calledWithExactly( - axiosGetStub, - expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY, - ); + assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigApiKey); assert.match(actual, expectedCount); // Session cookie auth ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.SESSION_COOKIE); - actual = await sut.getDatasetFileCounts(testDatasetId, testDatasetVersionId); + actual = await sut.getDatasetFileCounts(testDatasetId, testDatasetVersionId, testIncludeDeaccessioned); - assert.calledWithExactly( - axiosGetStub, - expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE, - ); + assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigSessionCookie); assert.match(actual, expectedCount); }); @@ -224,12 +239,14 @@ describe('FilesRepository', () => { const axiosGetStub = sandbox.stub(axios, 'get').rejects(TestConstants.TEST_ERROR_RESPONSE); let error: ReadError = undefined; - await sut.getDatasetFileCounts(testDatasetId, testDatasetVersionId).catch((e) => (error = e)); + await sut + .getDatasetFileCounts(testDatasetId, testDatasetVersionId, testIncludeDeaccessioned) + .catch((e) => (error = e)); assert.calledWithExactly( axiosGetStub, `${TestConstants.TEST_API_URL}/datasets/${testDatasetId}/versions/${testDatasetVersionId}/files/counts`, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY, + expectedRequestConfigApiKey, ); expect(error).to.be.instanceOf(Error); }); @@ -241,25 +258,25 @@ describe('FilesRepository', () => { const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/datasets/:persistentId/versions/${testDatasetVersionId}/files/counts?persistentId=${TestConstants.TEST_DUMMY_PERSISTENT_ID}`; // API Key auth - let actual = await sut.getDatasetFileCounts(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId); - - assert.calledWithExactly( - axiosGetStub, - expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY, + let actual = await sut.getDatasetFileCounts( + TestConstants.TEST_DUMMY_PERSISTENT_ID, + testDatasetVersionId, + testIncludeDeaccessioned, ); + + assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigApiKey); assert.match(actual, expectedCount); // Session cookie auth ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.SESSION_COOKIE); - actual = await sut.getDatasetFileCounts(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId); - - assert.calledWithExactly( - axiosGetStub, - expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE, + actual = await sut.getDatasetFileCounts( + TestConstants.TEST_DUMMY_PERSISTENT_ID, + testDatasetVersionId, + testIncludeDeaccessioned, ); + + assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigSessionCookie); assert.match(actual, expectedCount); }); @@ -268,13 +285,13 @@ describe('FilesRepository', () => { let error: ReadError = undefined; await sut - .getDatasetFileCounts(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId) + .getDatasetFileCounts(TestConstants.TEST_DUMMY_PERSISTENT_ID, testDatasetVersionId, testIncludeDeaccessioned) .catch((e) => (error = e)); assert.calledWithExactly( axiosGetStub, `${TestConstants.TEST_API_URL}/datasets/:persistentId/versions/${testDatasetVersionId}/files/counts?persistentId=${TestConstants.TEST_DUMMY_PERSISTENT_ID}`, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY, + expectedRequestConfigApiKey, ); expect(error).to.be.instanceOf(Error); }); diff --git a/test/unit/files/GetDatasetFileCounts.test.ts b/test/unit/files/GetDatasetFileCounts.test.ts index 3aa5096b..ce840967 100644 --- a/test/unit/files/GetDatasetFileCounts.test.ts +++ b/test/unit/files/GetDatasetFileCounts.test.ts @@ -23,7 +23,7 @@ describe('execute', () => { const actual = await sut.execute(1); assert.match(actual, testFileCounts); - assert.calledWithExactly(getDatasetFileCountsStub, 1, DatasetNotNumberedVersion.LATEST); + assert.calledWithExactly(getDatasetFileCountsStub, 1, DatasetNotNumberedVersion.LATEST, false); }); test('should return error result on repository error', async () => { From feaa7bf0bea1c2628d256cf334d0164e9d3535e8 Mon Sep 17 00:00:00 2001 From: GPortas Date: Mon, 25 Sep 2023 19:21:35 +0100 Subject: [PATCH 5/5] Added: friendlyType file property --- src/files/domain/models/File.ts | 1 + src/files/infra/repositories/transformers/fileTransformers.ts | 1 + test/testHelpers/files/filesHelper.ts | 2 ++ 3 files changed, 4 insertions(+) diff --git a/src/files/domain/models/File.ts b/src/files/domain/models/File.ts index 26d57985..2830d5dd 100644 --- a/src/files/domain/models/File.ts +++ b/src/files/domain/models/File.ts @@ -12,6 +12,7 @@ export interface File { datasetVersionId?: number; categories?: string[]; contentType: string; + friendlyType: string; embargo?: FileEmbargo; storageIdentifier?: string; originalFormat?: string; diff --git a/src/files/infra/repositories/transformers/fileTransformers.ts b/src/files/infra/repositories/transformers/fileTransformers.ts index 61065920..7cefd232 100644 --- a/src/files/infra/repositories/transformers/fileTransformers.ts +++ b/src/files/infra/repositories/transformers/fileTransformers.ts @@ -27,6 +27,7 @@ const transformFilePayloadToFile = (filePayload: any): File => { ...(filePayload.dataFile.datasetVersionId && { datasetVersionId: filePayload.dataFile.datasetVersionId }), ...(filePayload.dataFile.categories && { categories: filePayload.dataFile.categories }), contentType: filePayload.dataFile.contentType, + friendlyType: filePayload.dataFile.friendlyType, ...(filePayload.dataFile.embargo && { embargo: transformEmbargoPayloadToEmbargo(filePayload.dataFile.embargo) }), ...(filePayload.dataFile.storageIdentifier && { storageIdentifier: filePayload.dataFile.storageIdentifier }), ...(filePayload.dataFile.originalFormat && { originalFormat: filePayload.dataFile.originalFormat }), diff --git a/test/testHelpers/files/filesHelper.ts b/test/testHelpers/files/filesHelper.ts index f2618061..054de0b5 100644 --- a/test/testHelpers/files/filesHelper.ts +++ b/test/testHelpers/files/filesHelper.ts @@ -13,6 +13,7 @@ export const createFileModel = (): File => { restricted: false, latestRestricted: false, contentType: 'image/png', + friendlyType: 'PNG Image', storageIdentifier: 'local://18945a85439-9fa52783e5cb', rootDataFileId: 4, previousDataFileId: 4, @@ -44,6 +45,7 @@ export const createFilePayload = (): any => { persistentId: '', filename: 'test', contentType: 'image/png', + friendlyType: 'PNG Image', filesize: 127426, storageIdentifier: 'local://18945a85439-9fa52783e5cb', restricted: false,