Playwright によるメールテスト:エンドツーエンドのチュートリアル
このチュートリアルでは、現実のメールフローを Playwright でエンドツーエンドにテストする方法を、モックなしで紹介します。テストごとに使い捨て受信トレイを払い出し、登録を進めてから、認証メールを API 経由で読んでコードを抽出します。使い捨てメール API を土台にしており、開発者のためのメールテストガイドの一部です。
アプローチ
受信トレイはテストごとにひとつ作ります(スイートごとではありません。共用すると古い状態の問題がぶり返します)。ブラウザでフローを発火させ、受信トレイ API をポーリングしてメッセージを取り、簡単なマッチでコードを抽出して、ページに入力し直します。
再利用できるフィクスチャ
受信トレイ呼び出しを Playwright のフィクスチャに包めば、各テストは自動で新しいアドレスを得られ、テスト本体は振る舞いだけに集中できてトランスポートの細部から解放されます。
// inbox.ts — talks to your MoeMail-style API
export async function createInbox() {
const res = await fetch(API + '/emails/generate', {
method: 'POST',
headers: { 'X-API-Key': process.env.MAIL_KEY },
})
return res.json() // { id, address }
}
export async function waitForMessage(id, timeoutMs) {
const deadline = Date.now() + (timeoutMs || 30000)
while (Date.now() < deadline) {
const res = await fetch(API + '/emails/' + id + '/messages', {
headers: { 'X-API-Key': process.env.MAIL_KEY },
})
const list = await res.json()
if (list.messages && list.messages.length) return list.messages[0]
await new Promise(r => setTimeout(r, 1500))
}
throw new Error('no email arrived in time')
}
テスト本体
import { test, expect } from '@playwright/test'
import { createInbox, waitForMessage } from './inbox'
test('verifies signup email', async ({ page }) => {
const inbox = await createInbox()
await page.goto('/signup')
await page.getByLabel('Email').fill(inbox.address)
await page.getByRole('button', { name: 'Sign up' }).click()
const msg = await waitForMessage(inbox.id, 30000)
const code = msg.text.match(/[0-9]{6}/)[0]
await page.getByLabel('Verification code').fill(code)
await expect(page.getByText('Welcome')).toBeVisible()
})
ポーリングループは Date.now() で見張り、マッチで 6 桁のコードを取り出します。リンクが対象なら、URL をマッチさせて page.goto() に渡してください。
不安定さを減らすには
遅延を削るにはポーリングより webhook を優先し、実行ごとに固有のアドレスを与えて並列テストが衝突しないようにし、CI のタイムアウトは短めに保ちましょう。同じレシピは OTP と 2FA ログインにも使え、同じフィクスチャは Cypress や Selenium でもそのまま動きます。
はじめましょう
プロフィールから API キーを取得し、OpenAPI ドキュメントを読んで、上のフィクスチャをスイートに入れてみてください。この考え方が初めての方は、開発者のためのメールテストから始めましょう。