From dd8db090fa44f7a1fa76e2348b955881494fbe78 Mon Sep 17 00:00:00 2001 From: g-tejas Date: Thu, 27 Jun 2024 21:40:16 +0800 Subject: [PATCH] fix(tests): fix e2e testing for email notifs on encrypt-form --- .github/workflows/playwright.yml | 1 + __tests__/e2e/email-submission.spec.ts | 26 ++++++++-------- __tests__/e2e/encrypt-submission.spec.ts | 14 ++++----- __tests__/e2e/helpers/createForm.ts | 7 ++--- __tests__/e2e/helpers/verifySubmission.ts | 38 +++++++++++++++++------ __tests__/e2e/utils/mail.ts | 22 +++++++++++-- __tests__/e2e/utils/settings.ts | 26 ++++++++++++++-- 7 files changed, 94 insertions(+), 40 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 9beadd2eba..765c19d456 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -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) diff --git a/__tests__/e2e/email-submission.spec.ts b/__tests__/e2e/email-submission.spec.ts index 8fcc03bfbe..93ff448eb9 100644 --- a/__tests__/e2e/email-submission.spec.ts +++ b/__tests__/e2e/email-submission.spec.ts @@ -28,7 +28,7 @@ import { createMyInfoField, createOptionalVersion, deleteDocById, - getSettings, + getEmailSettings, makeModel, makeMongooseFixtures, } from './utils' @@ -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, { @@ -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, { @@ -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, { @@ -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, { @@ -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, }) @@ -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, }) @@ -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, }) @@ -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, }) @@ -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, { @@ -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, { @@ -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, { diff --git a/__tests__/e2e/encrypt-submission.spec.ts b/__tests__/e2e/encrypt-submission.spec.ts index e487065a13..03325670c6 100644 --- a/__tests__/e2e/encrypt-submission.spec.ts +++ b/__tests__/e2e/encrypt-submission.spec.ts @@ -26,7 +26,7 @@ import { createMyInfoField, createOptionalVersion, deleteDocById, - getSettings, + getEncryptSettings, makeModel, makeMongooseFixtures, } from './utils' @@ -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, { @@ -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, { @@ -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, { @@ -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, { @@ -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, { @@ -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, }) diff --git a/__tests__/e2e/helpers/createForm.ts b/__tests__/e2e/helpers/createForm.ts index f8f19603c5..01f6a9dcff 100644 --- a/__tests__/e2e/helpers/createForm.ts +++ b/__tests__/e2e/helpers/createForm.ts @@ -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) @@ -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) } } diff --git a/__tests__/e2e/helpers/verifySubmission.ts b/__tests__/e2e/helpers/verifySubmission.ts index 5ed73f0fe8..9dd563ca93 100644 --- a/__tests__/e2e/helpers/verifySubmission.ts +++ b/__tests__/e2e/helpers/verifySubmission.ts @@ -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, { @@ -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 => { +export const verifyEmailSubmission = async ( + page: Page, + { form, responseId, formFields, formSettings }: VerifySubmissionBaseInputs, +): Promise => { // 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) @@ -120,6 +123,7 @@ export const verifyEmailSubmission = async ({ getResponseTitle(field, { mode: FormResponseMode.Email }), ...responseArray, ]) + if (!submission.attachments) return expectAttachment(field, submission.attachments) } @@ -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) @@ -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 @@ -193,6 +210,7 @@ export const verifyEncryptSubmission = async ( getResponseTitle(field, { mode: FormResponseMode.Email }), ...responseArray, ]) + if (!submission.attachments) return expectAttachment(field, submission.attachments) } diff --git a/__tests__/e2e/utils/mail.ts b/__tests__/e2e/utils/mail.ts index f42207ba88..64e9b2fd6b 100644 --- a/__tests__/e2e/utils/mail.ts +++ b/__tests__/e2e/utils/mail.ts @@ -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' @@ -29,7 +31,7 @@ type EmailSubmission = { from: string[] subject: string html: string - attachments: Record + attachments?: Record } // Sleep util, needed before getting mail to give mail server some time to receive email. @@ -82,15 +84,26 @@ export const extractOtp = async (recipient: string): Promise => { * @returns {object} subject, sender, recipient and html content of email */ export const getSubmission = async ( + page: Page, formName: string, responseId: string, + responseMode: FormResponseMode, ): Promise => { 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, @@ -98,7 +111,10 @@ export const getSubmission = async ( 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) diff --git a/__tests__/e2e/utils/settings.ts b/__tests__/e2e/utils/settings.ts index f92581f6d0..3a6664a241 100644 --- a/__tests__/e2e/utils/settings.ts +++ b/__tests__/e2e/utils/settings.ts @@ -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 => { + return _getSettings(FormResponseMode.Encrypt, custom) +} + +export const getEmailSettings = ( + custom?: Partial, +): E2eSettingsOptions => { + return _getSettings(FormResponseMode.Email, custom) +} +const _getSettings = ( + responseMode: FormResponseMode, custom?: Partial, ): E2eSettingsOptions => { // Inject form auth settings @@ -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 }