Skip to content

Commit cebb64c

Browse files
authored
Merge pull request #322 from IQSS/321-file-add-includedeaccessioned-parameter-to-the-getfile
Update includeDeaccessioned to GetFile use case
2 parents 531b543 + 7080016 commit cebb64c

File tree

9 files changed

+177
-25
lines changed

9 files changed

+177
-25
lines changed

docs/useCases.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,8 @@ The `fileId` parameter can be a string, for persistent identifiers, or a number,
10071007

10081008
The optional `datasetVersionId` parameter can correspond to a numeric version identifier, as in the previous example, or a [DatasetNotNumberedVersion](../src/datasets/domain/models/DatasetNotNumberedVersion.ts) enum value. If not set, the default value is `DatasetNotNumberedVersion.LATEST`.
10091009

1010+
There is an optional third parameter called `includeDeaccessioned`, which indicates whether to consider deaccessioned versions or not in the file search. If not set, the default value is `false`.
1011+
10101012
#### Get a File and its Dataset
10111013

10121014
Returns a tuple of [FileModel](../src/files/domain/models/FileModel.ts) and [Dataset](../src/datasets/domain/models/Dataset.ts) objects (`[FileModel, Dataset]`), given the search parameters to identify the file.
@@ -1036,6 +1038,8 @@ The `fileId` parameter can be a string, for persistent identifiers, or a number,
10361038

10371039
The optional `datasetVersionId` parameter can correspond to a numeric version identifier, as in the previous example, or a [DatasetNotNumberedVersion](../src/datasets/domain/models/DatasetNotNumberedVersion.ts) enum value. If not set, the default value is `DatasetNotNumberedVersion.LATEST`.
10381040

1041+
There is an optional third parameter called `includeDeaccessioned`, which indicates whether to consider deaccessioned versions or not in the file search. If not set, the default value is `false`.
1042+
10391043
#### Get File Citation Text
10401044

10411045
Returns the File citation text.

src/files/domain/repositories/IFilesRepository.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ export interface IFilesRepository {
4747
getFile(
4848
fileId: number | string,
4949
datasetVersionId: string,
50-
returnDatasetVersion: boolean
50+
returnDatasetVersion: boolean,
51+
includeDeaccessioned: boolean
5152
): Promise<FileModel | [FileModel, Dataset]>
5253

5354
getFileCitation(

src/files/domain/useCases/GetFile.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,19 @@ export class GetFile implements UseCase<FileModel> {
1111
*
1212
* @param {number | string} [fileId] - The File identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers).
1313
* @param {string | DatasetNotNumberedVersion} [datasetVersionId=DatasetNotNumberedVersion.LATEST] - The dataset version identifier, which can be a version-specific numeric string (for example, 1.0) or a DatasetNotNumberedVersion enum value. If this parameter is not set, the default value is: DatasetNotNumberedVersion.LATEST
14+
* @param {boolean} [includeDeaccessioned=false] - If true, the file will be returned even if it has been deaccessioned.
1415
* @returns {Promise<FileModel>}
1516
*/
1617
async execute(
1718
fileId: number | string,
18-
datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST
19+
datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST,
20+
includeDeaccessioned = false
1921
): Promise<FileModel> {
20-
return (await this.filesRepository.getFile(fileId, datasetVersionId, false)) as FileModel
22+
return (await this.filesRepository.getFile(
23+
fileId,
24+
datasetVersionId,
25+
false,
26+
includeDeaccessioned
27+
)) as FileModel
2128
}
2229
}

src/files/domain/useCases/GetFileAndDataset.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,19 @@ export class GetFileAndDataset implements UseCase<[FileModel, Dataset]> {
1111
*
1212
* @param {number | string} [fileId] - The File identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers).
1313
* @param {string | DatasetNotNumberedVersion} [datasetVersionId=DatasetNotNumberedVersion.LATEST] - The dataset version identifier, which can be a version-specific numeric string (for example, 1.0) or a DatasetNotNumberedVersion enum value. If this parameter is not set, the default value is: DatasetNotNumberedVersion.LATEST
14+
* @param {boolean} [includeDeaccessioned=false] - If true, the file will be returned even if it has been deaccessioned.
1415
* @returns {Promise<[FileModel, Dataset]>}
1516
*/
1617
async execute(
1718
fileId: number | string,
18-
datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST
19+
datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST,
20+
includeDeaccessioned = false
1921
): Promise<[FileModel, Dataset]> {
20-
return (await this.filesRepository.getFile(fileId, datasetVersionId, true)) as [
21-
FileModel,
22-
Dataset
23-
]
22+
return (await this.filesRepository.getFile(
23+
fileId,
24+
datasetVersionId,
25+
true,
26+
includeDeaccessioned
27+
)) as [FileModel, Dataset]
2428
}
2529
}

src/files/infra/repositories/FilesRepository.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,16 @@ export class FilesRepository extends ApiRepository implements IFilesRepository {
196196
public async getFile(
197197
fileId: number | string,
198198
datasetVersionId: string,
199-
returnDatasetVersion: boolean
199+
returnDatasetVersion: boolean,
200+
includeDeaccessioned: boolean
200201
): Promise<FileModel | [FileModel, Dataset]> {
201202
return this.doGet(
202203
this.buildApiEndpoint(this.filesResourceName, `versions/${datasetVersionId}`, fileId),
203204
true,
204205
{
205206
returnDatasetVersion: returnDatasetVersion,
206-
returnOwners: true
207+
returnOwners: true,
208+
includeDeaccessioned: includeDeaccessioned
207209
}
208210
)
209211
.then((response) => transformFileResponseToFile(response, returnDatasetVersion))

test/integration/files/FilesRepository.test.ts

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ import {
2323
} from '../../../src/files/domain/models/FileCriteria'
2424
import {
2525
DatasetNotNumberedVersion,
26-
Dataset,
2726
CreatedDatasetIdentifiers,
28-
createDataset
27+
createDataset,
28+
Dataset
2929
} from '../../../src/datasets'
3030
import { FileModel } from '../../../src/files/domain/models/FileModel'
3131
import { FileCounts } from '../../../src/files/domain/models/FileCounts'
@@ -474,6 +474,7 @@ describe('FilesRepository', () => {
474474
const actual: FileModel = (await sut.getFile(
475475
testFileId,
476476
DatasetNotNumberedVersion.LATEST,
477+
false,
477478
false
478479
)) as FileModel
479480

@@ -484,17 +485,20 @@ describe('FilesRepository', () => {
484485
const actual: FileModel = (await sut.getFile(
485486
testFileId,
486487
DatasetNotNumberedVersion.DRAFT,
488+
false,
487489
false
488490
)) as FileModel
489491

490492
expect(actual.name).toBe(testTextFile1Name)
491493
})
492494

493495
test('should return file and dataset when providing id, version, and returnDatasetVersion is true', async () => {
494-
const actual = (await sut.getFile(testFileId, DatasetNotNumberedVersion.DRAFT, true)) as [
495-
FileModel,
496-
Dataset
497-
]
496+
const actual = (await sut.getFile(
497+
testFileId,
498+
DatasetNotNumberedVersion.DRAFT,
499+
true,
500+
false
501+
)) as [FileModel, Dataset]
498502

499503
expect(actual[0].name).toBe(testTextFile1Name)
500504
expect(actual[1].id).toBe(testDatasetIds.numericId)
@@ -504,15 +508,82 @@ describe('FilesRepository', () => {
504508
const expectedError = new ReadError(`[404] File with ID ${nonExistentFiledId} not found.`)
505509

506510
await expect(
507-
sut.getFile(nonExistentFiledId, DatasetNotNumberedVersion.LATEST, false)
511+
sut.getFile(nonExistentFiledId, DatasetNotNumberedVersion.LATEST, false, false)
508512
).rejects.toThrow(expectedError)
509513
})
510514
})
515+
516+
describe('getFile with deaccessioned dataset', () => {
517+
const testTextFile1Name = 'test-file-1.txt'
518+
519+
let deaccessionedFileTestDatasetIds: CreatedDatasetIdentifiers
520+
let deaccessionedTestFileId: number
521+
522+
beforeAll(async () => {
523+
deaccessionedFileTestDatasetIds = await createDataset.execute(
524+
TestConstants.TEST_NEW_DATASET_DTO
525+
)
526+
527+
await uploadFileViaApi(deaccessionedFileTestDatasetIds.numericId, testTextFile1Name).catch(
528+
() => {
529+
throw new Error(`Error while uploading file ${testTextFile1Name}`)
530+
}
531+
)
532+
533+
await publishDatasetViaApi(deaccessionedFileTestDatasetIds.numericId).catch(() => {
534+
throw new Error('Error while publishing test Dataset')
535+
})
536+
537+
await waitForNoLocks(deaccessionedFileTestDatasetIds.numericId, 10).catch(() => {
538+
throw new Error('Error while waiting for no locks')
539+
})
540+
541+
const datasetFiles = await sut.getDatasetFiles(
542+
deaccessionedFileTestDatasetIds.numericId,
543+
latestDatasetVersionId,
544+
false,
545+
FileOrderCriteria.NAME_AZ
546+
)
547+
deaccessionedTestFileId = datasetFiles.files[0].id
548+
549+
await deaccessionDatasetViaApi(deaccessionedFileTestDatasetIds.numericId, '1.0').catch(
550+
() => {
551+
throw new Error('Error while deaccessioning the dataset')
552+
}
553+
)
554+
})
555+
556+
afterAll(async () => {
557+
await deletePublishedDatasetViaApi(deaccessionedFileTestDatasetIds.persistentId).catch(
558+
() => {
559+
throw new Error('Error while deleting the test dataset')
560+
}
561+
)
562+
})
563+
564+
test('should return file if dataset is deaccessioned, and includeDeaccessioned is true', async () => {
565+
const actual = (await sut.getFile(deaccessionedTestFileId, '1.0', false, true)) as FileModel
566+
567+
expect(actual.name).toBe(testTextFile1Name)
568+
})
569+
570+
test('should throw error if dataset is deaccessioned, and includeDeaccessioned is false', async () => {
571+
const expectedError = new ReadError(
572+
`[404] "File metadata for file with id ${deaccessionedTestFileId} in dataset version 1.0 not found"`
573+
)
574+
575+
await expect(sut.getFile(deaccessionedTestFileId, '1.0', false, false)).rejects.toThrow(
576+
expectedError
577+
)
578+
})
579+
})
580+
511581
describe('by persistent id', () => {
512582
test('should return file when providing a valid persistent id', async () => {
513583
const actual = (await sut.getFile(
514584
testFilePersistentId,
515585
DatasetNotNumberedVersion.LATEST,
586+
false,
516587
false
517588
)) as FileModel
518589

@@ -523,6 +594,7 @@ describe('FilesRepository', () => {
523594
const actual = (await sut.getFile(
524595
testFilePersistentId,
525596
DatasetNotNumberedVersion.DRAFT,
597+
false,
526598
false
527599
)) as FileModel
528600

@@ -536,7 +608,7 @@ describe('FilesRepository', () => {
536608
)
537609

538610
await expect(
539-
sut.getFile(nonExistentFiledPersistentId, DatasetNotNumberedVersion.LATEST, false)
611+
sut.getFile(nonExistentFiledPersistentId, DatasetNotNumberedVersion.LATEST, false, false)
540612
).rejects.toThrow(expectedError)
541613
})
542614
})
@@ -672,6 +744,7 @@ describe('FilesRepository', () => {
672744
const fileInfo: FileModel = (await sut.getFile(
673745
testFileId,
674746
DatasetNotNumberedVersion.LATEST,
747+
false,
675748
false
676749
)) as FileModel
677750

test/unit/files/FilesRepository.test.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,7 @@ describe('FilesRepository', () => {
10161016
}
10171017

10181018
const expectedRequestParams = {
1019+
includeDeaccessioned: false,
10191020
returnDatasetVersion: false,
10201021
returnOwners: true
10211022
}
@@ -1043,13 +1044,13 @@ describe('FilesRepository', () => {
10431044
jest.spyOn(axios, 'get').mockResolvedValue(testGetFileResponse)
10441045

10451046
// API Key auth
1046-
let actual = await sut.getFile(testFile.id, DatasetNotNumberedVersion.LATEST, false)
1047+
let actual = await sut.getFile(testFile.id, DatasetNotNumberedVersion.LATEST, false, false)
10471048
expect(axios.get).toHaveBeenCalledWith(expectedApiEndpoint, expectedRequestConfigApiKey)
10481049
expect(actual).toEqual(createFileModel())
10491050

10501051
// Session cookie auth
10511052
ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.SESSION_COOKIE)
1052-
actual = await sut.getFile(testFile.id, DatasetNotNumberedVersion.LATEST, false)
1053+
actual = await sut.getFile(testFile.id, DatasetNotNumberedVersion.LATEST, false, false)
10531054
expect(axios.get).toHaveBeenCalledWith(
10541055
expectedApiEndpoint,
10551056
expectedRequestConfigSessionCookie
@@ -1061,7 +1062,7 @@ describe('FilesRepository', () => {
10611062
jest.spyOn(axios, 'get').mockRejectedValue(TestConstants.TEST_ERROR_RESPONSE)
10621063

10631064
await expect(
1064-
sut.getFile(testFile.id, DatasetNotNumberedVersion.LATEST, false)
1065+
sut.getFile(testFile.id, DatasetNotNumberedVersion.LATEST, false, false)
10651066
).rejects.toThrow(ReadError)
10661067
})
10671068
})
@@ -1076,6 +1077,7 @@ describe('FilesRepository', () => {
10761077
let actual = await sut.getFile(
10771078
TestConstants.TEST_DUMMY_PERSISTENT_ID,
10781079
DatasetNotNumberedVersion.LATEST,
1080+
false,
10791081
false
10801082
)
10811083
expect(axios.get).toHaveBeenCalledWith(expectedApiEndpoint, expectedRequestConfigApiKey)
@@ -1086,6 +1088,7 @@ describe('FilesRepository', () => {
10861088
actual = await sut.getFile(
10871089
TestConstants.TEST_DUMMY_PERSISTENT_ID,
10881090
DatasetNotNumberedVersion.LATEST,
1091+
false,
10891092
false
10901093
)
10911094
expect(axios.get).toHaveBeenCalledWith(
@@ -1102,6 +1105,7 @@ describe('FilesRepository', () => {
11021105
sut.getFile(
11031106
TestConstants.TEST_DUMMY_PERSISTENT_ID,
11041107
DatasetNotNumberedVersion.LATEST,
1108+
false,
11051109
false
11061110
)
11071111
).rejects.toThrow(ReadError)

test/unit/files/GetFile.test.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ describe('execute', () => {
1616
expect(filesRepositoryStub.getFile).toHaveBeenCalledWith(
1717
1,
1818
DatasetNotNumberedVersion.LATEST,
19+
false,
1920
false
2021
)
2122
})
@@ -33,6 +34,7 @@ describe('execute', () => {
3334
expect(filesRepositoryStub.getFile).toHaveBeenCalledWith(
3435
'doi:10.5072/FK2/J8SJZB',
3536
DatasetNotNumberedVersion.LATEST,
37+
false,
3638
false
3739
)
3840
})
@@ -47,7 +49,34 @@ describe('execute', () => {
4749
const actual = await sut.execute('doi:10.5072/FK2/J8SJZB', '2.0')
4850

4951
expect(actual).toEqual(testFile)
50-
expect(filesRepositoryStub.getFile).toHaveBeenCalledWith('doi:10.5072/FK2/J8SJZB', '2.0', false)
52+
expect(filesRepositoryStub.getFile).toHaveBeenCalledWith(
53+
'doi:10.5072/FK2/J8SJZB',
54+
'2.0',
55+
false,
56+
false
57+
)
58+
})
59+
60+
test('should return file on repository success when includeDeaccession is true', async () => {
61+
const testFile = createFileModel()
62+
const filesRepositoryStub: IFilesRepository = {} as IFilesRepository
63+
filesRepositoryStub.getFile = jest.fn().mockResolvedValue(testFile)
64+
65+
const sut = new GetFile(filesRepositoryStub)
66+
67+
const actual = await sut.execute(
68+
'doi:10.5072/FK2/J8SJZB',
69+
DatasetNotNumberedVersion.LATEST,
70+
true
71+
)
72+
73+
expect(actual).toEqual(testFile)
74+
expect(filesRepositoryStub.getFile).toHaveBeenCalledWith(
75+
'doi:10.5072/FK2/J8SJZB',
76+
DatasetNotNumberedVersion.LATEST,
77+
false,
78+
true
79+
)
5180
})
5281

5382
test('should return error result on repository error', async () => {

0 commit comments

Comments
 (0)