Almost every modern signup flow ends with an email: a verification link, a one-time password (OTP), or a magic login link. These steps are critical, easy to break, and notoriously painful to test automatically. Here's a reliable pattern for verifying them in your test suite without a real human checking a real inbox.

Why email steps break automated tests

Most end-to-end tests stop at "we submitted the signup form" because the next step lives outside the app, in an inbox the test can't see. Teams work around it by skipping verification in test environmentsโ€”but that means the single most important security step ships untested. The fix is to give your test a programmatic inbox it can actually read.

The reliable pattern

The approach is the same regardless of your framework:

  • Generate a unique address per test run so messages never collide.
  • Drive the signup form with that address as you normally would.
  • Poll an inbox API for the newest message to that address.
  • Extract the OTP or verification link from the body and continue the flow.

Example with Playwright


test('user verifies email with an OTP', async ({ page }) => {
  const inbox = `signup_${Date.now()}@testsmail.com`;

  await page.goto('/signup');
  await page.fill('#email', inbox);
  await page.click('#submit');

  // Poll the inbox API for the latest message
  const message = await mail.waitForLatest(inbox, { timeout: 30000 });
  const code = message.text.match(/\b(\d{6})\b/)[1];

  await page.fill('#otp', code);
  await page.click('#verify');
  await expect(page).toHaveURL('/dashboard');
});
            

Tips for stable email tests

  • Always use a fresh address per run so a leftover message from a previous test can't be matched by mistake.
  • Poll with a timeout rather than a fixed sleepโ€”delivery time varies.
  • Match codes with a precise pattern (for example, a six-digit boundary) to avoid grabbing the wrong number from the body.
  • Assert on the outcome, not just the clickโ€”confirm you actually reached the post-verification page.

With a programmatic inbox like testsmail, the verification step becomes just another assertion in your pipeline. You catch broken email flows before users do, and your CI run stays green for the right reasons.