Skip to content

Commit

Permalink
Merge branch 'dev' into BHBC-1530
Browse files Browse the repository at this point in the history
  • Loading branch information
anissa-agahchen authored Dec 18, 2021
2 parents 3be935e + 6a26b5c commit 414ba8f
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 276 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import chai, { expect } from 'chai';
import chai from 'chai';
import { expect } from 'chai';
import { describe } from 'mocha';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
Expand Down Expand Up @@ -108,23 +109,6 @@ describe('uploadObservationSubmission', () => {
}
});

it('should throw a 400 error when no sql statement returned', async () => {
sinon.stub(db, 'getDBConnection').returns(dbConnectionObj);

sinon.stub(survey_occurrence_queries, 'insertSurveyOccurrenceSubmissionSQL').returns(null);
sinon.stub(file_utils, 'scanFileForVirus').resolves(true);

const result = upload.uploadMedia();

try {
await result(mockReq, mockRes, mockNext);
expect.fail();
} catch (actualError) {
expect((actualError as CustomError).status).to.equal(400);
expect((actualError as CustomError).message).to.equal('Failed to query template methodology species table');
}
});

it('should throw a 400 error when file contains malicious content', async () => {
sinon.stub(db, 'getDBConnection').returns({
...dbConnectionObj,
Expand All @@ -149,7 +133,7 @@ describe('uploadObservationSubmission', () => {
it('should throw a 400 error when it fails to insert a record in the database', async () => {
const mockQuery = sinon.stub();

mockQuery.resolves({ rowCount: 0 });
mockQuery.onCall(0).resolves(null);

sinon.stub(db, 'getDBConnection').returns({
...dbConnectionObj,
Expand Down Expand Up @@ -177,7 +161,6 @@ describe('uploadObservationSubmission', () => {
const mockQuery = sinon.stub();

mockQuery.onCall(0).resolves({ rowCount: 1, rows: [{ id: 1 }] });
mockQuery.onCall(1).resolves({ rowCount: 1, rows: [{ id: 1 }] });

sinon.stub(db, 'getDBConnection').returns({
...dbConnectionObj,
Expand Down Expand Up @@ -206,8 +189,7 @@ describe('uploadObservationSubmission', () => {
const mockQuery = sinon.stub();

mockQuery.onCall(0).resolves({ rowCount: 1, rows: [{ id: 1 }] });
mockQuery.onCall(1).resolves({ rowCount: 1, rows: [{ id: 1 }] });
mockQuery.onCall(2).resolves({ rowCount: 0 });
mockQuery.onCall(1).resolves(null);

sinon.stub(db, 'getDBConnection').returns({
...dbConnectionObj,
Expand All @@ -218,7 +200,6 @@ describe('uploadObservationSubmission', () => {
});

sinon.stub(file_utils, 'scanFileForVirus').resolves(true);
sinon.stub(survey_occurrence_queries, 'getTemplateMethodologySpeciesSQL').returns(SQL`some query`);
sinon.stub(survey_occurrence_queries, 'insertSurveyOccurrenceSubmissionSQL').returns(SQL`some query`);
sinon.stub(survey_occurrence_queries, 'updateSurveyOccurrenceSubmissionSQL').returns(SQL`some query`);

Expand All @@ -238,7 +219,6 @@ describe('uploadObservationSubmission', () => {

mockQuery.onCall(0).resolves({ rowCount: 1, rows: [{ id: 1 }] });
mockQuery.onCall(1).resolves({ rowCount: 1, rows: [{ id: 1 }] });
mockQuery.onCall(2).resolves({ rowCount: 1, rows: [{ id: 1 }] });

sinon.stub(db, 'getDBConnection').returns({
...dbConnectionObj,
Expand All @@ -249,7 +229,6 @@ describe('uploadObservationSubmission', () => {
});

sinon.stub(file_utils, 'scanFileForVirus').resolves(true);
sinon.stub(survey_occurrence_queries, 'getTemplateMethodologySpeciesSQL').returns(SQL`some query`);
sinon.stub(survey_occurrence_queries, 'insertSurveyOccurrenceSubmissionSQL').returns(SQL`some query`);
sinon.stub(survey_occurrence_queries, 'updateSurveyOccurrenceSubmissionSQL').returns(SQL`some query`);
sinon.stub(file_utils, 'uploadFileToS3').rejects('Failed to insert occurrence submission data');
Expand Down Expand Up @@ -280,7 +259,6 @@ describe('uploadObservationSubmission', () => {
});

sinon.stub(file_utils, 'scanFileForVirus').resolves(true);
sinon.stub(survey_occurrence_queries, 'getTemplateMethodologySpeciesSQL').returns(SQL`some query`);
sinon.stub(survey_occurrence_queries, 'insertSurveyOccurrenceSubmissionSQL').returns(SQL`some query`);
sinon.stub(survey_occurrence_queries, 'updateSurveyOccurrenceSubmissionSQL').returns(SQL`some query`);
sinon.stub(file_utils, 'uploadFileToS3').resolves({ key: 'projects/1/surveys/1/test.txt' } as any);
Expand Down Expand Up @@ -324,33 +302,4 @@ describe('uploadObservationSubmission', () => {
expect((actualError as CustomError).message).to.equal('Failed to build SQL insert statement');
}
});

it('should throw a 400 error when it fails to get the getTemplateMethodologySpeciesId SQL', async () => {
const mockQuery = sinon.stub();

mockQuery.onCall(0).resolves({ rowCount: 1, rows: [{ id: 1 }] });

sinon.stub(db, 'getDBConnection').returns({
...dbConnectionObj,
systemUserId: () => {
return 20;
},
query: mockQuery
});

sinon.stub(file_utils, 'scanFileForVirus').resolves(true);
sinon.stub(survey_occurrence_queries, 'getTemplateMethodologySpeciesIdSQL').returns(null);

const result = upload.uploadMedia();

try {
await result(mockReq, mockRes, mockNext);
expect.fail();
} catch (actualError) {
expect((actualError as CustomError).status).to.equal(400);
expect((actualError as CustomError).message).to.equal(
'Failed to build SQL get template methodology species id sql statement'
);
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import { getDBConnection, IDBConnection } from '../../../../../../../database/db
import { HTTP400 } from '../../../../../../../errors/CustomError';
import {
insertSurveyOccurrenceSubmissionSQL,
updateSurveyOccurrenceSubmissionSQL,
getTemplateMethodologySpeciesIdSQL
updateSurveyOccurrenceSubmissionSQL
} from '../../../../../../../queries/survey/survey-occurrence-queries';
import { authorizeRequestHandler } from '../../../../../../../request-handlers/security/authorization';
import { generateS3FileKey, scanFileForVirus, uploadFileToS3 } from '../../../../../../../utils/file-utils';
Expand Down Expand Up @@ -138,16 +137,10 @@ export function uploadMedia(): RequestHandler {
throw new HTTP400('Malicious content detected, upload cancelled');
}

// TODO: TEMP - To test Goat templates, use templateMethodologyId 4 or 5
// TODO: TEMP - To test Sheep templates, use templateMethodologyId 6 or 7

const templateMethodologyId = await getTemplateMethodologySpeciesId(Number(req.params.surveyId), connection);

const response = await insertSurveyOccurrenceSubmission(
Number(req.params.surveyId),
'BioHub',
rawMediaFile.originalname,
templateMethodologyId,
connection
);

Expand Down Expand Up @@ -190,22 +183,19 @@ export function uploadMedia(): RequestHandler {
* @param {number} surveyId
* @param {string} source
* @param {string} inputFileName
* @param {(number | null)} templateMethodologyId
* @param {IDBConnection} connection
* @return {*} {Promise<void>}
*/
export const insertSurveyOccurrenceSubmission = async (
surveyId: number,
source: string,
inputFileName: string,
templateMethodologyId: number | null,
connection: IDBConnection
): Promise<any> => {
const insertSqlStatement = insertSurveyOccurrenceSubmissionSQL({
surveyId,
source,
inputFileName,
templateMethodologyId
inputFileName
});

if (!insertSqlStatement) {
Expand All @@ -221,31 +211,6 @@ export const insertSurveyOccurrenceSubmission = async (
return insertResponse;
};

/**
* Inserts a new record into the `occurrence_submission` table.
*
* @param {number} surveyId
* @param {IDBConnection} connection
* @return {*} {Promise<void>}
*/
export const getTemplateMethodologySpeciesId = async (
surveyId: number,
connection: IDBConnection
): Promise<number | null> => {
const getIdSqlStatement = getTemplateMethodologySpeciesIdSQL(surveyId);

if (!getIdSqlStatement) {
throw new HTTP400('Failed to build SQL get template methodology species id sql statement');
}
const getIdResponse = await connection.query(getIdSqlStatement.text, getIdSqlStatement.values);

if (!getIdResponse) {
throw new HTTP400('Failed to query template methodology species table');
}

return getIdResponse?.rows?.[0]?.template_methodology_species_id || null;
};

/**
* Update existing `occurrence_submission` record with inputKey.
*
Expand Down
60 changes: 0 additions & 60 deletions api/src/paths/xlsx/transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import chai, { expect } from 'chai';
import { describe } from 'mocha';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import { getMockDBConnection } from '../../__mocks__/db';
import * as transform from './transform';
import * as validate from './validate';
import * as db from '../../database/db';

chai.use(sinonChai);

Expand Down Expand Up @@ -47,60 +44,3 @@ describe('persistParseErrors', () => {
expect(actualResult).to.eql({ status: 'failed', reason: 'Unable to parse submission' });
});
});

describe('getTransformationSchema', () => {
const sampleReq = {
keycloak_token: {},
body: {
occurrence_submission_id: 1
}
} as any;

let actualResult: any = null;

const sampleRes = {
status: () => {
return {
json: (result: any) => {
actualResult = result;
}
};
}
};

const dbConnectionObj = getMockDBConnection();

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

it('should return with a failed status if no transformationSchema', async () => {
sinon.stub(db, 'getDBConnection').returns({ ...dbConnectionObj, systemUserId: () => 20 });
sinon.stub(validate, 'getTemplateMethodologySpecies').resolves({
transform: null
});

const result = transform.getTransformationSchema();
await result(sampleReq, sampleRes as any, (null as unknown) as any);

expect(actualResult).to.eql({
status: 'failed',
reason: 'Unable to fetch an appropriate transformation schema for your submission'
});
});

it('should set the transformationSchema in the request and call next on success', async () => {
const nextSpy = sinon.spy();

sinon.stub(db, 'getDBConnection').returns({ ...dbConnectionObj, systemUserId: () => 20 });
sinon.stub(validate, 'getTemplateMethodologySpecies').resolves({
transform: 'transform'
});

const result = transform.getTransformationSchema();
await result(sampleReq, (null as unknown) as any, nextSpy as any);

expect(sampleReq.transformationSchema).to.eql('transform');
expect(nextSpy).to.have.been.called;
});
});
13 changes: 10 additions & 3 deletions api/src/paths/xlsx/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { getLogger } from '../../utils/logger';
import { TransformationSchemaParser } from '../../utils/media/xlsx/transformation/transformation-schema-parser';
import { XLSXTransformation } from '../../utils/media/xlsx/transformation/xlsx-transformation';
import { XLSXCSV } from '../../utils/media/xlsx/xlsx-file';
import { getTemplateMethodologySpecies, prepXLSX } from './validate';
import { getTemplateMethodologySpeciesRecord, prepXLSX } from './validate';

const defaultLog = getLogger('paths/xlsx/transform');

Expand Down Expand Up @@ -136,8 +136,15 @@ export function getTransformationSchema(): RequestHandler {
try {
await connection.open();

const templateMethodologySpeciesRecord = await getTemplateMethodologySpecies(
req.body.occurrence_submission_id,
const xlsxCsv = req['xlsx'];
const template_id = xlsxCsv.workbook.rawWorkbook.Custprops.sims_template_id;
const species_id = xlsxCsv.workbook.rawWorkbook.Custprops.sims_species_id;
const csm_id = xlsxCsv.workbook.rawWorkbook.Custprops.sims_csm_id;

const templateMethodologySpeciesRecord = await getTemplateMethodologySpeciesRecord(
Number(species_id),
Number(csm_id),
Number(template_id),
connection
);

Expand Down
31 changes: 20 additions & 11 deletions api/src/paths/xlsx/validate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,23 +53,25 @@ describe('prepXLSX', () => {
});
});

describe('getTemplateMethodologySpecies', () => {
describe('getTemplateMethodologySpeciesRecord', () => {
afterEach(() => {
sinon.restore();
});

const dbConnectionObj = getMockDBConnection();

it('should throw 400 error when failed to build getTemplateMethodologySpeciesSQL statement', async () => {
sinon.stub(survey_occurrence_queries, 'getTemplateMethodologySpeciesSQL').returns(null);
it('should throw 400 error when failed to build getTemplateMethodologySpeciesRecordSQL statement', async () => {
sinon.stub(survey_occurrence_queries, 'getTemplateMethodologySpeciesRecordSQL').returns(null);

try {
await validate.getTemplateMethodologySpecies(1, { ...dbConnectionObj, systemUserId: () => 20 });
await validate.getTemplateMethodologySpeciesRecord(1234, 1, 1, { ...dbConnectionObj, systemUserId: () => 20 });

expect.fail();
} catch (actualError) {
expect((actualError as CustomError).status).to.equal(400);
expect((actualError as CustomError).message).to.equal('Failed to build SQL get statement');
expect((actualError as CustomError).message).to.equal(
'Failed to build SQL get template methodology species record sql statement'
);
}
});

Expand All @@ -80,11 +82,18 @@ describe('getTemplateMethodologySpecies', () => {
rows: [null]
});

sinon.stub(survey_occurrence_queries, 'getTemplateMethodologySpeciesSQL').returns(SQL`something`);
sinon.stub(survey_occurrence_queries, 'getTemplateMethodologySpeciesRecordSQL').returns(SQL`something`);

const result = await validate.getTemplateMethodologySpecies(1, { ...dbConnectionObj, systemUserId: () => 20 });

expect(result).to.equal(null);
try {
await validate.getTemplateMethodologySpeciesRecord(1234, 1, 1, {
...dbConnectionObj,
systemUserId: () => 20
});
expect.fail();
} catch (actualError) {
expect((actualError as CustomError).status).to.equal(400);
expect((actualError as CustomError).message).to.equal('Failed to query template methodology species table');
}
});

it('should return first row on success', async () => {
Expand All @@ -98,9 +107,9 @@ describe('getTemplateMethodologySpecies', () => {
]
});

sinon.stub(survey_occurrence_queries, 'getTemplateMethodologySpeciesSQL').returns(SQL`something`);
sinon.stub(survey_occurrence_queries, 'getTemplateMethodologySpeciesRecordSQL').returns(SQL`something`);

const result = await validate.getTemplateMethodologySpecies(1, {
const result = await validate.getTemplateMethodologySpeciesRecord(1234, 1, 1, {
...dbConnectionObj,
query: mockQuery,
systemUserId: () => 20
Expand Down
Loading

0 comments on commit 414ba8f

Please sign in to comment.