Skip to content

Commit

Permalink
abstract email validator, update test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinkim-ogp committed Nov 22, 2024
1 parent 576578f commit 5d1626a
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 30 deletions.
22 changes: 9 additions & 13 deletions backend/src/email/routes/email-transactional.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ export const InitEmailTransactionalRoute = (
const router = Router({ mergeParams: true })

// Validators
const emailValidator = Joi.string()
.trim()
.email()
.options({ convert: true })
.lowercase()

const emailArrayValidation = (fieldName: 'cc' | 'bcc') => {
return Joi.alternatives().try(
// array
Joi.array()
.unique()
.items(
Joi.string().trim().email().options({ convert: true }).lowercase()
),
Joi.array().unique().items(emailValidator),

// stringified array (form-data)
Joi.string().custom((value: string) => {
Expand All @@ -46,9 +48,7 @@ export const InitEmailTransactionalRoute = (
}
const { value: validatedEmails, error } = Joi.array()
.unique()
.items(
Joi.string().email().trim().lowercase().options({ convert: true })
)
.items(emailValidator)
.validate(parsed)

if (error) {
Expand Down Expand Up @@ -82,11 +82,7 @@ export const InitEmailTransactionalRoute = (
)
),
from: fromAddressValidator,
reply_to: Joi.string()
.trim()
.email()
.options({ convert: true })
.lowercase(),
reply_to: emailValidator,
attachments: Joi.array().items(Joi.object().keys().required()),
classification: Joi.string()
.uppercase()
Expand Down
29 changes: 12 additions & 17 deletions backend/src/email/routes/tests/email-transactional.routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -866,14 +866,11 @@ describe(`${emailTransactionalRoute}/send`, () => {
})

const ccValidTests = [
['[email protected]', '[email protected]'],
JSON.stringify([
'[email protected]',
'[email protected]',
]),
[['[email protected]']],
[['[email protected]', '[email protected]']],
]
test.each(ccValidTests)(
'Should throw api validation error if cc is not valid array or stringified array - JSON payload',
'Should send email with cc from valid array or stringified array - JSON payload',
async (cc) => {
mockSendEmail = jest
.spyOn(EmailService, 'sendEmail')
Expand All @@ -887,10 +884,8 @@ describe(`${emailTransactionalRoute}/send`, () => {
reply_to: user.email,
})

const arrayToCheck = Array.isArray(cc) ? cc : JSON.parse(cc)

expect(res.status).toBe(201)
expect(res.body.cc.sort()).toStrictEqual(arrayToCheck.sort())
expect(res.body.cc.sort()).toStrictEqual(cc.sort())
expect(mockSendEmail).toBeCalledTimes(1)
const transactionalEmail = await EmailMessageTransactional.findOne({
where: { id: res.body.id },
Expand All @@ -906,11 +901,14 @@ describe(`${emailTransactionalRoute}/send`, () => {
)

test.each(ccValidTests)(
'Should throw api validation error if cc is not valid array or stringified array - form-data',
'Should send email with cc from valid array or stringified array - form-data',
async (cc) => {
mockSendEmail = jest
.spyOn(EmailService, 'sendEmail')
.mockResolvedValue(true)
// in the case where single cc is sent, stringify the cc list
const ccSend = cc.length === 1 ? JSON.stringify(cc) : cc

const res = await request(app)
.post(endpoint)
.set('Authorization', `Bearer ${apiKey}`)
Expand All @@ -919,12 +917,10 @@ describe(`${emailTransactionalRoute}/send`, () => {
.field('body', validApiCall.body)
.field('from', 'Postman <[email protected]>')
.field('reply_to', validApiCall.reply_to)
.field('cc', cc)

const arrayToCheck = Array.isArray(cc) ? cc : JSON.parse(cc)
.field('cc', ccSend)

expect(res.status).toBe(201)
expect(res.body.cc.sort()).toStrictEqual(arrayToCheck.sort())
expect(res.body.cc.sort()).toStrictEqual(cc.sort())
expect(mockSendEmail).toBeCalledTimes(1)
const transactionalEmail = await EmailMessageTransactional.findOne({
where: { id: res.body.id },
Expand All @@ -949,7 +945,7 @@ describe(`${emailTransactionalRoute}/send`, () => {
transactionalEmail?.emailMessageTransactionalCc.map(
(item) => item.email
)
expect(transactionalCcEmails?.sort()).toStrictEqual(arrayToCheck.sort())
expect(transactionalCcEmails?.sort()).toStrictEqual(cc.sort())
}
)

Expand Down Expand Up @@ -995,14 +991,13 @@ describe(`${emailTransactionalRoute}/send`, () => {
)

test.each(ccInvalidTests)(
'Should throw api validation error if cc is not valid array or stringified array - JSON payload',
'Should throw api validation error if cc is not valid array or stringified array - form-data',
async ({ cc, errMsg }) => {
mockSendEmail = jest.spyOn(EmailService, 'sendEmail')

const res = await request(app)
.post(endpoint)
.set('Authorization', `Bearer ${apiKey}`)
.set('Authorization', `Bearer ${apiKey}`)
.field('recipient', validApiCall.recipient)
.field('subject', validApiCall.subject)
.field('body', validApiCall.body)
Expand Down

0 comments on commit 5d1626a

Please sign in to comment.