Guides

Tester les emails de vérification Better Auth

Vérifiez les emails d’inscription Better Auth dans une application Next.js avec Playwright.

Better Auth envoie les liens de vérification, les liens magiques et les codes à usage unique via SMTP, si bien qu’une application Next.js peut les acheminer vers InboxTap et tester chaque parcours d’authentification de bout en bout. Le projet complet et exécutable se trouve dans examples/better-auth-nextjs.

Brancher Better Auth sur InboxTap

Créez une fonction utilitaire Nodemailer pointée vers le port SMTP d’InboxTap. InboxTap parle SMTP simple, donc le transport désactive TLS et n’envoie aucun identifiant :

import { createTransport } from "nodemailer";

const transport = createTransport({
  host: process.env.SMTP_HOST ?? "localhost",
  port: Number(process.env.SMTP_PORT ?? 1025),
  secure: false,
  ignoreTLS: true,
});

Faites passer chaque fonction de rappel d’envoi de Better Auth par cette fonction utilitaire, en gardant chaque email en texte simple avec exactement un lien ou un code à six chiffres pour que l’extraction reste déterministe :

export const auth = betterAuth({
  database: new Database("./auth.db"),
  emailAndPassword: { enabled: true, requireEmailVerification: true },
  emailVerification: {
    sendOnSignUp: true,
    autoSignInAfterVerification: true,
    sendVerificationEmail: async ({ user, url }) => {
      await sendMail({ to: user.email, subject: "Verify your email", text: `Open: ${url}` });
    },
  },
  plugins: [
    magicLink({
      sendMagicLink: async ({ email, url }) => {
        await sendMail({ to: email, subject: "Your sign-in link", text: `Sign in: ${url}` });
      },
    }),
    emailOTP({
      sendVerificationOTP: async ({ email, otp }) => {
        await sendMail({ to: email, subject: "Your sign-in code", text: `Your code is ${otp}` });
      },
    }),
  ],
});

Piloter les flux avec Playwright

Laissez Playwright gérer les deux processus : webServer démarre npx inboxtap, attend son point de terminaison de contrôle d’état, puis démarre l’application. En local, il réutilise les serveurs que vous avez déjà lancés.

export default defineConfig({
  testDir: "./tests",
  use: { baseURL: "http://localhost:3000" },
  webServer: [
    {
      command: "npx inboxtap",
      url: "http://localhost:8025/health",
      reuseExistingServer: !process.env.CI,
    },
    {
      command: "npm run db:migrate && npm run dev",
      url: "http://localhost:3000",
      reuseExistingServer: !process.env.CI,
      timeout: 120_000,
    },
  ],
});

Chaque test crée sa propre boîte, s’inscrit via le vrai formulaire et suit le lien capturé :

test("signs up, verifies via the emailed link, and lands signed in", async ({ page }) => {
  const inbox = await inboxTap.createInbox({ alias: "signup" });

  await page.goto("/signup");
  await page.getByLabel("Email").fill(inbox.address);
  await page.getByLabel("Password").fill(password);
  await page.getByRole("button", { name: "Create account" }).click();

  const verificationUrl = await inbox.waitForLink({
    subject: /verify your email/i,
    timeoutMs: 20_000,
  });
  await page.goto(verificationUrl);

  await page.goto("/");
  await expect(page.getByText(`Signed in as ${inbox.address} (verified: true)`)).toBeVisible();
});

Le test de lien magique fonctionne de la même façon avec un filtre de sujet différent, et le test d’OTP remplace waitForLink() par waitForCode() — l’OTP par défaut de Better Auth fait six chiffres, ce qui correspond exactement au motif de code par défaut d’InboxTap.

Lancer le projet d’exemple

cd examples/better-auth-nextjs
npm install
npx playwright install chromium
npm test

La suite couvre la vérification à l’inscription, la connexion bloquée avant vérification, l’auto-inscription par lien magique, la connexion par OTP et le renvoi de code — sans jongler entre terminaux, car les tests démarrent eux-mêmes InboxTap et l’application. Le README de l’exemple documente aussi un déroulé interactif : npx inboxtap dans un terminal, npm run dev dans un autre, puis inscrivez-vous et lisez l’email capturé avec curl http://localhost:8025/api/emails/latest.