PlaywrightAuth0GitHub Actions
Testing Auth0 Email Flows with Playwright
Auth0 sends OTP codes and magic links for passwordless authentication and email verification. Testing these flows in CI requires catching real emails. Here's the complete setup.
The problem
Auth0's passwordless email flow sends a one-time code to verify identity. Most teams skip E2E testing this flow because intercepting Auth0's emails in CI is complex. ZeroDrop makes it straightforward — generate a disposable inbox, use it as the test email, catch the OTP automatically.
Install
npm install zerodrop-client
Testing Auth0 passwordless OTP
import { test, expect } from '@playwright/test';
import { ZeroDrop } from 'zerodrop-client';
const mail = new ZeroDrop();
test('Auth0 passwordless email OTP', async ({ page }) => {
const inbox = process.env.TEST_INBOX ?? mail.generateInbox();
// 1. Navigate to login
await page.goto('/login');
// 2. Enter disposable email on Auth0 Universal Login
await page.fill('[name="username"]', inbox);
await page.click('[name="action"]');
// 3. Auth0 sends OTP to inbox
await expect(page.getByText('code')).toBeVisible({ timeout: 5000 });
// 4. Catch the OTP — auto-extracted, no regex
const email = await mail.waitForLatest(inbox, { timeout: 30000 });
expect(email.otp).not.toBeNull();
// 5. Enter OTP
await page.fill('[name="otp"]', email.otp!);
await page.click('[name="action"]');
// 6. Should be authenticated and redirected
await expect(page).toHaveURL('/dashboard');
});Testing Auth0 email verification on signup
test('Auth0 signup email verification', async ({ page }) => {
const inbox = process.env.TEST_INBOX ?? mail.generateInbox();
// Sign up with disposable inbox
await page.goto('/login');
await page.click('[data-action="sign-up"]');
await page.fill('[name="email"]', inbox);
await page.fill('[name="password"]', 'TestPassword123!');
await page.click('[name="action"]');
// Auth0 sends verification email
const email = await mail.waitForLatest(inbox, { timeout: 30000 });
expect(email.magicLink).not.toBeNull();
// Click verification link
await page.goto(email.magicLink!);
// Should be verified and signed in
await expect(page).toHaveURL('/dashboard');
});GitHub Actions workflow
name: E2E Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npx playwright install --with-deps chromium
- name: Generate test inbox
id: inbox
uses: zerodrop-dev/create-inbox@8706a59 # v1.0.0
- name: Run E2E tests
run: npx playwright test
env:
TEST_INBOX: ${{ steps.inbox.outputs.inbox }}
AUTH0_DOMAIN: ${{ secrets.AUTH0_DOMAIN }}
AUTH0_CLIENT_ID: ${{ secrets.AUTH0_CLIENT_ID }}
AUTH0_CLIENT_SECRET: ${{ secrets.AUTH0_CLIENT_SECRET }}
NEXT_PUBLIC_URL: ${{ secrets.STAGING_URL }}Ready to test your Auth0 flows?
Free tier. No signup. No Docker. Works in CI in 5 minutes.