This guide explains how to write end-to-end tests in Playwright that verify email verification flows, covering what to enter, what to expect, and how to handle common pitfalls. You’ll learn practical patterns for confirming sign-up emails, resetting passwords, and validating email content using real or mocked email services.
Why Email Verification Is Hard to Test
Email verification is a critical part of most web apps, but it’s notoriously tricky to automate. The main challenge is that the email is sent by your backend to an external service, and your test needs to access that email to click the link or read the code. This involves crossing trust boundaries and dealing with asynchronous delays. Playwright itself doesn’t have built-in email support, so you must integrate with an email testing service, a local SMTP server, or your own API.
Approaches: Real vs. Mocked Email
You have two fundamental strategies: testing against a real email service (like Mailosaur or Mailinator) or mocking the email sending layer. Real services give you end-to-end fidelity but introduce external dependencies and flakiness. Mocking is faster and more reliable but may miss integration bugs. For most teams, a hybrid works best: use a real service for one critical smoke test and mock for the rest.
Setting Up a Test Mailbox
If you choose a real email service, you need a dedicated mailbox for tests. Services like Mailosaur provide a unique domain (e.g., abc123.mailosaur.net) and an API to fetch messages. In Playwright, you can use the service’s API to wait for the email and extract the verification link. Here’s a typical flow:
- Generate a unique email address using the service’s domain.
- Use that address when signing up in your UI.
- Wait for the email to arrive (poll the API with a timeout).
- Extract the verification link or code from the email body.
- Navigate to the link or enter the code in your app.
Playwright Code Example
Below is a practical example using Mailosaur’s API (you’ll need your API key and server ID). This test signs up a user, waits for the verification email, and clicks the link:
import { test, expect } from '@playwright/test';
const MAILOSAUR_API_KEY = 'your_api_key';
const MAILOSAUR_SERVER_ID = 'your_server_id';
test('user can verify email', async ({ page }) => {
const email = `${Date.now()}@${MAILOSAUR_SERVER_ID}.mailosaur.net`;
await page.goto('/signup');
await page.fill('#email', email);
await page.fill('#password', 'Password123!');
await page.click('button[type=submit]');
// Wait for the email via Mailosaur API
const message = await waitForEmail(email);
const verificationLink = message.html.links[0].href;
await page.goto(verificationLink);
await expect(page.locator('text=Email verified')).toBeVisible();
});
async function waitForEmail(email) {
// Poll the Mailosaur API for up to 30 seconds
const deadline = Date.now() + 30000;
while (Date.now() < deadline) {
const response = await fetch(
`https://mailosaur.com/api/messages?server=${MAILOSAUR_SERVER_ID}&to=${email}`,
{ headers: { Authorization: `Bearer ${MAILOSAUR_API_KEY}` } }
);
const data = await response.json();
if (data.items.length > 0) return data.items[0];
await new Promise(r => setTimeout(r, 2000));
}
throw new Error('Email not received');
}
Note: You must replace the API endpoints and headers with the current ones from your email service provider. The above is illustrative; check the provider’s docs.
Handling Asynchronous Delays
Email delivery is not instant. Your test must wait for the email to arrive, but Playwright’s built-in waitForSelector doesn’t apply to external APIs. You need to poll the email service with a reasonable timeout (30–60 seconds). To avoid flakiness, set a generous timeout and retry logic. Also, consider using Playwright’s expect.poll to wait for the email to appear in your own backend database if you control it.
Common Pitfalls and Solutions
- Email not arriving: Check if your test email address is unique each run; shared addresses can cause conflicts.
- Link expiration: Some verification links expire quickly. If your test fails, increase the timeout or make the expiration longer in test environments.
- Environment differences: Ensure your test environment actually sends emails. Sometimes staging sends to a catch-all or doesn’t send at all.
- Rate limiting: Email services may rate-limit your API calls. Add backoff between polls.
- Email content changes: If your email template changes, your link extraction may break. Use robust selectors (e.g., regex to find the link) rather than hardcoded positions.
Alternatives to External Services
If you want to avoid external dependencies, you can mock the email sending at the SMTP level. Tools like Mailpit or MailHog run a local SMTP server that captures emails. In Playwright, you can configure your app to use that SMTP server and then query Mailpit’s HTTP API to get the email content. This is faster and more reliable, but it doesn’t test the actual delivery path. Another option is to intercept the network request that sends the email and mock the response, but that only works if your frontend makes the request directly.
Frequently Asked Questions
Can I use Playwright’s built-in fixtures to test email?
No, Playwright doesn’t have built-in email support. You need to integrate with an email testing service or mock the email sending. However, you can create a custom fixture that wraps your email service API to make tests cleaner.
How do I test a verification code sent via SMS or email?
For email, you extract the code from the email body using regex or DOM parsing. For SMS, you’d need a service that provides a virtual phone number and an API to read messages. The pattern is similar: wait for the message, extract the code, and enter it in your app.
What if the verification link is not a direct URL but a button that requires JavaScript?
If the email contains a button that triggers a POST request, you can either click it in the email client (if you’re using a real browser) or extract the underlying URL and navigate to it. For security, many apps use POST-only links; you may need to use page.request.post to simulate the click.
How do I avoid test flakiness due to email delays?
Increase the timeout for the email polling, use a unique email address per test run, and consider using a local SMTP server for most tests to reduce latency. Also, make sure your test environment doesn’t have email throttling.
Can I test email verification without a real email service?
Yes, you can mock the email sending by intercepting the network request in Playwright and returning a fake response. This is fast but doesn’t verify the actual email delivery. It’s best for unit-like tests, not full end-to-end.
Is it safe to use a public email service like Mailinator for tests?
Public services are convenient but can be unreliable because other users may access the same inbox. For stable tests, use a dedicated service with unique addresses or a local SMTP server. Avoid using personal emails.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- OnePlus Watch 2 Teased? What We Know
- Vagrant vs Docker: Which Should You Use for Development?
- iQOO Neo 10 vs Neo 10R: Which Phone Should You Choose?
- Embedded OS: What They Do & When You Need One
- Best Sony E-Mount Lenses: Format & Subject Guide
- Samsung Galaxy Note Discontinued? Status Explained