End-to-End Testing: Saving and Restoring Pages via Email with CodeceptJS and Playwright

Ruslan Kazakov
Bear Necessities
Published in
6 min readOct 13, 2023
Photo by Solen Feyissa on Unsplash

There are many application processes and workflows that are common in modern web apps and services, but can still be challenging to develop an end-to-end testing scenario for. Such scenarios include Email and OpenID logins, CAPTCHA, visual testing, two-factor authentication, file downloads, HTTP response codes and many more. QA engineers need to find creative ways to develop End-to-End testing scenarios to ensure these workflows are not left out. This article discusses one of such challenges and proposes a practical real life solution developed with CodeceptJS and Playwright End-to-End testing frameworks.

Problem

One of the most common workflows for web applications in the insurance industry is so called Quote and Buy workflow. A part of this process is a workflow that QAs typically struggle with, namely Email and Retrieve quote. This functionality allows clients to save their insurance quote at different stages of your application, send it to your email address, so that you could come back to it within a reasonable time period. When clicking on the email link a state of your quote is restored and you can modify it or proceed to payment.

By definition this creates a number of questions for a QA professional:

  • Should this part of the application be mocked? If so, is this testing useful?
  • If testing the real scenario how do we get data from the email?
  • Are there other ways to satisfy the testing criteria and avoid using third-party email services?

System under test

I will illustrate a real-life challenge in one of our customer’s web applications in the insurance industry. The insurance Quote and Buy journey offers the capability to send an email to save the quote state.

The email letter will contain a generated link that will open a new browser tab with the unique quote identifier. Based on this identifier the quote state could be fully restored later to continue the process of the application.

Options

This problem can be approached from different angles.

  • Mocking responses or parts of application
  • Leveraging Email services
  • Exploring API requests

Mocking responses

Mocking data is a common technique used to test software that relies on external sources of data, such as databases, web services, or APIs. It involves creating fake or simulated data that replicates the real data, without actually interacting with the external source. While mocking data can be helpful in certain situations, it has significant drawbacks.

The cons of mocking include:

  • Inability to test the real system, leading to potential issues being missed
  • Potential inconsistencies between mocked and real data, especially over the long term period
  • Increased maintenance and complexity in testing
  • Limited test coverage

In our scenario we could mock the send email and retrieve quote part, but we will not be testing the real system. It may be reasonable at unit testing level, but will not be feasible at End-to-End testing level.

Leveraging Email service

Another approach that we could leverage is an Email testing service such as MailSlurp or Mailosaur. These are two excellent services that can assist with various email workflows.

Using CodeceptJS framework along with Playwright helper, we will demonstrate how to use MailSlurp service to automate send and retrieve quote scenario in our insurance web application.

Thankfully CodeceptJS provides an integration with MailSlurp in a form of a helper which can be quickly implemented.

In your CodeceptJS test automation project bring in the NPM dependency for MailSlurp helper.

npm install @codeceptjs/mailslurp-helper

Modify CodeceptJS configuration to add the new helper. More details on MailSlurp setup can be found on the official website.

// codecept.conf.ts
{
...
helpers: {
MailSlurp: {
require: '@codeceptjs/mailslurp-helper',
apiKey: '<MailSlurp-API-Key>'
}
}
...
}

Implement your testing scenario in CodeceptJS to click on the button to send the email with the retrieve quote link, wait for the email and open that link. These actions are mimicking user’s behaviour and test the scenario as it would happen in real life.

// Create new MailSlurp mailbox
const quoteMailbox = await I.haveNewMailbox()

// Populate the email address and trigger send
I.fillField('#emailQuote', quoteMailbox.emailAddress)
I.click('Send')
// Open mailbox
I.openMailbox(quoteMailbox)
// Find the right email and get url to retrieve quote
const emailContent = I.waitForEmailMatching({ subject: 'Your quote is ready' })
const retrieveQuoteUrl = emailContent.body.match(/https:\\/\\/(.*?)\\s/)[0]
// Open the new url
I.openNewTab()
I.amOnPage(retrieveQuoteUrl)

Even though this approach is closer to how the real client is using the system, it has downsides:

  • Dependency on the third-party service for any outages
  • Maintenance for APIs changes
  • Subscription costs

Exploring API requests

The previous approach to test the application might be exactly what many team need, but over time we will find ourselves with a bunch of integrations and dependencies to external services.

A good question to ask at this stage is: “Are there alternative methods to meet the testing criteria and avoid relying on third-party email services?”

If we explore how our frontend and backend APIs talk to each other, we will notice that the information that is needed lies within API requests that are made from the frontend.

A closer look into retrieve quote url will show that all we need to retrieve a quote is its unique uuid.

https://<domain>/quote?quoteUuid=<uuid>&brand=<brand>

When we trigger an event by clicking on the Send button, we trigger an API call that passes a uuid of the current quote as a payload to /api/quote/email backend endpoint.

We start by entering email address and clicking on Send button. Note the email address does not matter in this case as we will not be looking into the email message.

Then we listen to network traffic and extract the request payload to get the unique quote uuid and brand to compose the retrieve url.

// Populate the email address and click Send
I.fillField('#emailQuote', 'e2e-test@example.com')
I.click('Send')

// Start recording network traffic
I.startRecordingTraffic()

// Wait when a particular endpoint is resolved
I.waitForResponse(process.env.API_QUOTE_EMAIL_URL)

// Get the recorded network traffic
const traffics = await this.grabRecordedNetworkTraffics()
// Stop recording process
I.stopRecordingTraffic()

// Find the request
const emailRequest = traffics.find(({ url }) => url.includes(process.env.API_QUOTE_EMAIL_URL))
// Get details from request payload
const emailData = JSON.parse(emailRequest.requestPostData)
// Compose retrieve url
const retrieveQuoteUrl = `${process.env.BASE_URL}/quote?quoteUuid=${emailData.quoteUuid}&brand=${emailData.brand}`

I.waitForText('Thank you')
I.pressKey('Escape')

// Open the new url
I.openNewTab()
I.amOnPage(retrieveQuoteUrl)

By opening new tab we clear the session that had been used before and continue the quote journey for the user.

In this approach, we found a creative solution to a challenging task by leveraging the data already present in our application. By avoiding third-party services, we are able to avoid the hassle of explicit dependencies.

Summary

There are numerous application workflows that are commonly found in modern websites, which often pose a challenge for QA teams when it comes to automation. In this article, we have provided an example of a real-life application to demonstrate how a challenging process can be further explored and effectively automated, using creative approaches. By exploring this article, readers will be inspired to look further into find creative solutions in their own projects.

Source code

If you are looking for a modern End-to-End testing boilerplate project, CodeceptJS Playwright Typescript Boilerplate might be the one for you. It’s available in Bear Plus GitHub space.

--

--