この記事で得られること WebAuthn(パスキー)認証をCI環境でテストする方法 OTPメール取得の自動化(Mailpit API連携) 並列E2Eテストでのメール競合を防ぐテクニック 日本語UIを直接テストするlocale-specific testing はじめに 第1回では、マルチテナントSaaS「Saru」の全体像と自動化戦略を紹介した。今回は、その自動化の核となるE2Eテストの実装詳細を掘り下げる。
特に難しいのが認証フローのテストだ。Saruでは2種類の認証方式を採用している:
ポータル 認証方式 難しさ System / Provider OTP + パスキー メール取得、WebAuthn Reseller / Consumer Keycloak OAuth 外部IdP連携 これらをすべてCIで自動テストする方法を解説する。
1. WebAuthn仮想認証器:パスキーをCIでテスト パスキー認証の課題 WebAuthn(パスキー)は物理的なセキュリティキーや生体認証を使う。普通に考えると、CI環境でテストするのは不可能に思える。
解決策:Chrome DevTools Protocol (CDP) の仮想認証器
Playwrightでは、CDPを通じて仮想的な認証器を作成できる。これにより、物理デバイスなしでWebAuthnのフルフローをテストできる。
注意: CDP仮想認証器はChromium系ブラウザ限定の機能。Safari(WebKit)やFirefoxでは使用できない。クロスブラウザ対応が必要な場合、WebAuthnテストはChromiumでのみ実行し、他ブラウザでは認証済み状態をモックする等の対策が必要になる。
実装コード 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import { test, expect, type BrowserContext } from '@playwright/test'; test('should complete signup with Passkey registration', async ({ page, context }) => { // 仮想認証器を有効化 const cdpSession = await context.newCDPSession(page); await cdpSession.send('WebAuthn.enable'); // 仮想認証器を追加 await cdpSession.send('WebAuthn.addVirtualAuthenticator', { options: { protocol: 'ctap2', // CTAP2プロトコル transport: 'usb', // USB接続をエミュレート hasResidentKey: true, // パスキー対応 hasUserVerification: true, // 生体認証をエミュレート isUserVerified: true, // 常に認証成功 automaticPresenceSimulation: true, // 自動応答 }, }); // ... サインアップフローを実行 ... // Passkey登録ボタンをクリック await page.getByRole('button', { name: 'Passkey' }).click(); // 仮想認証器が自動的に応答し、登録が完了する await expect(page.getByText('Passkey registered')).toBeVisible(); // クリーンアップ await cdpSession.send('WebAuthn.disable'); }); transport設定とサーバー設定の整合性 WebAuthn仮想認証器を設定する際、サーバー側の設定との整合性が重要になる。
...