Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

117- Create use case to get the file citation #125

Merged
merged 5 commits into from
Feb 19, 2024
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
1 change: 1 addition & 0 deletions src/files/domain/repositories/IFilesRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ export interface IFilesRepository {
getFileDataTables(fileId: number | string): Promise<FileDataTable[]>;

getFile(fileId: number | string, datasetVersionId: string): Promise<File>;
getFileCitation(fileId: number | string, datasetVersionId: string, includeDeaccessioned: boolean): Promise<string>;
}
19 changes: 19 additions & 0 deletions src/files/domain/useCases/GetFileCitation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { UseCase } from '../../../core/domain/useCases/UseCase';
import { IFilesRepository } from '../repositories/IFilesRepository';
import { DatasetNotNumberedVersion } from '../../../datasets';

export class GetFileCitation implements UseCase<string> {
private filesRepository: IFilesRepository;

constructor(filesRepository: IFilesRepository) {
this.filesRepository = filesRepository;
}

async execute(
fileId: number,
datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST,
includeDeaccessioned = false,
): Promise<string> {
return await this.filesRepository.getFileCitation(fileId, datasetVersionId, includeDeaccessioned);
}
}
3 changes: 3 additions & 0 deletions src/files/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { GetFileUserPermissions } from './domain/useCases/GetFileUserPermissions
import { GetFileDataTables } from './domain/useCases/GetFileDataTables';
import { GetDatasetFilesTotalDownloadSize } from './domain/useCases/GetDatasetFilesTotalDownloadSize';
import { GetFile } from './domain/useCases/GetFile';
import { GetFileCitation } from './domain/useCases/GetFileCitation';

const filesRepository = new FilesRepository();

Expand All @@ -16,6 +17,7 @@ const getFileUserPermissions = new GetFileUserPermissions(filesRepository);
const getFileDataTables = new GetFileDataTables(filesRepository);
const getDatasetFilesTotalDownloadSize = new GetDatasetFilesTotalDownloadSize(filesRepository);
const getFile = new GetFile(filesRepository);
const getFileCitation = new GetFileCitation(filesRepository);

export {
getDatasetFiles,
Expand All @@ -25,6 +27,7 @@ export {
getDatasetFileCounts,
getDatasetFilesTotalDownloadSize,
getFile,
getFileCitation,
};

export { File, FileEmbargo, FileChecksum } from './domain/models/File';
Expand Down
16 changes: 16 additions & 0 deletions src/files/infra/repositories/FilesRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,22 @@ export class FilesRepository extends ApiRepository implements IFilesRepository {
});
}

public async getFileCitation(
fileId: number | string,
datasetVersionId: string,
includeDeaccessioned: boolean,
): Promise<string> {
return this.doGet(
this.buildApiEndpoint(this.filesResourceName, `versions/${datasetVersionId}/citation`, fileId),
true,
{ includeDeaccessioned: includeDeaccessioned },
)
.then((response) => response.data.data.message)
.catch((error) => {
throw error;
});
}

private getFileEndpoint(fileId: number | string, datasetVersionId: string): string {
if (datasetVersionId === DatasetNotNumberedVersion.DRAFT) {
return this.buildApiEndpoint(this.filesResourceName, 'draft', fileId);
Expand Down
7 changes: 1 addition & 6 deletions test/integration/datasets/DatasetsRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,6 @@ describe('DatasetsRepository', () => {
expect(actual.id).toBe(TestConstants.TEST_CREATED_DATASET_1_ID);
});

test('should return dataset when it exists filtering by id and version id', async () => {
const actual = await sut.getDataset(TestConstants.TEST_CREATED_DATASET_1_ID, latestVersionId, false);
expect(actual.id).toBe(TestConstants.TEST_CREATED_DATASET_1_ID);
});

test('should return dataset when it is deaccessioned and includeDeaccessioned param is set', async () => {
await publishDatasetViaApi(TestConstants.TEST_CREATED_DATASET_2_ID)
.then()
Expand Down Expand Up @@ -238,7 +233,7 @@ describe('DatasetsRepository', () => {
assert.match(actual.length, 1);
assert.match(actual[0].lockType, DatasetLockType.FINALIZE_PUBLICATION);
assert.match(actual[0].userId, 'dataverseAdmin');
assert.match(actual[0].message, 'Publishing the dataset; Validating Datafiles Asynchronously');
assert.match(actual[0].message, 'Publishing the dataset; Registering PIDs for Datafiles; Validating Datafiles Asynchronously');
});

test('should return error when dataset does not exist', async () => {
Expand Down
48 changes: 48 additions & 0 deletions test/integration/files/FilesRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { DatasetNotNumberedVersion } from '../../../src/datasets';
import { FileCounts } from '../../../src/files/domain/models/FileCounts';
import { FileDownloadSizeMode } from '../../../src';
import { fail } from 'assert';
import {deaccessionDatasetViaApi, publishDatasetViaApi, waitForNoLocks} from "../../testHelpers/datasets/datasetHelper";

describe('FilesRepository', () => {
const sut: FilesRepository = new FilesRepository();
Expand Down Expand Up @@ -519,4 +520,51 @@ describe('FilesRepository', () => {
});
});
});
describe('getFileCitation', () => {
test('should return citation when file exists', async () => {
const actualFileCitation = await sut.getFileCitation(
testFileId,
DatasetNotNumberedVersion.LATEST,
false,
);
expect(typeof actualFileCitation).to.be.a('string');
});

test('should return citation when dataset is deaccessioned', async () => {
await publishDatasetViaApi(TestConstants.TEST_CREATED_DATASET_1_ID)
.then()
.catch(() => {
assert.fail('Error while publishing test Dataset');
});

await waitForNoLocks(TestConstants.TEST_CREATED_DATASET_1_ID, 10)
.then()
.catch(() => {
assert.fail('Error while waiting for no locks');
});

await deaccessionDatasetViaApi(TestConstants.TEST_CREATED_DATASET_1_ID, '1.0')
.then()
.catch(() => {
assert.fail('Error while deaccessioning test Dataset');
});

const actualFileCitation = await sut.getFileCitation(
testFileId,
DatasetNotNumberedVersion.LATEST,
true,
);
expect(typeof actualFileCitation).to.be.a('string');
});

test('should return error when file does not exist', async () => {
let error: ReadError = undefined;
await sut.getFileCitation(nonExistentFiledId, DatasetNotNumberedVersion.LATEST, false).catch((e) => (error = e));

assert.match(
error.message,
`There was an error when reading the resource. Reason was: [404] File with ID ${nonExistentFiledId} not found.`,
);
});
});
});
53 changes: 53 additions & 0 deletions test/unit/files/FilesRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -874,4 +874,57 @@ describe('FilesRepository', () => {
});
});
});

describe('getFileCitation', () => {
const testIncludeDeaccessioned = true;
const testCitation = 'test citation';
const testCitationSuccessfulResponse = {
data: {
status: 'OK',
data: {
message: testCitation,
},
},
};
test('should return citation when response is successful', async () => {
const axiosGetStub = sandbox.stub(axios, 'get').resolves(testCitationSuccessfulResponse);
const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/files/${testFile.id}/versions/${DatasetNotNumberedVersion.LATEST}/citation`;

// API Key auth
let actual = await sut.getFileCitation(testFile.id, DatasetNotNumberedVersion.LATEST, testIncludeDeaccessioned);

assert.calledWithExactly(
axiosGetStub,
expectedApiEndpoint,
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.getFileCitation(testFile.id, DatasetNotNumberedVersion.LATEST, testIncludeDeaccessioned);

assert.calledWithExactly(
axiosGetStub,
expectedApiEndpoint,
TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE_INCLUDE_DEACCESSIONED,
);
assert.match(actual, testCitation);
});

test('should return error on repository read error', async () => {
const axiosGetStub = sandbox.stub(axios, 'get').rejects(TestConstants.TEST_ERROR_RESPONSE);

let error: ReadError = undefined;
await sut.getFileCitation(1, DatasetNotNumberedVersion.LATEST, testIncludeDeaccessioned).catch((e) => (error = e));

assert.calledWithExactly(
axiosGetStub,
`${TestConstants.TEST_API_URL}/files/${testFile.id}/versions/${DatasetNotNumberedVersion.LATEST}/citation`,
TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY_INCLUDE_DEACCESSIONED,
);
expect(error).to.be.instanceOf(Error);
});
});
});
39 changes: 39 additions & 0 deletions test/unit/files/GetFileCitation.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {assert, createSandbox, SinonSandbox} from "sinon";
import {DatasetNotNumberedVersion, ReadError} from "../../../src";
import {IFilesRepository} from "../../../src/files/domain/repositories/IFilesRepository";
import {GetFileCitation} from "../../../src/files/domain/useCases/GetFileCitation";

describe('execute', () => {
const sandbox: SinonSandbox = createSandbox();
const testId = 1;

afterEach(() => {
sandbox.restore();
});

test('should return successful result with file citation on repository success', async () => {
const testCitation = 'test citation';
const filesRepositoryStub = <IFilesRepository>{};
const getFileCitation = sandbox.stub().returns(testCitation);
filesRepositoryStub.getFileCitation = getFileCitation;

const sut = new GetFileCitation(filesRepositoryStub);

const actual = await sut.execute(testId);

assert.match(actual, testCitation);
assert.calledWithExactly(getFileCitation, testId, DatasetNotNumberedVersion.LATEST, false);
});

test('should return error result on repository error', async () => {
const filesRepositoryStub = <IFilesRepository>{};
const testReadError = new ReadError();
filesRepositoryStub.getFileCitation = sandbox.stub().throwsException(testReadError);
const sut = new GetFileCitation(filesRepositoryStub);

let actualError: ReadError = undefined;
await sut.execute(testId).catch((e) => (actualError = e));

assert.match(actualError, testReadError);
});
})
Loading