Playwright
Setup
Install the MailOven client:
sh
npm install -D @mailoven/clientsh
yarn add -D @mailoven/clientsh
pnpm add -D @mailoven/clientsh
bun add -D @mailoven/clientsh
deno add -D npm:@mailoven/clientExample: using the client in the tests
typescript
// tests/password-reset.spec.ts
import { test, expect } from "@playwright/test";
import { MailOvenClient } from "@mailoven/client";
const mailoven = new MailOvenClient({
apiKey: process.env.MAILOVEN_API_KEY!,
slug: "acme",
});
test("password reset sends email with reset link", async ({ page }) => {
const inbox = "reset-test";
await mailoven.deleteInbox(inbox);
await page.goto("/forgot-password");
await page.locator('input[name="email"]').fill(mailoven.getEmailAddress(inbox));
await page.getByRole("button", { name: "Send reset link" }).click();
const email = await mailoven.waitForEmail({
to: inbox,
filter: { subject: "Reset your password" },
});
const resetLink = email.bodyText?.match(/https?:\/\/\S*reset\S*/)?.[0];
expect(resetLink).toBeTruthy();
await page.goto(resetLink!);
await expect(page.locator("h1")).toContainText("Reset");
});Example: screenshot an email in the MailOven UI
The MailOven web UI supports API key authentication via the Authorization header, so you can open any email's rendered view directly in Playwright and take a screenshot — useful for visual regression tests on email templates.
typescript
// tests/email-screenshot.spec.ts
import { test, expect } from "@playwright/test";
import { MailOvenClient } from "@mailoven/client";
const API_KEY = process.env.MAILOVEN_API_KEY!;
const mailoven = new MailOvenClient({ apiKey: API_KEY, slug: "acme" });
test("welcome email matches screenshot", async ({ browser }) => {
const inbox = "screenshot-test";
await mailoven.deleteInbox(inbox);
// Trigger your app to send the email
await fetch("http://localhost:3000/api/signup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: mailoven.getEmailAddress(inbox) }),
});
const email = await mailoven.waitForEmail({
to: inbox,
filter: { subject: "Welcome" },
});
// Open a browser context with the API key header
const context = await browser.newContext({
extraHTTPHeaders: {
Authorization: `Bearer ${API_KEY}`,
},
});
const page = await context.newPage();
await page.goto(`${mailoven.getInboxEndpoint(inbox)}/${email.id}`);
await expect(page).toHaveScreenshot("welcome-email.png");
await context.close();
});bash
MAILOVEN_API_KEY=mo_your_api_keyFixture-based approach
For cleaner tests, wrap the client in a Playwright fixture:
typescript
// tests/fixtures.ts
import { test as base } from "@playwright/test";
import { MailOvenClient } from "@mailoven/client";
type MailOvenFixtures = {
mailoven: {
client: MailOvenClient;
uniqueInbox: () => string;
};
};
export const test = base.extend<MailOvenFixtures>({
mailoven: async ({}, use) => {
const client = new MailOvenClient({
apiKey: process.env.MAILOVEN_API_KEY!,
slug: "acme",
});
const inboxes: string[] = [];
const uniqueInbox = () => {
const name = `test-${crypto.randomUUID().slice(0, 8)}`;
inboxes.push(name);
return name;
};
await use({ client, uniqueInbox });
// Clean up all inboxes used in the test
await Promise.all(inboxes.map((inbox) => client.deleteInbox(inbox)));
},
});
export { expect } from "@playwright/test";typescript
// tests/example.spec.ts
import { test, expect } from "./fixtures";
test("signup sends verification email", async ({ page, mailoven }) => {
const inbox = mailoven.uniqueInbox();
await page.goto("/signup");
await page.locator('input[name="email"]').fill(mailoven.client.getEmailAddress(inbox));
// ... rest of test
const email = await mailoven.client.waitForEmail({
to: inbox,
filter: { subject: "Verify" },
});
expect(email.subject).toContain("Verify");
});