Skip to content

Commit

Permalink
feat: migrate get encrypt metadata endpoint controller to TypeScript (#…
Browse files Browse the repository at this point in the history
…711)

* feat(EncryptSubSvc): add getSubmissionMetadata service fn (and tests)

* feat(EncryptSubSvc): add getSubmissionMetadataList service fn (+tests)

* feat(EncryptSubCtl): add handleGetMetadata fn

* ref(AdminFormRoutes): use new handleGetMetadata handler fn

* feat(AdminFormRoutes): allow optional page when submissionId exists

* test(EncryptSubCtl): add tests for handleGetMetadata
  • Loading branch information
karrui authored Nov 25, 2020
1 parent cb50ec0 commit 29e1a94
Show file tree
Hide file tree
Showing 6 changed files with 474 additions and 65 deletions.
59 changes: 0 additions & 59 deletions src/app/controllers/encrypt-submissions.server.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ const crypto = require('crypto')
const { StatusCodes } = require('http-status-codes')

const mongoose = require('mongoose')
const errorHandler = require('../utils/handle-mongo-error')
const {
getEncryptSubmissionModel,
} = require('../models/submission.server.model')
Expand All @@ -20,8 +19,6 @@ const {
getProcessedResponses,
} = require('../modules/submission/submission.service')

const HttpStatus = require('http-status-codes')

/**
* Extracts relevant fields, injects questions, verifies visibility of field and validates answers
* to produce req.body.parsedResponses
Expand Down Expand Up @@ -210,59 +207,3 @@ exports.saveResponseToDb = function (req, res, next) {
return onEncryptSubmissionFailure(err, req, res, submission)
})
}

/**
* Return metadata for encrypted form responses matching form._id
* @param {Object} req - Express request object
* @param {String} req.query.pageNo - page of table to return data for
* @param {Object} req.form - the form
* @param {Object} res - Express response object
*/
exports.getMetadata = function (req, res) {
let { page, submissionId } = req.query || {}

if (submissionId) {
// Early return if submissionId is invalid.
if (!mongoose.Types.ObjectId.isValid(submissionId)) {
return res.status(HttpStatus.OK).json({ metadata: [], count: 0 })
}

return EncryptSubmission.findSingleMetadata(req.form._id, submissionId)
.then((result) => {
if (!result) {
return res.status(HttpStatus.OK).json({ metadata: [], count: 0 })
}

return res.status(HttpStatus.OK).json({ metadata: [result], count: 1 })
})
.catch((error) => {
logger.error({
message: 'Failure retrieving metadata from database',
meta: {
action: 'getMetadata',
...createReqMeta(req),
},
error,
})
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
message: errorHandler.getMongoErrorMessage(error),
})
})
} else {
return EncryptSubmission.findAllMetadataByFormId(req.form._id, { page })
.then((result) => res.status(StatusCodes.OK).json(result))
.catch((error) => {
logger.error({
message: 'Failure retrieving metadata from database',
meta: {
action: 'getMetadata',
...createReqMeta(req),
},
error: error,
})
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
message: errorHandler.getMongoErrorMessage(error),
})
})
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { ObjectId } from 'bson-ext'
import { errAsync, okAsync } from 'neverthrow'
import { mocked } from 'ts-jest/utils'

import { DatabaseError } from 'src/app/modules/core/core.errors'
import { CreatePresignedUrlError } from 'src/app/modules/form/admin-form/admin-form.errors'
import { SubmissionData } from 'src/types'
import { SubmissionData, SubmissionMetadata } from 'src/types'

import expressHandler from 'tests/unit/backend/helpers/jest-express'

import { SubmissionNotFoundError } from '../../submission.errors'
import { handleGetEncryptedResponse } from '../encrypt-submission.controller'
import {
handleGetEncryptedResponse,
handleGetMetadata,
} from '../encrypt-submission.controller'
import * as EncryptSubmissionService from '../encrypt-submission.service'

jest.mock('../encrypt-submission.service')
const MockEncryptSubService = mocked(EncryptSubmissionService)

describe('encrypt-submission.controller', () => {
beforeEach(() => jest.clearAllMocks())

describe('handleGetEncryptedResponse', () => {
const MOCK_REQ = expressHandler.mockRequest({
params: { formId: 'mockFormId' },
Expand Down Expand Up @@ -114,4 +120,176 @@ describe('encrypt-submission.controller', () => {
expect(mockRes.json).toHaveBeenCalledWith({ message: mockErrorString })
})
})

describe('handleGetMetadata', () => {
const MOCK_FORM_ID = new ObjectId().toHexString()

it('should return 200 with single submission metadata when query.submissionId is provided and can be found', async () => {
// Arrange
const mockSubmissionId = new ObjectId().toHexString()
const mockReq = expressHandler.mockRequest({
params: { formId: MOCK_FORM_ID },
query: {
submissionId: mockSubmissionId,
},
})
const mockRes = expressHandler.mockResponse()
// Mock service result.
const expectedMetadata: SubmissionMetadata = {
number: 2,
refNo: mockSubmissionId,
submissionTime: 'some submission time',
}

MockEncryptSubService.getSubmissionMetadata.mockReturnValueOnce(
okAsync(expectedMetadata),
)

// Act
await handleGetMetadata(mockReq, mockRes, jest.fn())

// Assert
expect(mockRes.json).toHaveBeenCalledWith({
metadata: [expectedMetadata],
count: 1,
})
expect(
MockEncryptSubService.getSubmissionMetadataList,
).not.toHaveBeenCalled()
expect(MockEncryptSubService.getSubmissionMetadata).toHaveBeenCalledWith(
MOCK_FORM_ID,
mockSubmissionId,
)
})

it('should return 200 with empty submission metadata when query.submissionId is provided but cannot be found', async () => {
// Arrange
const mockSubmissionId = new ObjectId().toHexString()
const mockReq = expressHandler.mockRequest({
params: { formId: MOCK_FORM_ID },
query: {
submissionId: mockSubmissionId,
},
})
const mockRes = expressHandler.mockResponse()
// Mock service result.
MockEncryptSubService.getSubmissionMetadata.mockReturnValueOnce(
okAsync(null),
)

// Act
await handleGetMetadata(mockReq, mockRes, jest.fn())

// Assert
expect(mockRes.json).toHaveBeenCalledWith({
metadata: [],
count: 0,
})
expect(
MockEncryptSubService.getSubmissionMetadataList,
).not.toHaveBeenCalled()
expect(MockEncryptSubService.getSubmissionMetadata).toHaveBeenCalledWith(
MOCK_FORM_ID,
mockSubmissionId,
)
})

it('should return 200 with list of submission metadata', async () => {
// Arrange
const mockReq = expressHandler.mockRequest({
params: { formId: MOCK_FORM_ID },
query: {
page: 20,
},
})
const mockRes = expressHandler.mockResponse()
// Mock service result.
const expectedMetadataList = {
metadata: [
{
number: 2,
refNo: new ObjectId().toHexString(),
submissionTime: 'some submission time',
},
] as SubmissionMetadata[],
count: 32,
}

MockEncryptSubService.getSubmissionMetadataList.mockReturnValueOnce(
okAsync(expectedMetadataList),
)

// Act
await handleGetMetadata(mockReq, mockRes, jest.fn())

// Assert
expect(mockRes.json).toHaveBeenCalledWith(expectedMetadataList)
expect(
MockEncryptSubService.getSubmissionMetadataList,
).toHaveBeenCalledWith(MOCK_FORM_ID, mockReq.query.page)
expect(MockEncryptSubService.getSubmissionMetadata).not.toHaveBeenCalled()
})

it('should return 500 when database errors occurs for single metadata retrieval', async () => {
// Arrange
const mockSubmissionId = new ObjectId().toHexString()
const mockReq = expressHandler.mockRequest({
params: { formId: MOCK_FORM_ID },
query: {
submissionId: mockSubmissionId,
},
})
const mockErrorString = 'error retrieving metadata'
const mockRes = expressHandler.mockResponse()
// Mock service result.
MockEncryptSubService.getSubmissionMetadata.mockReturnValueOnce(
errAsync(new DatabaseError(mockErrorString)),
)

// Act
await handleGetMetadata(mockReq, mockRes, jest.fn())

// Assert
expect(mockRes.json).toHaveBeenCalledWith({
message: mockErrorString,
})
expect(mockRes.status).toHaveBeenCalledWith(500)
expect(
MockEncryptSubService.getSubmissionMetadataList,
).not.toHaveBeenCalled()
expect(MockEncryptSubService.getSubmissionMetadata).toHaveBeenCalledWith(
MOCK_FORM_ID,
mockSubmissionId,
)
})

it('should return 500 when database errors occurs for metadata list retrieval', async () => {
// Arrange
const mockReq = expressHandler.mockRequest({
params: { formId: MOCK_FORM_ID },
query: {
page: 1,
},
})
const mockErrorString = 'error retrieving metadata list'
const mockRes = expressHandler.mockResponse()
// Mock service result.
MockEncryptSubService.getSubmissionMetadataList.mockReturnValueOnce(
errAsync(new DatabaseError(mockErrorString)),
)

// Act
await handleGetMetadata(mockReq, mockRes, jest.fn())

// Assert
expect(mockRes.json).toHaveBeenCalledWith({
message: mockErrorString,
})
expect(mockRes.status).toHaveBeenCalledWith(500)
expect(MockEncryptSubService.getSubmissionMetadata).not.toHaveBeenCalled()
expect(
MockEncryptSubService.getSubmissionMetadataList,
).toHaveBeenCalledWith(MOCK_FORM_ID, mockReq.query.page)
})
})
})
Loading

0 comments on commit 29e1a94

Please sign in to comment.