Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend tests - updating template for channels #1175

Merged
merged 20 commits into from
May 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
286 changes: 286 additions & 0 deletions backend/src/email/routes/tests/email-campaign.routes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
import request from 'supertest'
import { Sequelize } from 'sequelize-typescript'
import initialiseServer from '@test-utils/server'
import { Campaign, User } from '@core/models'
import sequelizeLoader from '@test-utils/sequelize-loader'
import { RedisService } from '@core/services'
import { EmailFromAddress, EmailMessage } from '@email/models'
import { CustomDomainService } from '@email/services'
import { ChannelType } from '@core/constants'

const app = initialiseServer(true)
let sequelize: Sequelize
let campaignId: number
let protectedCampaignId: number

beforeAll(async () => {
sequelize = await sequelizeLoader(process.env.JEST_WORKER_ID || '1')
await User.create({ id: 1, email: 'user@agency.gov.sg' })
const campaign = await Campaign.create({
name: 'campaign-1',
userId: 1,
type: ChannelType.Email,
valid: false,
protect: false,
})
campaignId = campaign.id
const protectedCampaign = await Campaign.create({
name: 'campaign-2',
userId: 1,
type: ChannelType.Email,
valid: false,
protect: true,
})
protectedCampaignId = protectedCampaign.id
})

afterAll(async () => {
await EmailMessage.destroy({ where: {} })
await Campaign.destroy({ where: {} })
await User.destroy({ where: {} })
await sequelize.close()
RedisService.otpClient.quit()
RedisService.sessionClient.quit()
})

describe('PUT /campaign/{campaignId}/email/template', () => {
afterEach(async () => {
await EmailFromAddress.destroy({ where: {} })
})

test('Invalid from address is not accepted', async () => {
const res = await request(app)
.put(`/campaign/${campaignId}/email/template`)
.send({
from: 'abc@postman.gov.sg',
subject: 'test',
body: 'test',
reply_to: 'user@agency.gov.sg',
})
expect(res.status).toBe(400)
expect(res.body).toEqual({ message: "Invalid 'from' email address." })
})

test('Default from address is used if not provided', async () => {
const res = await request(app)
.put(`/campaign/${campaignId}/email/template`)
.send({
subject: 'test',
body: 'test',
reply_to: 'user@agency.gov.sg',
})
expect(res.status).toBe(200)
expect(res.body).toEqual(
expect.objectContaining({
message: `Template for campaign ${campaignId} updated`,
template: expect.objectContaining({
from: 'Postman <donotreply@mail.postman.gov.sg>',
reply_to: 'user@agency.gov.sg',
}),
})
)
})

test('Default from address is accepted', async () => {
const res = await request(app)
.put(`/campaign/${campaignId}/email/template`)
.send({
from: 'Postman <donotreply@mail.postman.gov.sg>',
subject: 'test',
body: 'test',
reply_to: 'user@agency.gov.sg',
})
expect(res.status).toBe(200)
expect(res.body).toEqual(
expect.objectContaining({
message: `Template for campaign ${campaignId} updated`,
template: expect.objectContaining({
from: 'Postman <donotreply@mail.postman.gov.sg>',
reply_to: 'user@agency.gov.sg',
}),
})
)
})

test("Unverified user's email as from address is not accepted", async () => {
const res = await request(app)
.put(`/campaign/${campaignId}/email/template`)
.send({
from: 'user@agency.gov.sg',
subject: 'test',
body: 'test',
reply_to: 'user@agency.gov.sg',
})
expect(res.status).toBe(400)
expect(res.body).toEqual({ message: 'From Address has not been verified.' })
})

test("Verified user's email as from address is accepted", async () => {
await EmailFromAddress.create({
lamkeewei marked this conversation as resolved.
Show resolved Hide resolved
email: 'user@agency.gov.sg',
name: 'Agency ABC',
})
const mockVerifyFromAddress = jest
.spyOn(CustomDomainService, 'verifyFromAddress')
.mockReturnValue(Promise.resolve())

const res = await request(app)
.put(`/campaign/${campaignId}/email/template`)
.send({
from: 'Agency ABC <user@agency.gov.sg>',
subject: 'test',
body: 'test',
reply_to: 'user@agency.gov.sg',
})
expect(res.status).toBe(200)
expect(res.body).toEqual(
expect.objectContaining({
message: `Template for campaign ${campaignId} updated`,
template: expect.objectContaining({
from: 'Agency ABC <user@agency.gov.sg>',
reply_to: 'user@agency.gov.sg',
}),
})
)
mockVerifyFromAddress.mockRestore()
})

test('Protected template without protectedlink variables is not accepted', async () => {
const res = await request(app)
.put(`/campaign/${protectedCampaignId}/email/template`)
.send({
subject: 'test',
body: 'test',
reply_to: 'user@agency.gov.sg',
})
expect(res.status).toBe(500)
expect(res.body).toEqual({
message:
'Error: There are missing keywords in the message template: protectedlink. Please return to the previous step to add in the keywords.',
})
})

test('Protected template with disallowed variables in subject is not accepted', async () => {
const testSubject = await request(app)
.put(`/campaign/${protectedCampaignId}/email/template`)
.send({
subject: 'test {{name}}',
body: '{{recipient}} {{protectedLink}}',
reply_to: 'user@agency.gov.sg',
})
expect(testSubject.status).toBe(500)
expect(testSubject.body).toEqual({
message:
'Error: Only these keywords are allowed in the template: protectedlink,recipient.\nRemove the other keywords from the template: name.',
})
})

test('Protected template with disallowed variables in body is not accepted', async () => {
const testBody = await request(app)
.put(`/campaign/${protectedCampaignId}/email/template`)
.send({
subject: 'test',
body: '{{recipient}} {{protectedLink}} {{name}}',
reply_to: 'user@agency.gov.sg',
})

expect(testBody.status).toBe(500)
expect(testBody.body).toEqual({
message:
'Error: Only these keywords are allowed in the template: protectedlink,recipient.\nRemove the other keywords from the template: name.',
})
})

test('Protected template with only allowed variables is accepted', async () => {
const testBody = await request(app)
.put(`/campaign/${protectedCampaignId}/email/template`)
.send({
subject: 'test {{recipient}} {{protectedLink}}',
body: 'test {{recipient}} {{protectedLink}}',
reply_to: 'user@agency.gov.sg',
})

expect(testBody.status).toBe(200)
expect(testBody.body).toEqual(
expect.objectContaining({
message: `Template for campaign ${protectedCampaignId} updated`,
template: expect.objectContaining({
from: 'Postman <donotreply@mail.postman.gov.sg>',
reply_to: 'user@agency.gov.sg',
}),
})
)
})

test('Template with only invalid HTML tags is not accepted', async () => {
const testBody = await request(app)
.put(`/campaign/${campaignId}/email/template`)
.send({
subject: 'test',
body: '<script></script>',
reply_to: 'user@agency.gov.sg',
})

expect(testBody.status).toBe(400)
expect(testBody.body).toEqual({
message:
'Message template is invalid as it only contains invalid HTML tags!',
})
})

test('Existing populated messages are removed when template has new variables', async () => {
await EmailMessage.create({
campaignId,
recipient: 'user@agency.gov.sg',
params: { recipient: 'user@agency.gov.sg' },
})
const testBody = await request(app)
.put(`/campaign/${campaignId}/email/template`)
.send({
subject: 'test',
body: 'test {{name}}',
reply_to: 'user@agency.gov.sg',
})

expect(testBody.status).toBe(200)
expect(testBody.body).toEqual(
expect.objectContaining({
message:
'Please re-upload your recipient list as template has changed.',
template: expect.objectContaining({
from: 'Postman <donotreply@mail.postman.gov.sg>',
reply_to: 'user@agency.gov.sg',
}),
})
)

const emailMessages = await EmailMessage.count({
where: { campaignId },
})
expect(emailMessages).toEqual(0)
})
lamkeewei marked this conversation as resolved.
Show resolved Hide resolved

test('Successfully update template', async () => {
const res = await request(app)
.put(`/campaign/${campaignId}/email/template`)
.send({
subject: 'test',
body: 'test {{name}}',
reply_to: 'user@agency.gov.sg',
})

expect(res.status).toBe(200)
expect(res.body).toEqual(
expect.objectContaining({
message: `Template for campaign ${campaignId} updated`,
template: {
subject: 'test',
body: 'test {{name}}',
from: 'Postman <donotreply@mail.postman.gov.sg>',
reply_to: 'user@agency.gov.sg',
params: ['name'],
},
})
)
})
})
94 changes: 94 additions & 0 deletions backend/src/sms/routes/tests/sms-campaign.routes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import request from 'supertest'
import { Sequelize } from 'sequelize-typescript'
import initialiseServer from '@test-utils/server'
import { Campaign, User } from '@core/models'
import sequelizeLoader from '@test-utils/sequelize-loader'
import { RedisService } from '@core/services'
import { SmsMessage } from '@sms/models'
import { ChannelType } from '@core/constants'

const app = initialiseServer(true)
let sequelize: Sequelize
let campaignId: number

beforeAll(async () => {
sequelize = await sequelizeLoader(process.env.JEST_WORKER_ID || '1')
await User.create({ id: 1, email: 'user@agency.gov.sg' })
const campaign = await Campaign.create({
name: 'campaign-1',
userId: 1,
type: ChannelType.SMS,
valid: false,
})
campaignId = campaign.id
})

afterAll(async () => {
await SmsMessage.destroy({ where: {} })
await Campaign.destroy({ where: {} })
await User.destroy({ where: {} })
await sequelize.close()
RedisService.otpClient.quit()
RedisService.sessionClient.quit()
})

describe('PUT /campaign/{campaignId}/sms/template', () => {
test('Template with only invalid HTML tags is not accepted', async () => {
const testBody = await request(app)
.put(`/campaign/${campaignId}/sms/template`)
.send({
body: '<img></img>',
})

expect(testBody.status).toBe(400)
expect(testBody.body).toEqual({
message:
'Message template is invalid as it only contains invalid HTML tags!',
})
})

test('Existing populated messages are removed when template has new variables', async () => {
await SmsMessage.create({
campaignId,
recipient: 'user@agency.gov.sg',
params: { recipient: 'user@agency.gov.sg' },
})
const res = await request(app)
.put(`/campaign/${campaignId}/sms/template`)
.send({
body: 'test {{name}}',
})

expect(res.status).toBe(200)
expect(res.body).toEqual(
expect.objectContaining({
message:
'Please re-upload your recipient list as template has changed.',
template: expect.objectContaining({
params: ['name'],
}),
})
)

const smsMessages = await SmsMessage.count({
where: { campaignId },
})
expect(smsMessages).toEqual(0)
})

test('Successfully update template', async () => {
const res = await request(app)
.put(`/campaign/${campaignId}/sms/template`)
.send({
body: 'test {{name}}',
})

expect(res.status).toBe(200)
expect(res.body).toEqual(
expect.objectContaining({
message: `Template for campaign ${campaignId} updated`,
template: { body: 'test {{name}}', params: ['name'] },
})
)
})
})
Loading