Examples
Playwright
Learn how to test email workflows in Playwright using Trivumo.
Email verification, password resets, magic links, invitations, and OTP-based flows are common parts of modern applications. Trivumo makes it easy to validate these workflows directly from your Playwright tests.
Install
npm install trivumoCreate a Client
import { TrivumoClient } from 'trivumo';
export const trivumo = new TrivumoClient({
apiKey: process.env.TRIVUMO_API_KEY!,
domain: process.env.TRIVUMO_DOMAIN!,
});Verify Email Signup Flow
Generate a unique email address, sign up, wait for the verification email, and follow the verification link.
import { test, expect } from '@playwright/test';
import { TrivumoClient } from 'trivumo';
const trivumo = new TrivumoClient({
apiKey: process.env.TRIVUMO_API_KEY!,
domain: process.env.TRIVUMO_DOMAIN!,
});
test('user can verify their email', async ({ page }) => {
const email = trivumo.generateEmail();
await page.goto('http://localhost:3000/signup');
await page.getByLabel('Email').fill(email);
await page.getByLabel('Password').fill('Password123!');
await page.getByRole('button', { name: 'Create Account' }).click();
const message = await trivumo.waitForMessage({
to: email,
subject: 'Verify your account',
});
const verificationLink =
message.html?.links[0]?.href;
await page.goto(verificationLink!);
await expect(
page.getByText('Email verified')
).toBeVisible();
});Password Reset Flow
Wait for the reset email after triggering a password reset.
test('user can reset password', async ({ page }) => {
const email = 'user@example.com';
await page.goto('http://localhost:3000/forgot-password');
await page.getByLabel('Email').fill(email);
const message = await trivumo.waitForMessageAfter(
() =>
page.getByRole('button', {
name: 'Send Reset Link',
}).click(),
{
to: email,
subject: 'Reset your password',
}
);
const resetLink =
message.html?.links[0]?.href;
await page.goto(resetLink!);
await page.getByLabel('New Password')
.fill('NewPassword123!');
await page.getByRole('button', {
name: 'Update Password',
}).click();
await expect(
page.getByText('Password updated')
).toBeVisible();
});Magic Link Login
Validate passwordless authentication flows.
test('user can login with magic link', async ({ page }) => {
const email = trivumo.generateEmail();
await page.goto('http://localhost:3000/login');
await page.getByLabel('Email').fill(email);
const message = await trivumo.waitForMessageAfter(
() =>
page.getByRole('button', {
name: 'Send Magic Link',
}).click(),
{
to: email,
subject: 'Sign in to your account',
}
);
const magicLink =
message.html?.links[0]?.href;
await page.goto(magicLink!);
await expect(
page.getByText('Welcome back')
).toBeVisible();
});One-Time Password (OTP)
Extract verification codes directly from emails.
test('user can login using OTP', async ({ page }) => {
const email = trivumo.generateEmail();
await page.goto('http://localhost:3000/login');
await page.getByLabel('Email').fill(email);
const message = await trivumo.waitForMessageAfter(
() =>
page.getByRole('button', {
name: 'Send Code',
}).click(),
{
to: email,
}
);
const otp =
message.html?.codes[0] ??
message.text?.codes[0];
await page.getByLabel('Code').fill(otp!);
await page.getByRole('button', {
name: 'Verify',
}).click();
await expect(
page.getByText('Successfully logged in')
).toBeVisible();
});Validate Email Content
Assert on email subjects, content, and links.
test('welcome email contains onboarding link', async () => {
const email = trivumo.generateEmail();
const message = await trivumo.waitForMessage({
to: email,
subject: 'Welcome to Acme',
});
expect(message.subject).toBe('Welcome to Acme');
expect(
message.html?.body
).toContain('Getting Started');
expect(
message.html?.links.some(
link => link.href.includes('/onboarding')
)
).toBeTruthy();
});Best Practice: Use waitForMessageAfter
Using waitForMessageAfter() prevents tests from accidentally matching emails that were received before the action under test.
const message = await trivumo.waitForMessageAfter(
() => page.getByRole('button').click(),
{
to: email,
subject: 'Verify your account',
}
);