MailFlatDocs
Documentation/Test frameworks & CI/Vitest

Email testing with Vitest

The same flow as Jest with typed fixtures: Vitest picks up the client's TypeScript types with no extra setup.

How it fits together

Vitest inherits Vite's TypeScript handling, so the client's types work out of the box. As with Jest, the only trap is the default timeout being shorter than real email delivery.

Skip the setup

The steps below are what a working project looks like. If you want that project rather than the explanation, generate it — one runnable smoke test, one signup test to edit, and a gitignored .env for your key.
Shell
npm create mailflat@latest -- --template vitest
Zero dependencies of its own; the generated project pulls the SDK.

The test

TypeScript
// signup.test.ts
import { beforeEach, afterEach, expect, test } from "vitest";
import { MailFlat, type Inbox } from "@mailflat/sdk";
 
const mf = new MailFlat({ apiKey: process.env.MAILFLAT_API_KEY! });
let inbox: Inbox;
 
beforeEach(async () => {
inbox = await mf.create({
prefix: `vitest-${Date.now().toString(36)}`,
retentionHours: 2,
});
});
 
afterEach(async () => {
await inbox.delete();
});
 
test("signup sends a verification code", async () => {
await api.post("/signup", { email: inbox.address });
 
const otp = await inbox.waitForOtp({ timeout: 60_000 });
expect(otp).toMatch(/^\d{6}$/);
}, 70_000);

Or in the config

TypeScript
// vitest.config.ts
export default defineConfig({
test: { testTimeout: 70_000, hookTimeout: 30_000 },
});

Worth knowing

hookTimeout matters too: creating an inbox in beforeEach is an HTTP call.