From ba97ffc2bc112773d7006c8317888582f6785395 Mon Sep 17 00:00:00 2001 From: Anugerah Erlaut Date: Tue, 25 May 2021 17:44:44 +0700 Subject: [PATCH] Address comments pr 126 (#128) * add route test * add test for getListOfExperiments --- .../route-services/__mocks__/experiment.js | 7 ++ src/api/route-services/__mocks__/projects.js | 14 ++++ src/api/route-services/experiment.js | 2 +- src/specs/api.yaml | 2 +- tests/api/route-services/experiment.test.js | 30 ++++++++ tests/api/route-services/projects.test.js | 69 +++++++++++-------- tests/api/routes/projects.test.js | 24 +++++++ tests/test-utils/mockAWSServices.js | 11 +++ 8 files changed, 130 insertions(+), 29 deletions(-) diff --git a/src/api/route-services/__mocks__/experiment.js b/src/api/route-services/__mocks__/experiment.js index 19470e5bf..1661f69ee 100644 --- a/src/api/route-services/__mocks__/experiment.js +++ b/src/api/route-services/__mocks__/experiment.js @@ -5,6 +5,12 @@ const mockExperimentData = jest.fn((experimentId) => new Promise((resolve) => { }); })); +const mockGetListOfExperiments = jest.fn((experimentIds) => new Promise((resolve) => { + resolve(experimentIds.map((experimentId) => ({ + experimentId, + }))); +})); + const mockGetCellSets = jest.fn(() => new Promise((resolve) => { resolve({ cellSets: [ @@ -102,6 +108,7 @@ const mockUpdateProcessingConfig = jest.fn( const mock = jest.fn().mockImplementation(() => ({ getExperimentData: mockExperimentData, + getListOfExperiments: mockGetListOfExperiments, getCellSets: mockGetCellSets, updateCellSets: mockUpdateCellSets, getProcessingConfig: mockGetProcessingConfig, diff --git a/src/api/route-services/__mocks__/projects.js b/src/api/route-services/__mocks__/projects.js index ef3c8a180..1d9599655 100644 --- a/src/api/route-services/__mocks__/projects.js +++ b/src/api/route-services/__mocks__/projects.js @@ -8,6 +8,19 @@ const mockGetProject = jest.fn((projectUuid) => new Promise((resolve) => { resolve(OK()); })); +const mockGetExperiments = jest.fn((projectUuid) => new Promise((resolve) => { + if (projectUuid === 'unknown-project') { + throw new NotFoundError('Project not found'); + } + + resolve([ + { + experimentId: 'mock-experiment', + name: 'someExperiments', + }, + ]); +})); + const mockUpdateProject = jest.fn((projectUuid) => new Promise((resolve) => { if (projectUuid === 'unknown-project') { throw new NotFoundError('Project not found'); @@ -25,6 +38,7 @@ const mockDeleteProject = jest.fn((projectUuid) => new Promise((resolve) => { })); const mock = jest.fn().mockImplementation(() => ({ + getExperiments: mockGetExperiments, getProject: mockGetProject, updateProject: mockUpdateProject, deleteProject: mockDeleteProject, diff --git a/src/api/route-services/experiment.js b/src/api/route-services/experiment.js index c51b0d9f9..c9a0297f8 100644 --- a/src/api/route-services/experiment.js +++ b/src/api/route-services/experiment.js @@ -53,7 +53,7 @@ class ExperimentService { const params = { RequestItems: { [this.experimentsTableName]: { - Keys: [...experimentIds].map((experimentId) => convertToDynamoDbRecord({ experimentId })), + Keys: experimentIds.map((experimentId) => convertToDynamoDbRecord({ experimentId })), }, }, }; diff --git a/src/specs/api.yaml b/src/specs/api.yaml index 9d392d8c5..7bd9acbe0 100644 --- a/src/specs/api.yaml +++ b/src/specs/api.yaml @@ -711,7 +711,7 @@ paths: items: $ref: ./models/api-body-schemas/Experiment.v1.yaml '401': - description: Not Found + description: Unauthorized content: application/json: schema: diff --git a/tests/api/route-services/experiment.test.js b/tests/api/route-services/experiment.test.js index 1fcaa945c..66950015e 100644 --- a/tests/api/route-services/experiment.test.js +++ b/tests/api/route-services/experiment.test.js @@ -7,6 +7,7 @@ const { mockDynamoUpdateItem, mockS3GetObject, mockS3PutObject, + mockDynamoBatchGetItem, } = require('../../test-utils/mockAWSServices'); jest.setTimeout(30000); @@ -38,6 +39,35 @@ describe('tests for the experiment service', () => { .then(() => done()); }); + it('Get list of experiments work', async (done) => { + const experimentIds = ['experiment-1', 'experiment-2', 'experiment-3']; + + const response = { + Responses: { + 'experiments-test': experimentIds.map((experimentId) => AWS.DynamoDB.Converter.marshall({ experimentId })), + }, + }; + + const fnSpy = mockDynamoBatchGetItem(response); + + (new ExperimentService()).getListOfExperiments(experimentIds) + .then((data) => { + expect(data).toEqual(experimentIds.map((experimentId) => ({ experimentId }))); + expect(fnSpy).toHaveBeenCalledWith( + { + RequestItems: { + 'experiments-test': { + Keys: experimentIds.map( + (experimentId) => AWS.DynamoDB.Converter.marshall({ experimentId }), + ), + }, + }, + }, + ); + }) + .then(() => done()); + }); + it('Get cell sets works', async (done) => { const jsData = { cellSets: [ diff --git a/tests/api/route-services/projects.test.js b/tests/api/route-services/projects.test.js index e96364e6c..9c512c591 100644 --- a/tests/api/route-services/projects.test.js +++ b/tests/api/route-services/projects.test.js @@ -2,35 +2,38 @@ const AWSMock = require('aws-sdk-mock'); const AWS = require('../../../src/utils/requireAWS'); const ProjectsService = require('../../../src/api/route-services/projects'); +const ExperimentsService = require('../../../src/api/route-services/experiment'); const { mockDynamoUpdateItem, mockDynamoDeleteItem, mockDynamoGetItem } = require('../../test-utils/mockAWSServices'); const { OK } = require('../../../src/utils/responses'); +jest.mock('../../../src/api/route-services/experiment'); + describe('tests for the projects service', () => { + const mockProject = { + name: 'Test project', + description: '', + createdDate: '', + lastModified: '', + uuid: 'project-1', + experiments: ['experiment-1'], + lastAnalyzed: null, + samples: [], + }; + afterEach(() => { AWSMock.restore('DynamoDB'); }); it('GetProject gets project and samples properly', async (done) => { - const project = { - name: 'Test project', - description: '', - createdDate: '', - lastModified: '', - uuid: 'project-1', - experiments: [], - lastAnalyzed: null, - samples: [], - }; - const marshalledKey = AWS.DynamoDB.Converter.marshall({ projectUuid: 'project-1', }); - const getFnSpy = mockDynamoGetItem({ projects: project }); + const getFnSpy = mockDynamoGetItem({ projects: mockProject }); (new ProjectsService()).getProject('project-1') .then((res) => { - expect(res).toEqual(project); + expect(res).toEqual(mockProject); expect(getFnSpy).toHaveBeenCalledWith({ TableName: 'projects-test', Key: marshalledKey, @@ -39,29 +42,41 @@ describe('tests for the projects service', () => { .then(() => done()); }); - it('UpdateProject updates project properly', async (done) => { - const jsData = { - name: 'Test project', - description: '', - createdDate: '', - lastModified: '', - uuid: 'project-1', - experiments: [], - lastAnalyzed: null, - samples: [], - }; + it('GetExperiments gets projects', async (done) => { + const fnSpy = mockDynamoGetItem({ projects: mockProject }); + + const experimentsService = new ExperimentsService(); + const marshalledKey = AWS.DynamoDB.Converter.marshall({ + projectUuid: mockProject.projectUuid, + }); + + (new ProjectsService()).getExperiments() + .then((res) => { + expect(res).toEqual([{ experimentId: mockProject.experiments[0] }]); + expect(fnSpy).toHaveBeenCalledWith({ + TableName: 'projects-test', + Key: marshalledKey, + }); + expect( + experimentsService.getListOfExperiments, + ).toHaveBeenCalledWith(mockProject.experiments); + }) + .then(() => done()); + }); + + it('UpdateProject updates project properly', async (done) => { const marshalledKey = AWS.DynamoDB.Converter.marshall({ projectUuid: 'project-1', }); const marshalledData = AWS.DynamoDB.Converter.marshall({ - ':project': jsData, + ':project': mockProject, }); - const getItemSpy = mockDynamoUpdateItem({ projects: jsData }); + const getItemSpy = mockDynamoUpdateItem({ projects: mockProject }); - (new ProjectsService()).updateProject('project-1', jsData) + (new ProjectsService()).updateProject('project-1', mockProject) .then((res) => { expect(res).toEqual(OK()); expect(getItemSpy).toHaveBeenCalledWith({ diff --git a/tests/api/routes/projects.test.js b/tests/api/routes/projects.test.js index 6c07fed05..5e129cb3f 100644 --- a/tests/api/routes/projects.test.js +++ b/tests/api/routes/projects.test.js @@ -17,6 +17,30 @@ describe('tests for projects route', () => { jest.restoreAllMocks(); }); + it('Getting project experiments send 200', async (done) => { + request(app) + .get('/v1/projects/someId/experiments') + .expect(200) + .end((err) => { + if (err) { + return done(err); + } + return done(); + }); + }); + + it('Getting project experiments send 404 if id is not found', async (done) => { + request(app) + .get('/v1/projects/unknown-project/experiments') + .expect(404) + .end((err) => { + if (err) { + return done(err); + } + return done(); + }); + }); + it('Updating project send 200', async (done) => { const payload = { name: 'Test project', diff --git a/tests/test-utils/mockAWSServices.js b/tests/test-utils/mockAWSServices.js index 713b3503d..f3188410c 100644 --- a/tests/test-utils/mockAWSServices.js +++ b/tests/test-utils/mockAWSServices.js @@ -15,6 +15,16 @@ const mockDynamoGetItem = (payload = {}, error = null) => { return fnSpy; }; +const mockDynamoBatchGetItem = (response = {}, error = null) => { + const fnSpy = jest.fn((x) => x); + AWSMock.setSDKInstance(AWS); + AWSMock.mock('DynamoDB', 'batchGetItem', (params, callback) => { + fnSpy(params); + callback(error, response); + }); + return fnSpy; +}; + const mockDynamoDeleteItem = (payload = {}, error = null) => { const fnSpy = jest.fn((x) => x); AWSMock.setSDKInstance(AWS); @@ -76,6 +86,7 @@ const mockS3PutObject = (payload = {}, error = null) => { module.exports = { mockDynamoGetItem, + mockDynamoBatchGetItem, mockDynamoQuery, mockDynamoUpdateItem, mockDynamoDeleteItem,