Skip to content

Commit

Permalink
Merge pull request #7426 from opengovsg/06-21-fix_tests_fix_e2e_testi…
Browse files Browse the repository at this point in the history
…ng_for_email_notifications_on_encrypt-forms

fix(tests): fix e2e testing for email notifications on encrypt-forms
  • Loading branch information
g-tejas authored Jun 27, 2024
2 parents e1d4d71 + dd8db09 commit b0ac37d
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 40 deletions.
1 change: 1 addition & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
- name: Build
env:
NODE_OPTIONS: '--max-old-space-size=4096 --openssl-legacy-provider'
AWS_SDK_JS_SUPPRESS_MAINTENANCE_MODE_MESSAGE: 1
REACT_APP_FORMSG_SDK_MODE: 'test'
run: npm run build
- name: Run Playwright tests (login)
Expand Down
26 changes: 13 additions & 13 deletions __tests__/e2e/email-submission.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
createMyInfoField,
createOptionalVersion,
deleteDocById,
getSettings,
getEmailSettings,
makeModel,
makeMongooseFixtures,
} from './utils'
Expand Down Expand Up @@ -58,7 +58,7 @@ test.describe('Email form submission', () => {
// Define
const formFields = ALL_FIELDS
const formLogics = NO_LOGIC
const formSettings = getSettings()
const formSettings = getEmailSettings()

// Test
await runEmailSubmissionTest(page, Form, {
Expand All @@ -76,7 +76,7 @@ test.describe('Email form submission', () => {
createBlankVersion(createOptionalVersion(ff)),
)
const formLogics = NO_LOGIC
const formSettings = getSettings()
const formSettings = getEmailSettings()

// Test
await runEmailSubmissionTest(page, Form, {
Expand All @@ -98,10 +98,10 @@ test.describe('Email form submission', () => {
title: `Attachment ${i}`,
path: `__tests__/e2e/files/att-folder-${i}/test-att.txt`,
val: `${i === 2 ? '' : `${2 - i}-`}test-att.txt`,
} as E2eFieldMetadata),
}) as E2eFieldMetadata,
)
const formLogics = NO_LOGIC
const formSettings = getSettings()
const formSettings = getEmailSettings()

// Test
await runEmailSubmissionTest(page, Form, {
Expand Down Expand Up @@ -135,7 +135,7 @@ test.describe('Email form submission', () => {
} as E2eFieldMetadata,
]
const formLogics = NO_LOGIC
const formSettings = getSettings()
const formSettings = getEmailSettings()

// Test
await runEmailSubmissionTest(page, Form, {
Expand All @@ -151,7 +151,7 @@ test.describe('Email form submission', () => {
// Define
const formFields = ALL_FIELDS
const formLogics = NO_LOGIC
const formSettings = getSettings({
const formSettings = getEmailSettings({
authType: FormAuthType.SP,
})

Expand All @@ -169,7 +169,7 @@ test.describe('Email form submission', () => {
// Define
const formFields = ALL_FIELDS
const formLogics = NO_LOGIC
const formSettings = getSettings({
const formSettings = getEmailSettings({
authType: FormAuthType.CP,
})

Expand All @@ -187,7 +187,7 @@ test.describe('Email form submission', () => {
// Define
const formFields = ALL_FIELDS
const formLogics = NO_LOGIC
const formSettings = getSettings({
const formSettings = getEmailSettings({
authType: FormAuthType.SGID,
})

Expand Down Expand Up @@ -216,7 +216,7 @@ test.describe('Email form submission', () => {
createMyInfoField(MyInfoAttribute.WorkpassStatus, 'Live', false),
]
const formLogics = NO_LOGIC
const formSettings = getSettings({
const formSettings = getEmailSettings({
authType: FormAuthType.MyInfo,
})

Expand All @@ -233,7 +233,7 @@ test.describe('Email form submission', () => {
}) => {
// Define
const { formFields, formLogics } = TEST_ALL_FIELDS_SHOWN_BY_LOGIC
const formSettings = getSettings()
const formSettings = getEmailSettings()

// Test
await runEmailSubmissionTest(page, Form, {
Expand All @@ -248,7 +248,7 @@ test.describe('Email form submission', () => {
}) => {
// Define
const { formFields, formLogics } = TEST_FIELD_HIDDEN_BY_LOGIC
const formSettings = getSettings()
const formSettings = getEmailSettings()

// Test
await runEmailSubmissionTest(page, Form, {
Expand All @@ -264,7 +264,7 @@ test.describe('Email form submission', () => {
// Define
const { formFields, formLogics, preventSubmitMessage } =
TEST_SUBMISSION_DISABLED_BY_CHAINED_LOGIC
const formSettings = getSettings()
const formSettings = getEmailSettings()

// Test
const { form } = await createForm(page, Form, FormResponseMode.Email, {
Expand Down
14 changes: 7 additions & 7 deletions __tests__/e2e/encrypt-submission.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
createMyInfoField,
createOptionalVersion,
deleteDocById,
getSettings,
getEncryptSettings,
makeModel,
makeMongooseFixtures,
} from './utils'
Expand Down Expand Up @@ -61,7 +61,7 @@ test.describe('Storage form submission', () => {
// Define
const formFields = ALL_FIELDS
const formLogics = NO_LOGIC
const formSettings = getSettings()
const formSettings = getEncryptSettings()

// Test
await runEncryptSubmissionTest(page, Form, {
Expand All @@ -79,7 +79,7 @@ test.describe('Storage form submission', () => {
createBlankVersion(createOptionalVersion(ff)),
)
const formLogics = NO_LOGIC
const formSettings = getSettings()
const formSettings = getEncryptSettings()

// Test
await runEncryptSubmissionTest(page, Form, {
Expand All @@ -94,7 +94,7 @@ test.describe('Storage form submission', () => {
}) => {
// Define
const { formFields, formLogics } = TEST_ALL_FIELDS_SHOWN_BY_LOGIC
const formSettings = getSettings()
const formSettings = getEncryptSettings()

// Test
await runEncryptSubmissionTest(page, Form, {
Expand All @@ -109,7 +109,7 @@ test.describe('Storage form submission', () => {
}) => {
// Define
const { formFields, formLogics } = TEST_FIELD_HIDDEN_BY_LOGIC
const formSettings = getSettings()
const formSettings = getEncryptSettings()

// Test
await runEncryptSubmissionTest(page, Form, {
Expand All @@ -125,7 +125,7 @@ test.describe('Storage form submission', () => {
// Define
const { formFields, formLogics, preventSubmitMessage } =
TEST_SUBMISSION_DISABLED_BY_CHAINED_LOGIC
const formSettings = getSettings()
const formSettings = getEncryptSettings()

// Test
const { form } = await createForm(page, Form, FormResponseMode.Encrypt, {
Expand Down Expand Up @@ -158,7 +158,7 @@ test.describe('Storage form submission', () => {
createMyInfoField(MyInfoAttribute.WorkpassStatus, 'Live', false),
]
const formLogics = NO_LOGIC
const formSettings = getSettings({
const formSettings = getEncryptSettings({
authType: FormAuthType.MyInfo,
})

Expand Down
7 changes: 3 additions & 4 deletions __tests__/e2e/helpers/createForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,7 @@ const addSettings = async (
await expect(page).toHaveURL(ADMIN_FORM_PAGE_SETTINGS(formId))

await addGeneralSettings(page, formSettings)
// Encrypt mode forms don't have an email
if (formResponseMode.responseMode === FormResponseMode.Encrypt) {
await addAdminEmails(page, formSettings)
}
await addAdminEmails(page, formSettings)
await addAuthSettings(page, formSettings)
await addCollaborators(page, formSettings)

Expand Down Expand Up @@ -385,6 +382,8 @@ const addAdminEmails = async (

await emailInput.fill(formSettings.emails.join(', '))

await page.keyboard.press('Tab')

await expectToast(page, /emails successfully updated/i)
}
}
Expand Down
38 changes: 28 additions & 10 deletions __tests__/e2e/helpers/verifySubmission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const verifySubmission = async (
// Verify the submission content
switch (formResponseMode.responseMode) {
case FormResponseMode.Email:
await verifyEmailSubmission(data)
await verifyEmailSubmission(page, data)
break
case FormResponseMode.Encrypt:
await verifyEncryptSubmission(page, {
Expand Down Expand Up @@ -87,14 +87,17 @@ export const verifySubmission = async (
* @param {E2eFieldMetadata[]} formFields the field metadata used to create and fill the form
* @param {E2eSettingsOptions} formSettings the form settings used to create the form
*/
export const verifyEmailSubmission = async ({
form,
responseId,
formFields,
formSettings,
}: VerifySubmissionBaseInputs): Promise<void> => {
export const verifyEmailSubmission = async (
page: Page,
{ form, responseId, formFields, formSettings }: VerifySubmissionBaseInputs,
): Promise<void> => {
// Get the submission from the email, via the subject.
const submission = await getSubmission(form.title, responseId)
const submission = await getSubmission(
page,
form.title,
responseId,
FormResponseMode.Email,
)

// Verify email metadata
expect(submission.from).toContain(MAIL_FROM)
Expand All @@ -120,6 +123,7 @@ export const verifyEmailSubmission = async ({
getResponseTitle(field, { mode: FormResponseMode.Email }),
...responseArray,
])
if (!submission.attachments) return
expectAttachment(field, submission.attachments)
}

Expand Down Expand Up @@ -166,7 +170,21 @@ export const verifyEncryptSubmission = async (
if (formSettings.emails) {
// (Optional) Step 1: Verify that there's an email notification in maildev
// Get the submission from the email, via the subject.
const submission = await getSubmission(form.title, responseId)
await page.evaluate(
([responseId, form_title]) => {
console.log(
`Checking maildev for submission_id=${responseId} for form=${form_title}`,
)
},
[responseId, form.title],
)

const submission = await getSubmission(
page,
form.title,
responseId,
FormResponseMode.Encrypt,
)

// Verify email metadata
expect(submission.from).toContain(MAIL_FROM)
Expand All @@ -180,7 +198,6 @@ export const verifyEncryptSubmission = async (
}

// Subject need not be verified, since we got the email via the subject.

const expectSubmissionContains = expectContains(submission.html)

// Verify form responses in email
Expand All @@ -193,6 +210,7 @@ export const verifyEncryptSubmission = async (
getResponseTitle(field, { mode: FormResponseMode.Email }),
...responseArray,
])
if (!submission.attachments) return
expectAttachment(field, submission.attachments)
}

Expand Down
22 changes: 19 additions & 3 deletions __tests__/e2e/utils/mail.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Page } from '@playwright/test'
import axios from 'axios'
import { FormResponseMode } from 'shared/types'

// Maildev default port is 1080.
const MAIL_URL = 'http://0.0.0.0:1080'
Expand Down Expand Up @@ -29,7 +31,7 @@ type EmailSubmission = {
from: string[]
subject: string
html: string
attachments: Record<string, string>
attachments?: Record<string, string>
}

// Sleep util, needed before getting mail to give mail server some time to receive email.
Expand Down Expand Up @@ -82,23 +84,37 @@ export const extractOtp = async (recipient: string): Promise<string> => {
* @returns {object} subject, sender, recipient and html content of email
*/
export const getSubmission = async (
page: Page,
formName: string,
responseId: string,
responseMode: FormResponseMode,
): Promise<EmailSubmission> => {
const subject = `formsg-auto: ${formName} (#${responseId})`

const emails = await getEmailsBy((e) => e.subject === subject)

const lastEmail = emails.pop()
if (!lastEmail) throw Error(`mailbox does not contain subject "${subject}"`)
if (!lastEmail) {
const err_msg = `mailbox does not contain subject "${subject}"`
await page.evaluate(
([err_msg]) => {
console.log(err_msg)
},
[err_msg],
)
throw Error(err_msg)
}

const submission = {
responseId,
to: lastEmail.to.map((p) => p.address),
from: lastEmail.from.map((p) => p.address),
subject: lastEmail.subject,
html: lastEmail.html,
attachments: await getSubmissionAttachments(lastEmail),
attachments:
responseMode === FormResponseMode.Email
? await getSubmissionAttachments(lastEmail)
: undefined,
}

await MAIL_CLIENT.deleteById(lastEmail.id)
Expand Down
26 changes: 23 additions & 3 deletions __tests__/e2e/utils/settings.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
import { FormAuthType, FormStatus } from 'shared/types'
import { FormAuthType, FormResponseMode, FormStatus } from 'shared/types'

import { ADMIN_EMAIL } from '../constants'
import { E2eSettingsOptions } from '../constants/settings'

export const getSettings = (
export const getEncryptSettings = (
custom?: Partial<E2eSettingsOptions>,
): E2eSettingsOptions => {
return _getSettings(FormResponseMode.Encrypt, custom)
}

export const getEmailSettings = (
custom?: Partial<E2eSettingsOptions>,
): E2eSettingsOptions => {
return _getSettings(FormResponseMode.Email, custom)
}
const _getSettings = (
responseMode: FormResponseMode,
custom?: Partial<E2eSettingsOptions>,
): E2eSettingsOptions => {
// Inject form auth settings
Expand All @@ -24,11 +37,18 @@ export const getSettings = (
}
}

return {
// Create
const settings: E2eSettingsOptions = {
status: FormStatus.Public,
collaborators: [],
authType: FormAuthType.NIL,
// By default, if emails is undefined, only the admin (current user) will receive.
...custom,
}

if (responseMode === FormResponseMode.Encrypt) {
settings.emails = [ADMIN_EMAIL]
}

return settings
}

0 comments on commit b0ac37d

Please sign in to comment.