Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/useCases.md
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,8 @@ The `fileId` parameter can be a string, for persistent identifiers, or a number,

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`.

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`.

#### Get a File and its Dataset

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.
Expand Down Expand Up @@ -1036,6 +1038,8 @@ The `fileId` parameter can be a string, for persistent identifiers, or a number,

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`.

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`.

#### Get File Citation Text

Returns the File citation text.
Expand Down
3 changes: 2 additions & 1 deletion src/files/domain/repositories/IFilesRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ export interface IFilesRepository {
getFile(
fileId: number | string,
datasetVersionId: string,
returnDatasetVersion: boolean
returnDatasetVersion: boolean,
includeDeaccessioned: boolean
): Promise<FileModel | [FileModel, Dataset]>

getFileCitation(
Expand Down
11 changes: 9 additions & 2 deletions src/files/domain/useCases/GetFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,19 @@ export class GetFile implements UseCase<FileModel> {
*
* @param {number | string} [fileId] - The File identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers).
* @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
* @param {boolean} [includeDeaccessioned=false] - If true, the file will be returned even if it has been deaccessioned.
* @returns {Promise<FileModel>}
*/
async execute(
fileId: number | string,
datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST
datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST,
includeDeaccessioned = false
): Promise<FileModel> {
return (await this.filesRepository.getFile(fileId, datasetVersionId, false)) as FileModel
return (await this.filesRepository.getFile(
fileId,
datasetVersionId,
false,
includeDeaccessioned
)) as FileModel
}
}
14 changes: 9 additions & 5 deletions src/files/domain/useCases/GetFileAndDataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@ export class GetFileAndDataset implements UseCase<[FileModel, Dataset]> {
*
* @param {number | string} [fileId] - The File identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers).
* @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
* @param {boolean} [includeDeaccessioned=false] - If true, the file will be returned even if it has been deaccessioned.
* @returns {Promise<[FileModel, Dataset]>}
*/
async execute(
fileId: number | string,
datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST
datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST,
includeDeaccessioned = false
): Promise<[FileModel, Dataset]> {
return (await this.filesRepository.getFile(fileId, datasetVersionId, true)) as [
FileModel,
Dataset
]
return (await this.filesRepository.getFile(
fileId,
datasetVersionId,
true,
includeDeaccessioned
)) as [FileModel, Dataset]
}
}
6 changes: 4 additions & 2 deletions src/files/infra/repositories/FilesRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,14 +196,16 @@ export class FilesRepository extends ApiRepository implements IFilesRepository {
public async getFile(
fileId: number | string,
datasetVersionId: string,
returnDatasetVersion: boolean
returnDatasetVersion: boolean,
includeDeaccessioned: boolean
): Promise<FileModel | [FileModel, Dataset]> {
return this.doGet(
this.buildApiEndpoint(this.filesResourceName, `versions/${datasetVersionId}`, fileId),
true,
{
returnDatasetVersion: returnDatasetVersion,
returnOwners: true
returnOwners: true,
includeDeaccessioned: includeDeaccessioned
}
)
.then((response) => transformFileResponseToFile(response, returnDatasetVersion))
Expand Down
89 changes: 81 additions & 8 deletions test/integration/files/FilesRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import {
} from '../../../src/files/domain/models/FileCriteria'
import {
DatasetNotNumberedVersion,
Dataset,
CreatedDatasetIdentifiers,
createDataset
createDataset,
Dataset
} from '../../../src/datasets'
import { FileModel } from '../../../src/files/domain/models/FileModel'
import { FileCounts } from '../../../src/files/domain/models/FileCounts'
Expand Down Expand Up @@ -474,6 +474,7 @@ describe('FilesRepository', () => {
const actual: FileModel = (await sut.getFile(
testFileId,
DatasetNotNumberedVersion.LATEST,
false,
false
)) as FileModel

Expand All @@ -484,17 +485,20 @@ describe('FilesRepository', () => {
const actual: FileModel = (await sut.getFile(
testFileId,
DatasetNotNumberedVersion.DRAFT,
false,
false
)) as FileModel

expect(actual.name).toBe(testTextFile1Name)
})

test('should return file and dataset when providing id, version, and returnDatasetVersion is true', async () => {
const actual = (await sut.getFile(testFileId, DatasetNotNumberedVersion.DRAFT, true)) as [
FileModel,
Dataset
]
const actual = (await sut.getFile(
testFileId,
DatasetNotNumberedVersion.DRAFT,
true,
false
)) as [FileModel, Dataset]

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

await expect(
sut.getFile(nonExistentFiledId, DatasetNotNumberedVersion.LATEST, false)
sut.getFile(nonExistentFiledId, DatasetNotNumberedVersion.LATEST, false, false)
).rejects.toThrow(expectedError)
})
})

describe('getFile with deaccessioned dataset', () => {
const testTextFile1Name = 'test-file-1.txt'

let deaccessionedFileTestDatasetIds: CreatedDatasetIdentifiers
let deaccessionedTestFileId: number

beforeAll(async () => {
deaccessionedFileTestDatasetIds = await createDataset.execute(
TestConstants.TEST_NEW_DATASET_DTO
)

await uploadFileViaApi(deaccessionedFileTestDatasetIds.numericId, testTextFile1Name).catch(
() => {
throw new Error(`Error while uploading file ${testTextFile1Name}`)
}
)

await publishDatasetViaApi(deaccessionedFileTestDatasetIds.numericId).catch(() => {
throw new Error('Error while publishing test Dataset')
})

await waitForNoLocks(deaccessionedFileTestDatasetIds.numericId, 10).catch(() => {
throw new Error('Error while waiting for no locks')
})

const datasetFiles = await sut.getDatasetFiles(
deaccessionedFileTestDatasetIds.numericId,
latestDatasetVersionId,
false,
FileOrderCriteria.NAME_AZ
)
deaccessionedTestFileId = datasetFiles.files[0].id

await deaccessionDatasetViaApi(deaccessionedFileTestDatasetIds.numericId, '1.0').catch(
() => {
throw new Error('Error while deaccessioning the dataset')
}
)
})

afterAll(async () => {
await deletePublishedDatasetViaApi(deaccessionedFileTestDatasetIds.persistentId).catch(
() => {
throw new Error('Error while deleting the test dataset')
}
)
})

test('should return file if dataset is deaccessioned, and includeDeaccessioned is true', async () => {
const actual = (await sut.getFile(deaccessionedTestFileId, '1.0', false, true)) as FileModel

expect(actual.name).toBe(testTextFile1Name)
})

test('should throw error if dataset is deaccessioned, and includeDeaccessioned is false', async () => {
const expectedError = new ReadError(
`[404] "File metadata for file with id ${deaccessionedTestFileId} in dataset version 1.0 not found"`
)

await expect(sut.getFile(deaccessionedTestFileId, '1.0', false, false)).rejects.toThrow(
expectedError
)
})
})

describe('by persistent id', () => {
test('should return file when providing a valid persistent id', async () => {
const actual = (await sut.getFile(
testFilePersistentId,
DatasetNotNumberedVersion.LATEST,
false,
false
)) as FileModel

Expand All @@ -523,6 +594,7 @@ describe('FilesRepository', () => {
const actual = (await sut.getFile(
testFilePersistentId,
DatasetNotNumberedVersion.DRAFT,
false,
false
)) as FileModel

Expand All @@ -536,7 +608,7 @@ describe('FilesRepository', () => {
)

await expect(
sut.getFile(nonExistentFiledPersistentId, DatasetNotNumberedVersion.LATEST, false)
sut.getFile(nonExistentFiledPersistentId, DatasetNotNumberedVersion.LATEST, false, false)
).rejects.toThrow(expectedError)
})
})
Expand Down Expand Up @@ -672,6 +744,7 @@ describe('FilesRepository', () => {
const fileInfo: FileModel = (await sut.getFile(
testFileId,
DatasetNotNumberedVersion.LATEST,
false,
false
)) as FileModel

Expand Down
10 changes: 7 additions & 3 deletions test/unit/files/FilesRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@ describe('FilesRepository', () => {
}

const expectedRequestParams = {
includeDeaccessioned: false,
returnDatasetVersion: false,
returnOwners: true
}
Expand Down Expand Up @@ -1043,13 +1044,13 @@ describe('FilesRepository', () => {
jest.spyOn(axios, 'get').mockResolvedValue(testGetFileResponse)

// API Key auth
let actual = await sut.getFile(testFile.id, DatasetNotNumberedVersion.LATEST, false)
let actual = await sut.getFile(testFile.id, DatasetNotNumberedVersion.LATEST, false, false)
expect(axios.get).toHaveBeenCalledWith(expectedApiEndpoint, expectedRequestConfigApiKey)
expect(actual).toEqual(createFileModel())

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

await expect(
sut.getFile(testFile.id, DatasetNotNumberedVersion.LATEST, false)
sut.getFile(testFile.id, DatasetNotNumberedVersion.LATEST, false, false)
).rejects.toThrow(ReadError)
})
})
Expand All @@ -1076,6 +1077,7 @@ describe('FilesRepository', () => {
let actual = await sut.getFile(
TestConstants.TEST_DUMMY_PERSISTENT_ID,
DatasetNotNumberedVersion.LATEST,
false,
false
)
expect(axios.get).toHaveBeenCalledWith(expectedApiEndpoint, expectedRequestConfigApiKey)
Expand All @@ -1086,6 +1088,7 @@ describe('FilesRepository', () => {
actual = await sut.getFile(
TestConstants.TEST_DUMMY_PERSISTENT_ID,
DatasetNotNumberedVersion.LATEST,
false,
false
)
expect(axios.get).toHaveBeenCalledWith(
Expand All @@ -1102,6 +1105,7 @@ describe('FilesRepository', () => {
sut.getFile(
TestConstants.TEST_DUMMY_PERSISTENT_ID,
DatasetNotNumberedVersion.LATEST,
false,
false
)
).rejects.toThrow(ReadError)
Expand Down
31 changes: 30 additions & 1 deletion test/unit/files/GetFile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ describe('execute', () => {
expect(filesRepositoryStub.getFile).toHaveBeenCalledWith(
1,
DatasetNotNumberedVersion.LATEST,
false,
false
)
})
Expand All @@ -33,6 +34,7 @@ describe('execute', () => {
expect(filesRepositoryStub.getFile).toHaveBeenCalledWith(
'doi:10.5072/FK2/J8SJZB',
DatasetNotNumberedVersion.LATEST,
false,
false
)
})
Expand All @@ -47,7 +49,34 @@ describe('execute', () => {
const actual = await sut.execute('doi:10.5072/FK2/J8SJZB', '2.0')

expect(actual).toEqual(testFile)
expect(filesRepositoryStub.getFile).toHaveBeenCalledWith('doi:10.5072/FK2/J8SJZB', '2.0', false)
expect(filesRepositoryStub.getFile).toHaveBeenCalledWith(
'doi:10.5072/FK2/J8SJZB',
'2.0',
false,
false
)
})

test('should return file on repository success when includeDeaccession is true', async () => {
const testFile = createFileModel()
const filesRepositoryStub: IFilesRepository = {} as IFilesRepository
filesRepositoryStub.getFile = jest.fn().mockResolvedValue(testFile)

const sut = new GetFile(filesRepositoryStub)

const actual = await sut.execute(
'doi:10.5072/FK2/J8SJZB',
DatasetNotNumberedVersion.LATEST,
true
)

expect(actual).toEqual(testFile)
expect(filesRepositoryStub.getFile).toHaveBeenCalledWith(
'doi:10.5072/FK2/J8SJZB',
DatasetNotNumberedVersion.LATEST,
false,
true
)
})

test('should return error result on repository error', async () => {
Expand Down
Loading