Skip to content

How to Test OTP Emails in Playwright

Email verification is one of the most common flows in web apps — and one of the hardest to test reliably. This guide shows you how to test OTP emails in Playwright using Inboxical.

Most teams either skip email testing or resort to hacks:

  • Mocking the email service — fast but doesn’t test the actual email delivery path
  • Shared test inboxes — breaks in parallel test runs when multiple tests read the same inbox
  • Polling with arbitrary waitsawait page.waitForTimeout(5000) hoping the email arrived

All of these lead to either false confidence or flaky tests.

Inboxical gives you isolated test inboxes with a real API. Each test gets its own inbox, emails arrive in real time, and you can assert on content without polling.

Terminal window
npm install @inboxical/playwright

Add INBOXICAL_API_KEY to your environment or .env file:

Terminal window
export INBOXICAL_API_KEY=your_api_key_here
import { test, expect } from '@playwright/test'
import { inboxical } from '@inboxical/playwright'
test('OTP verification flow', async ({ page }) => {
// Create an isolated inbox for this test
const inbox = await inboxical.createInbox()
// Register with the test inbox email
await page.goto('/register')
await page.fill('[name=email]', inbox.emailAddress)
await page.fill('[name=password]', 'SecurePass123!')
await page.click('[type=submit]')
// Wait for the OTP email (long-polls until it arrives)
const messages = await inboxical.waitForMessages(inbox.id)
// Assert email arrived
expect(messages).toHaveLength(1)
expect(messages[0].subject).toBe('Verify your email')
// Extract the OTP automatically
const otp = messages[0].extractedOtp
expect(otp).toHaveLength(6)
// Complete the verification
await page.fill('[name=otp]', otp)
await page.click('[type=submit]')
await expect(page.locator('h1')).toContainText('Dashboard')
})
  • Isolated inbox — no interference from other tests, safe for parallel runs
  • Long-pollingwaitForMessages() blocks until the email arrives, no arbitrary delays
  • OTP extraction — Inboxical parses 4-8 digit codes automatically, no regex in your test
  • Real email path — tests the actual SMTP delivery, not a mock

The same test works in GitHub Actions, GitLab CI, or any CI environment:

- name: Run Playwright tests
run: npx playwright test
env:
INBOXICAL_API_KEY: ${{ secrets.INBOXICAL_API_KEY }}

No SMTP server to spin up, no Docker containers — just an API key.