Skip to content

Commit

Permalink
feat: add totalFilesCount to GetDatasetFiles use case
Browse files Browse the repository at this point in the history
  • Loading branch information
MellyGray committed Jan 17, 2024
1 parent 02d7882 commit 2788a3d
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 51 deletions.
6 changes: 6 additions & 0 deletions src/files/domain/models/FilesSubset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { File } from "./File";

export interface FilesSubset {
files: File[];
totalFilesCount: number;
}
4 changes: 2 additions & 2 deletions src/files/domain/repositories/IFilesRepository.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { File } from '../models/File';
import { FilesSubset } from "../models/FilesSubset";
import { FileDataTable } from '../models/FileDataTable';
import { FileUserPermissions } from '../models/FileUserPermissions';
import { FileSearchCriteria, FileOrderCriteria } from '../models/FileCriteria';
Expand All @@ -14,7 +14,7 @@ export interface IFilesRepository {
limit?: number,
offset?: number,
fileSearchCriteria?: FileSearchCriteria,
): Promise<File[]>;
): Promise<FilesSubset>;

getDatasetFileCounts(
datasetId: number | string,
Expand Down
6 changes: 3 additions & 3 deletions src/files/domain/useCases/GetDatasetFiles.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { UseCase } from '../../../core/domain/useCases/UseCase';
import { IFilesRepository } from '../repositories/IFilesRepository';
import { File } from '../models/File';
import { FilesSubset } from "../models/FilesSubset";
import { FileSearchCriteria, FileOrderCriteria } from '../models/FileCriteria';
import { DatasetNotNumberedVersion } from '../../../datasets';

export class GetDatasetFiles implements UseCase<File[]> {
export class GetDatasetFiles implements UseCase<FilesSubset> {
private filesRepository: IFilesRepository;

constructor(filesRepository: IFilesRepository) {
Expand All @@ -19,7 +19,7 @@ export class GetDatasetFiles implements UseCase<File[]> {
offset?: number,
fileSearchCriteria?: FileSearchCriteria,
fileOrderCriteria: FileOrderCriteria = FileOrderCriteria.NAME_AZ,
): Promise<File[]> {
): Promise<FilesSubset> {
return await this.filesRepository.getDatasetFiles(
datasetId,
datasetVersionId,
Expand Down
8 changes: 4 additions & 4 deletions src/files/infra/repositories/FilesRepository.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ApiRepository } from '../../../core/infra/repositories/ApiRepository';
import { IFilesRepository } from '../../domain/repositories/IFilesRepository';
import { File } from '../../domain/models/File';
import { transformFilesResponseToFiles } from './transformers/fileTransformers';
import {FilesSubset} from "../../domain/models/FilesSubset";
import { transformFilesResponseToFilesSubset } from './transformers/fileTransformers';
import { FileDataTable } from '../../domain/models/FileDataTable';
import { transformDataTablesResponseToDataTables } from './transformers/fileDataTableTransformers';
import { FileUserPermissions } from '../../domain/models/FileUserPermissions';
Expand Down Expand Up @@ -46,7 +46,7 @@ export class FilesRepository extends ApiRepository implements IFilesRepository {
limit?: number,
offset?: number,
fileSearchCriteria?: FileSearchCriteria,
): Promise<File[]> {
): Promise<FilesSubset> {
const queryParams: GetFilesQueryParams = {
includeDeaccessioned: includeDeaccessioned,
orderCriteria: fileOrderCriteria.toString(),
Expand All @@ -65,7 +65,7 @@ export class FilesRepository extends ApiRepository implements IFilesRepository {
true,
queryParams,
)
.then((response) => transformFilesResponseToFiles(response))
.then((response) => transformFilesResponseToFilesSubset(response))
.catch((error) => {
throw error;
});
Expand Down
17 changes: 12 additions & 5 deletions src/files/infra/repositories/transformers/fileTransformers.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { File, FileEmbargo, FileChecksum } from '../../../domain/models/File';
import { AxiosResponse } from 'axios';
import { FilesSubset } from "../../../domain/models/FilesSubset";

export const transformFilesResponseToFiles = (response: AxiosResponse): File[] => {
const files: File[] = [];
export const transformFilesResponseToFilesSubset = (
response: AxiosResponse,
): FilesSubset => {
const filesPayload = response.data.data;
const files: File[] = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
filesPayload.forEach(function (filePayload: any) {
files.push(transformFilePayloadToFile(filePayload));
filesPayload.forEach(function (filesPayload: any) {
files.push(transformFilePayloadToFile(filesPayload));
});
return files;

return {
files: files,
totalFilesCount: response.data.totalCount,
};
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down
70 changes: 38 additions & 32 deletions test/integration/files/FilesRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,12 @@ describe('FilesRepository', () => {
false,
FileOrderCriteria.NAME_AZ,
);
assert.match(actual.length, 4);
assert.match(actual[0].name, testTextFile1Name);
assert.match(actual[1].name, testTextFile2Name);
assert.match(actual[2].name, testTextFile3Name);
assert.match(actual[3].name, testTabFile4Name);
assert.match(actual.files.length, 4);
assert.match(actual.files[0].name, testTextFile1Name);
assert.match(actual.files[1].name, testTextFile2Name);
assert.match(actual.files[2].name, testTextFile3Name);
assert.match(actual.files[3].name, testTabFile4Name);
assert.match(actual.totalFilesCount, 4);
});

test('should return correct files filtering by dataset id, version id, and paginating', async () => {
Expand All @@ -89,12 +90,13 @@ describe('FilesRepository', () => {
3,
undefined,
);
assert.match(actual.length, 1);
assert.match(actual[0].name, testTabFile4Name);
assert.match(actual.files.length, 1);
assert.match(actual.files[0].name, testTabFile4Name);
assert.match(actual.totalFilesCount, 4);
});

test('should return correct files filtering by dataset id, version id, and applying newest file criteria', async () => {
let actual = await sut.getDatasetFiles(
const actual = await sut.getDatasetFiles(
TestConstants.TEST_CREATED_DATASET_1_ID,
latestDatasetVersionId,
false,
Expand All @@ -103,10 +105,11 @@ describe('FilesRepository', () => {
undefined,
testFileCriteria,
);
assert.match(actual.length, 3);
assert.match(actual[0].name, testTextFile3Name);
assert.match(actual[1].name, testTextFile2Name);
assert.match(actual[2].name, testTextFile1Name);
assert.match(actual.files.length, 3);
assert.match(actual.files[0].name, testTextFile3Name);
assert.match(actual.files[1].name, testTextFile2Name);
assert.match(actual.files[2].name, testTextFile1Name);
assert.match(actual.totalFilesCount, 4);
});

test('should return error when dataset does not exist', async () => {
Expand Down Expand Up @@ -137,11 +140,12 @@ describe('FilesRepository', () => {
false,
FileOrderCriteria.NAME_AZ,
);
assert.match(actual.length, 4);
assert.match(actual[0].name, testTextFile1Name);
assert.match(actual[1].name, testTextFile2Name);
assert.match(actual[2].name, testTextFile3Name);
assert.match(actual[3].name, testTabFile4Name);
assert.match(actual.files.length, 4);
assert.match(actual.files[0].name, testTextFile1Name);
assert.match(actual.files[1].name, testTextFile2Name);
assert.match(actual.files[2].name, testTextFile3Name);
assert.match(actual.files[3].name, testTabFile4Name);
assert.match(actual.totalFilesCount, 4);
});

test('should return correct files filtering by persistent id, version id, and paginating', async () => {
Expand All @@ -159,8 +163,9 @@ describe('FilesRepository', () => {
3,
undefined,
);
assert.match(actual.length, 1);
assert.match(actual[0].name, testTabFile4Name);
assert.match(actual.files.length, 1);
assert.match(actual.files[0].name, testTabFile4Name);
assert.match(actual.totalFilesCount, 4);
});

test('should return correct files filtering by persistent id, version id, and applying newest file criteria', async () => {
Expand All @@ -169,7 +174,7 @@ describe('FilesRepository', () => {
latestDatasetVersionId,
false,
);
let actual = await sut.getDatasetFiles(
const actual = await sut.getDatasetFiles(
testDataset.persistentId,
latestDatasetVersionId,
false,
Expand All @@ -178,10 +183,11 @@ describe('FilesRepository', () => {
undefined,
testFileCriteria,
);
assert.match(actual.length, 3);
assert.match(actual[0].name, testTextFile3Name);
assert.match(actual[1].name, testTextFile2Name);
assert.match(actual[2].name, testTextFile1Name);
assert.match(actual.files.length, 3);
assert.match(actual.files[0].name, testTextFile3Name);
assert.match(actual.files[1].name, testTextFile2Name);
assert.match(actual.files[2].name, testTextFile1Name);
assert.match(actual.totalFilesCount, 4);
});

test('should return error when dataset does not exist', async () => {
Expand Down Expand Up @@ -332,13 +338,13 @@ describe('FilesRepository', () => {

describe('getFileDownloadCount', () => {
test('should return count filtering by file id and version id', async () => {
const currentTestFiles = await sut.getDatasetFiles(
const currentTestFilesSubset = await sut.getDatasetFiles(
TestConstants.TEST_CREATED_DATASET_1_ID,
latestDatasetVersionId,
false,
FileOrderCriteria.NAME_AZ,
);
const testFile = currentTestFiles[0];
const testFile = currentTestFilesSubset.files[0];
const actual = await sut.getFileDownloadCount(testFile.id);
assert.match(actual, 0);
});
Expand All @@ -357,13 +363,13 @@ describe('FilesRepository', () => {

describe('getFileUserPermissions', () => {
test('should return user permissions filtering by file id and version id', async () => {
const currentTestFiles = await sut.getDatasetFiles(
const currentTestFilesSubset = await sut.getDatasetFiles(
TestConstants.TEST_CREATED_DATASET_1_ID,
latestDatasetVersionId,
false,
FileOrderCriteria.NAME_AZ,
);
const testFile = currentTestFiles[0];
const testFile = currentTestFilesSubset.files[0];
const actual = await sut.getFileUserPermissions(testFile.id);
assert.match(actual.canDownloadFile, true);
assert.match(actual.canManageFilePermissions, true);
Expand All @@ -384,25 +390,25 @@ describe('FilesRepository', () => {

describe('getFileDataTables', () => {
test('should return data tables filtering by tabular file id and version id', async () => {
const currentTestFiles = await sut.getDatasetFiles(
const currentTestFilesSubset = await sut.getDatasetFiles(
TestConstants.TEST_CREATED_DATASET_1_ID,
latestDatasetVersionId,
false,
FileOrderCriteria.NAME_AZ,
);
const testFile = currentTestFiles[3];
const testFile = currentTestFilesSubset.files[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(
const currentTestFilesSubset = await sut.getDatasetFiles(
TestConstants.TEST_CREATED_DATASET_1_ID,
latestDatasetVersionId,
false,
FileOrderCriteria.NAME_AZ,
);
const testFile = currentTestFiles[0];
const testFile = currentTestFilesSubset.files[0];

let error: ReadError = undefined;

Expand Down
16 changes: 16 additions & 0 deletions test/testHelpers/files/filesHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { File } from '../../../src/files/domain/models/File';
import axios, { AxiosResponse } from 'axios';
import { TestConstants } from '../TestConstants';
import { readFile } from 'fs/promises';
import {FilesSubset} from "../../../src/files/domain/models/FilesSubset";

interface FileMetadata {
categories?: string[]
Expand Down Expand Up @@ -38,6 +39,17 @@ export const createFileModel = (): File => {
};
};

export const createManyFilesModel = (amount: number): File[] => {
return Array.from({ length: amount }, () => createFileModel());
}

export const createFilesSubsetModel = (amount: number): FilesSubset => {
return {
files: createManyFilesModel(amount),
totalFilesCount: amount,
};
}

export const createFilePayload = (): any => {
return {
label: 'test',
Expand Down Expand Up @@ -74,6 +86,10 @@ export const createFilePayload = (): any => {
};
};

export const createManyFilesPayload = (amount: number): any[] => {
return Array.from({ length: amount }, () => createFilePayload());
}

export const uploadFileViaApi = async (datasetId: number, fileName: string, fileMetadata?: FileMetadata): Promise<AxiosResponse> => {
const formData = new FormData();
const file = await readFile(`${__dirname}/${fileName}`);
Expand Down
16 changes: 11 additions & 5 deletions test/unit/files/FilesRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { expect } from 'chai';
import { ReadError } from '../../../src/core/domain/repositories/ReadError';
import { ApiConfig, DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig';
import { TestConstants } from '../../testHelpers/TestConstants';
import { createFilePayload, createFileModel } from '../../testHelpers/files/filesHelper';
import {
createFileModel,
createManyFilesPayload,
createFilesSubsetModel
} from '../../testHelpers/files/filesHelper';
import { createFileDataTablePayload, createFileDataTableModel } from '../../testHelpers/files/fileDataTablesHelper';
import { createFileUserPermissionsModel } from '../../testHelpers/files/fileUserPermissionsHelper';
import { FileSearchCriteria, FileAccessStatus, FileOrderCriteria } from '../../../src/files/domain/models/FileCriteria';
Expand Down Expand Up @@ -40,10 +44,12 @@ describe('FilesRepository', () => {
});

describe('getDatasetFiles', () => {
const testTotalCount = 4;
const testFilesSuccessfulResponse = {
data: {
status: 'OK',
data: [createFilePayload()],
data: createManyFilesPayload(testTotalCount),
totalCount: testTotalCount,
},
};

Expand Down Expand Up @@ -77,7 +83,7 @@ describe('FilesRepository', () => {
headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers,
};

const expectedFiles = [testFile];
const expectedFiles = createFilesSubsetModel(testTotalCount);

describe('by numeric id and version id', () => {
const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/datasets/${testDatasetId}/versions/${testDatasetVersionId}/files`;
Expand Down Expand Up @@ -124,7 +130,7 @@ describe('FilesRepository', () => {
);

assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigApiKeyWithOptional);
assert.match(actual, [testFile]);
assert.match(actual, expectedFiles);
});

test('should return error result on error response', async () => {
Expand Down Expand Up @@ -185,7 +191,7 @@ describe('FilesRepository', () => {
);

assert.calledWithExactly(axiosGetStub, expectedApiEndpoint, expectedRequestConfigApiKeyWithOptional);
assert.match(actual, [testFile]);
assert.match(actual, expectedFiles);
});

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

0 comments on commit 2788a3d

Please sign in to comment.