Skip to content

Commit

Permalink
feat(#416): Update unit test for file and bulk curation changes
Browse files Browse the repository at this point in the history
  • Loading branch information
tholulomo committed Jul 18, 2023
1 parent c851901 commit 0e48dcc
Show file tree
Hide file tree
Showing 6 changed files with 413 additions and 28 deletions.
37 changes: 21 additions & 16 deletions resfulservice/spec/controllers/curationController.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,20 @@ const {
mockCurationError,
mockBulkCuration1,
mockBulkCuration2,
mockReadFolder,
next
} = require('../mocks')
const XlsxObject = require('../../src/models/curatedSamples');
const XlsxCurationList = require('../../src/models/xlsxCurationList');
const DatasetId = require('../../src/models/datasetId');
const TempFiles = require('../../src/models/temporaryFiles');
const XmlData = require('../../src/models/xmlData');
const XlsxFileManager = require('../../src/utils/curation-utility');
const FileManager = require('../../src/utils/fileManager');
const XlsxController = require('../../src/controllers/curationController');
const { createMaterialObject } = require('../../src/controllers/curationController')
const { logger } = require('../common/utils');
const latency = require('../../src/middlewares/latencyTimer');
const FileStorage = require('../../src/middlewares/fileStorage');

const { expect } = chai;

Expand All @@ -63,10 +65,6 @@ describe('Curation Controller', function() {
send: () => {}
};

const next = function (fn) {
return fn;
};

context('curateXlsxSpreadsheet', () => {
it('should return a 400 error if no file is uploaded', async function() {
sinon.stub(res, 'status').returnsThis();
Expand Down Expand Up @@ -209,8 +207,10 @@ describe('Curation Controller', function() {
sinon.stub(DatasetId, 'findOne').returns(mockDatasetId);
sinon.stub(XlsxFileManager, 'unZipFolder').returns(mockUnzippedFolder);
sinon.stub(XlsxController, 'curateXlsxSpreadsheet').returns(mockCurationError);
sinon.stub(XlsxFileManager, 'readFolder').returns(mockUnzippedFolder);
sinon.stub(TempFiles, 'insertMany').returns(true);
sinon.stub(XlsxFileManager, 'readFolder').returns({ ...mockReadFolder, folders: [] });
sinon.stub(FileStorage, 'minioPutObject').returns(true);
sinon.stub(FileManager, 'deleteFile').returns(true);
sinon.stub(FileManager, 'deleteFolder').returns(true);
sinon.stub(latency, 'latencyCalculator').returns(true)

const result = await XlsxController.bulkXlsxCurations(req, res, fn => fn);
Expand All @@ -227,10 +227,10 @@ describe('Curation Controller', function() {
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returns(mockBulkCuration1);
sinon.stub(DatasetId, 'findOne').returns(null);
sinon.stub(XlsxFileManager, 'unZipFolder').returns(mockUnzippedFolder);
sinon.stub(XlsxController, 'curateXlsxSpreadsheet').returns(mockCurationError);
sinon.stub(XlsxFileManager, 'readFolder').returns(mockUnzippedFolder);
sinon.stub(latency, 'latencyCalculator').returns(true)
// sinon.stub(XlsxFileManager, 'unZipFolder').returns(mockReadFolder);
// sinon.stub(XlsxController, 'curateXlsxSpreadsheet').returns(mockCurationError);
// sinon.stub(XlsxFileManager, 'readFolder').returns(mockUnzippedFolder);
// sinon.stub(latency, 'latencyCalculator').returns(true)

const result = await XlsxController.bulkXlsxCurations(req, res, fn => fn);
expect(result).to.have.property('message');
Expand All @@ -243,11 +243,16 @@ describe('Curation Controller', function() {
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returns(mockBulkCuration2);
sinon.stub(DatasetId, 'findOne').returns(mockDatasetId);
sinon.stub(XlsxFileManager, 'unZipFolder').returns({...mockUnzippedFolder, folders: []});
sinon.stub(XlsxController, 'curateXlsxSpreadsheet').returns({curatedSample: mockCurateObject, processedFiles: mockUnzippedFolder.curationFiles });
sinon.stub(XlsxFileManager, 'readFolder').returns(mockUnzippedFolder);
sinon.stub(TempFiles, 'insertMany').returns(true);
sinon.stub(XlsxFileManager, 'unZipFolder').returns(mockUnzippedFolder);
sinon.stub(XlsxController, 'curateXlsxSpreadsheet').returns({curatedSample: mockCurateObject, processedFiles: mockReadFolder.curationFiles });
const readFolderStub = sinon.stub(XlsxFileManager, 'readFolder');
readFolderStub.onFirstCall().returns(mockReadFolder);
readFolderStub.onSecondCall().returns({ ...mockReadFolder, folders: [] });
sinon.stub(FileManager, 'deleteFolder').returns(true);
sinon.stub(FileManager, 'deleteFile').returns(true);
sinon.stub(latency, 'latencyCalculator').returns(true)
sinon.stub(FileStorage, 'minioPutObject').returns(true);


const result = await XlsxController.bulkXlsxCurations(req, res, fn => fn);

Expand All @@ -264,7 +269,7 @@ describe('Curation Controller', function() {
sinon.stub(res, 'json').returnsThis();
sinon.stub(XlsxFileManager, 'unZipFolder').returns(mockUnzippedFolder);
sinon.stub(XlsxController, 'curateXlsxSpreadsheet').throws();
sinon.stub(TempFiles, 'insertMany').returns(true);
sinon.stub(latency, 'latencyCalculator').returns(true)

await XlsxController.bulkXlsxCurations(req, res, nextSpy);
sinon.assert.calledOnce(nextSpy);
Expand Down
204 changes: 204 additions & 0 deletions resfulservice/spec/controllers/fileController.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
const { expect } = require('chai');
const sinon = require('sinon');
const { logger } = require('../common/utils');
const { next, mockFSFiles, mockBucket, mockDownloadStream, mockEmptyStream, mockFindObjectStream } = require('../mocks');
const FileController = require('../../src/controllers/fileController');
const FsFile = require('../../src/models/fsFiles');
const FileManager = require('../../src/utils/fileManager')
const latency = require('../../src/middlewares/latencyTimer');
const minioClient = require('../../src/utils/minio');


describe('File Controller Unit Tests:', function() {
afterEach(() => sinon.restore());

const req = {
logger,
files: {},
env: { FILES_DIRECTORY: 'file_directory' }
}

const res = {
header: () => {},
status: () => {},
json: () => {},
send: () => {},
setHeader: () => {},
sendStatus: sinon.spy()
};

context('imageMigration', () => {
it('should return success when files successful upload', async () => {

req.params = { imageType: 'charts'};
const files = [[{ path: '/images/cat.png'}, { path: '/images/dog.png'}]];
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returns({ images: files });
sinon.stub(FileController, 'connectToMongoBucket').returns(mockBucket);
sinon.stub(latency, 'latencyCalculator').returns(true)
const result = await FileController.imageMigration(req, res, next);
expect(result).to.have.property('images');
});
it('should return a 500 server error', async function() {
const nextSpy = sinon.spy();
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returnsThis();
sinon.stub(FileController, 'connectToMongoBucket').throws();
await FileController.imageMigration(req, res, nextSpy);
sinon.assert.calledOnce(nextSpy);
});
});

context('fileContent', () => {
req.params = { fileId: '638dd8e9af9d478e0136ffcb' };

it('should successfully stream files from mongo bucket', async () => {
req.query = { isDirectory: false, isBucket: false };
const files = [[{ path: '/images/cat.png'}, { path: '/images/dog.png'}]];
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returns({ images: files });
sinon.stub(FsFile, 'findById').returns(mockFSFiles);
sinon.stub(FileController, 'connectToMongoBucket').returns(mockBucket);
sinon.stub(res, 'setHeader').returns(true);
sinon.stub(latency, 'latencyCalculator').returns(true)

await FileController.fileContent(req, res, next);
sinon.assert.calledOnce(mockDownloadStream.pipe);
});

it('should empty stream files from mongo bucket', async () => {
req.query = { isDirectory: false, isBucket: false };
const files = [[{ path: '/images/cat.png'}, { path: '/images/dog.png'}]];
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returns({ images: files });
sinon.stub(FsFile, 'findById').returns({ limit: sinon.stub().returns(null)});
sinon.stub(FileController, 'connectToMongoBucket').returns(mockBucket);
sinon.stub(FileController, '_createEmptyStream').returns(mockEmptyStream);
sinon.stub(res, 'setHeader').returns(true);
sinon.stub(latency, 'latencyCalculator').returns(true)

await FileController.fileContent(req, res, next);
sinon.assert.calledOnce(mockEmptyStream.pipe);
});

it('should successfully stream file from the file system', async () => {
req.query = { isDirectory: true, isBucket: false };
const files = [[{ path: '/images/cat.png'}, { path: '/images/dog.png'}]];
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returns({ images: files });
sinon.stub(FileManager, 'findFile').returns(mockDownloadStream);
sinon.stub(res, 'setHeader').returns(true);
sinon.stub(latency, 'latencyCalculator').returns(true)

await FileController.fileContent(req, res, next);
sinon.assert.calledTwice(mockDownloadStream.pipe);
});

it('should return empty stream file from the file system', async () => {
req.query = { isDirectory: true, isBucket: false };
const files = [[{ path: '/images/cat.png'}, { path: '/images/dog.png'}]];
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returns({ images: files });
sinon.stub(FileManager, 'findFile').returns(null);
sinon.stub(FileController, '_createEmptyStream').returns(mockEmptyStream);
sinon.stub(res, 'setHeader').returns(true);
sinon.stub(latency, 'latencyCalculator').returns(true)

await FileController.fileContent(req, res, next);
sinon.assert.calledTwice(mockEmptyStream.pipe);
});

it('should successfully stream file from minio bucket', async () => {
req.query = { isDirectory: false, isBucket: true };
const files = [[{ path: '/images/cat.png'}, { path: '/images/dog.png'}]];
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returns({ images: files });
sinon.stub(minioClient, 'getObject').returns(mockDownloadStream);
sinon.stub(res, 'setHeader').returns(true);
sinon.stub(latency, 'latencyCalculator').returns(true)

await FileController.fileContent(req, res, next);
sinon.assert.calledThrice(mockDownloadStream.pipe);
});

it('should return empty stream file from minio bucket', async () => {
req.query = { isDirectory: false, isBucket: true };
const files = [[{ path: '/images/cat.png'}, { path: '/images/dog.png'}]];
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returns({ images: files });
sinon.stub(minioClient, 'getObject').returns(null);
sinon.stub(FileController, '_createEmptyStream').returns(mockEmptyStream);
sinon.stub(res, 'setHeader').returns(true);
sinon.stub(latency, 'latencyCalculator').returns(true)

await FileController.fileContent(req, res, next);
sinon.assert.calledThrice(mockEmptyStream.pipe);
});

it('should return a 500 server error', async function() {
const nextSpy = sinon.spy();
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returnsThis();
sinon.stub(FileController, 'connectToMongoBucket').throws();
await FileController.fileContent(req, res, nextSpy);
sinon.assert.calledOnce(nextSpy);
});
});


context('uploadFile', () => {
it('should return success when files successful upload', async () => {
req.files = { uploadfile: [{ path: '/images/cat.png'}, { path: '/images/dog.png'}]};
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returns({ files: req.files.uploadfile });
sinon.stub(latency, 'latencyCalculator').returns(true)

const result = await FileController.uploadFile(req, res, next);

expect(result).to.have.property('files');
});
it('should return a 500 server error', async function() {
const nextSpy = sinon.spy();
req.files = { uploadfile: [{ path: '/images/cat.png'}, { path: '/images/dog.png'}]};
sinon.stub(res, 'status').throws();
// sinon.stub(res, 'json').returns({ data: response.data.hits });

await FileController.uploadFile(req, res, nextSpy);
sinon.assert.calledOnce(nextSpy);
});
});

context('deleteFile', () => {
req.params = { fileId: '638dd8e9af9d478e0136ffcb' };
it('should delete a file from both file system and minio', async () => {
sinon.stub(minioClient, 'removeObject').returns(true);
sinon.stub(FileManager, 'deleteFile').returns(true);
sinon.stub(latency, 'latencyCalculator').returns(true)

await FileController.deleteFile(req, res, next);
sinon.assert.calledOnce(res.sendStatus);
})

it('should return a 500 server error when deleting a file', async function() {
const nextSpy = sinon.spy();
sinon.stub(res, 'status').returnsThis();
sinon.stub(res, 'json').returnsThis();
sinon.stub(minioClient, 'removeObject').throws();
await FileController.deleteFile(req, res, nextSpy);
sinon.assert.calledOnce(nextSpy);
});
})

context('findFiles', () => {
req.query = { filename: '001.tif'}
it('should find files based on filename query from minio', async () => {
sinon.stub(res, 'status').returnsThis()
sinon.stub(minioClient, 'listObjects').returns(mockFindObjectStream);
sinon.stub(latency, 'latencyCalculator').returns(true)

FileController.findFiles(req, res, next);
// sinon.assert.calledThrice(mockFindObjectStream.on);
sinon.assert.called(mockFindObjectStream.on);
})
})
})
44 changes: 32 additions & 12 deletions resfulservice/spec/mocks/curationMock.js
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,25 @@ const user = {
};

const mockUnzippedFolder = {
folderPath: 'mm_files/bulk-curation-1688982949940',
allfiles: [{
mode: 33188,
mtime: '2023-05-10T11:43:10.000Z',
path: 'bulk/S10_L1/001.tif',
type: 'file',
data: '<Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 ff db 00 84 00 03 02 02 0a 0a 0a 0a 0a 0a 08 08 0a 08 0a 0a 0a 0a 08 08 0a 0a 0a 0a 0a 0a ... 57576 more bytes'
},
{
mode: 33188,
mtime: '2023-05-10T11:43:10.000Z',
path: '__MACOSX/bulk/S10_L1/._001.tif',
type: 'file',
data: '<Buffer 00 05 16 07 00 02 00 00 4d 61 63 20 4f 53 20 58 20 20 20 20 20 20 20 20 00 02 00 00 00 09 00 00 00 32 00 00 02 ce 00 00 00 02 00 00 03 00 00 00 00 00 ... 718 more bytes>'
}
]
};

const mockReadFolder = {
masterTemplates: [
'mm_files/bulk-curation-1686834726293/master_template.xlsx',
'mm_files/bulk-curation-1688984487096/master_template (1).xlsx'
Expand All @@ -1461,25 +1480,25 @@ const mockCurationError = {
};

const mockBulkCuration1 = {
bulkCurations: {},
bulkErrors: {
root: mockCurationError.errors,
'Ls-94k-askd': {
bulkCurations: [],
bulkErrors: [
{
filename: 'mm_files/bulk-curation-1686834726293/master_template.xlsx',
'001.tif': 'file not uploaded'
}
}
]
};

const mockBulkCuration2 = {
bulkCurations: {
root: mockCurateObject,
'Ls-94k-askd': mockCurateObject
},
bulkErrors: {
'Ls-95k-askd': {
bulkCurations: [
mockCurateObject
],
bulkErrors: [
{
filename: 'mm_files/bulk-curation-1686834726293/master_template.xlsx',
'001.tif': 'file not uploaded'
}
}
]
};

const mockRes = {
Expand Down Expand Up @@ -1521,5 +1540,6 @@ module.exports = {
mockCurationError,
mockBulkCuration1,
mockBulkCuration2,
mockReadFolder,
mockRes
};
Loading

0 comments on commit 0e48dcc

Please sign in to comment.