Skip to content

Commit

Permalink
Merge pull request #114 from digital-land/rosado/3338-send-email-fail…
Browse files Browse the repository at this point in the history
…-handling

form submission: error handling and logging for email notifications
  • Loading branch information
GeorgeGoodall authored Jul 10, 2024
2 parents 1880045 + afdd200 commit a011fbe
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 74 deletions.
92 changes: 58 additions & 34 deletions src/controllers/CheckAnswersController.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,54 +14,78 @@ class CheckAnswersController extends PageController {
* @param {Object} req - The HTTP request object.
* @param {Object} res - The HTTP response object.
* @param {Function} next - The next middleware function.
*/
post (req, res, next) {
this.sendEmails(req, res, next)
*/
async post (req, res, next) {
const result = await this.sendEmails(req, res, next)
for (const err of (result.errors ?? [])) {
console.error(err)
}

super.post(req, res, next)
}

sendEmails (req, res, next) {
/**
* Attempts to send email notifications.
*
* @param {*} req
* @param {*} res
* @param {*} next
* @returns {Promise<{} | {errors: string[]}>}
*/
async sendEmails (req, res, next) {
const name = req.sessionModel.get('name')
const email = req.sessionModel.get('email')
const organisation = req.sessionModel.get('lpa')
const dataset = req.sessionModel.get('dataset')
const documentationUrl = req.sessionModel.get('documentation-url')
const endpoint = req.sessionModel.get('endpoint-url')

const { RequestTemplateId, AcknowledgementTemplateId } = config.email.templates

// ToDo: handle errors when sending emails
notifyClient.sendEmail(
RequestTemplateId,
dataManagementEmail,
{
personalisation: {
name,
email,
organisation,
endpoint,
'documentation-url': documentationUrl,
dataset
}
}
)
const { RequestTemplateId, AcknowledgementTemplateId } =
config.email.templates

notifyClient.sendEmail(
AcknowledgementTemplateId,
const personalisation = {
name,
email,
{
personalisation: {
name,
email,
organisation,
endpoint,
'documentation-url': documentationUrl,
dataset
}
}
)
organisation,
endpoint,
'documentation-url': documentationUrl,
dataset
}

const [reqResult, ackResult] = await Promise.allSettled([
notifyClient.sendEmail(RequestTemplateId, dataManagementEmail, {
personalisation
}),
notifyClient.sendEmail(AcknowledgementTemplateId, email, {
personalisation
})
])

const errors = []
if (reqResult.status === 'rejected') {
const msg = emailFailureMessage(RequestTemplateId, personalisation)
errors.push(msg)
}
if (ackResult.status === 'rejected') {
const msg = emailFailureMessage(AcknowledgementTemplateId, personalisation)
errors.push(msg)
}

if (errors.length !== 0) {
return { errors }
}
return {}
}
}

/**
*
* @param {string} templateId
* @param {{organisation: string, name: string, email: string}} metadata
* @returns
*/
function emailFailureMessage (templateId, { organisation, name, email }) {
return `Failed to send email template=${templateId} to (org: ${organisation}, name: ${name}, email: ${email}):`
}

export default CheckAnswersController
2 changes: 1 addition & 1 deletion test/unit/check-answers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import config from '../../config/index.js'
import { stripWhitespace } from '../utils/stripWhiteSpace.js'
import { mockDataSubjects } from './data.js'

describe('check-answers View', () => {
describe('check-answers View', async () => {
const params = {
values: {
lpa: 'mockLpa',
Expand Down
88 changes: 49 additions & 39 deletions test/unit/checkAnswersController.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,41 @@ import config from '../../config/index.js'

vi.mock('../../src/utils/mailClient.js')

describe('Check answers controller', () => {
function makeRequest () {
return {
sessionModel: {
get: vi.fn().mockImplementation((key) => {
const values = {
name: 'John Doe',
email: '[email protected]',
lpa: 'LPA',
dataset: 'Dataset',
'documentation-url': 'Documentation URL',
'endpoint-url': 'Endpoint URL'
}
return values[key]
})
}
}
}

describe('Handle email notification handlers', async () => {
const CheckAnswersController = await vi.importActual('../../src/controllers/CheckAnswersController.js')
const sendEmailMock = vi.fn(() => Promise.reject(new Error('something went wrong')))
notifyClient.sendEmail = sendEmailMock

const controller = new CheckAnswersController.default({ route: '/dataset' })
const req = makeRequest()
const res = {}
const next = vi.fn()

it('should reuturn list of errors when failed to send email', async () => {
const result = await controller.sendEmails(req, res, next)
expect(result.errors.length).toBe(2)
})
})

describe('Check answers controller', async () => {
let CheckAnswersController
let checkAnswersController
let sendEmailMock
Expand All @@ -22,57 +56,33 @@ describe('Check answers controller', () => {
})

describe('send emails', () => {
it('should get the values from the session model and then send the request and acknowledgement emails', () => {
it('should get the values from the session model and then send the request and acknowledgement emails', async () => {
// Mock req, res, next
const req = {
sessionModel: {
get: vi.fn().mockImplementation((key) => {
const values = {
name: 'John Doe',
email: '[email protected]',
lpa: 'LPA',
dataset: 'Dataset',
'documentation-url': 'Documentation URL',
'endpoint-url': 'Endpoint URL'
}
return values[key]
})
}
}

const req = makeRequest()
const res = {}
const next = vi.fn()

checkAnswersController.sendEmails(req, res, next)
await checkAnswersController.sendEmails(req, res, next)

const personalisation = {
name: 'John Doe',
email: '[email protected]',
organisation: 'LPA',
dataset: 'Dataset',
'documentation-url': 'Documentation URL',
endpoint: 'Endpoint URL'
}

expect(sendEmailMock).toHaveBeenCalledWith(
config.email.templates.RequestTemplateId,
config.email.dataManagementEmail,
{
personalisation: {
name: 'John Doe',
email: '[email protected]',
organisation: 'LPA',
dataset: 'Dataset',
'documentation-url': 'Documentation URL',
endpoint: 'Endpoint URL'
}
}
{ personalisation }
)

expect(sendEmailMock).toHaveBeenCalledWith(
config.email.templates.AcknowledgementTemplateId,
'[email protected]',
{
personalisation: {
name: 'John Doe',
email: '[email protected]',
organisation: 'LPA',
endpoint: 'Endpoint URL',
'documentation-url': 'Documentation URL',
dataset: 'Dataset'
}
}
{ personalisation }
)
})
})
Expand Down

0 comments on commit a011fbe

Please sign in to comment.