# Tests E2E Playwright > Version : 0.1 · Dernière maj : 2026-05-18 > Stack : Playwright + Chromium · DB séparée `rubis_test_e2e` · Stripe mocké Tests end-to-end qui simulent un **vrai user** interagissant avec la SPA + landing dans un Chromium headless (ou headed). Validation complète de la chaîne navigation, formulaires, redirections, hydratation Tanstack, fetch API, persistence DB. Complémentaires aux tests : - **Unit** (`apps/api/tests/unit/`) : logique pure, fonctions isolées. - **Functional HTTP** (`apps/api/tests/functional/`) : routes API via japa ApiClient. - **Vitest SPA** (`apps/web/src/**/*.test.tsx`) : hooks + composants isolés. - **E2E Playwright** (`e2e/tests/`) ← *vous êtes ici*. Navigateur réel, full stack. --- ## Pré-requis (une fois) 1. **PostgreSQL** local accessible (généralement via docker-compose dev) : ```bash pnpm dev:up # spin up Postgres + Redis + Mailpit + MinIO ``` 2. **Setup de la DB de test** : ```bash pnpm e2e:setup ``` Crée `rubis_test_e2e` (si absente) et applique toutes les migrations Adonis. 3. **Chromium Playwright** (déjà fait si tu as `pnpm install` après ce commit) : ```bash pnpm exec playwright install chromium ``` --- ## Lancement ```bash # Headless (CI / dev rapide) pnpm e2e # Headed (regarder le navigateur en action — debug) pnpm e2e:headed # UI interactive (mode dev Playwright, idéal pour itérer) pnpm e2e:ui ``` Playwright **spawn lui-même** l'API Adonis (port 3333) et la SPA Vite (port 5173) en mode `test_e2e` avant de lancer les tests. Pas besoin de `pnpm dev` à part. Si tu as déjà ton stack qui tourne, set `E2E_SKIP_WEBSERVER=1`. ### Variables d'env | Variable | Default | Rôle | |---|---|---| | `E2E_PG_DB_NAME` | `rubis_test_e2e` | Nom de la DB de test | | `E2E_WEB_URL` | `http://localhost:5173` | Base URL SPA | | `E2E_API_URL` | `http://localhost:3333` | Base URL API (pour les helpers reset/mock) | | `E2E_SKIP_WEBSERVER` | unset | Si défini, Playwright n'essaie pas de spawn API+SPA | | `CI` | unset | Active retries + reporter github + traces | --- ## Architecture ### Stripe mocké côté API Le SDK Stripe est remplacé par un mock déterministe via `__setStripeForTests` (cf. `apps/api/app/services/stripe.ts`). En `NODE_ENV=test_e2e`, les endpoints suivants sont exposés (gated, 404 sinon) : | Endpoint | Rôle | |---|---| | `POST /__test__/reset` | TRUNCATE des tables applicatives + ré-install mock par défaut | | `POST /__test__/stripe/mock` | Switch de scenario (`trial_happy`, `trial_decline`) | | `POST /__test__/stripe/webhook` | Simule un event Stripe sans signer manuellement | | `GET /__test__/state/org/:id` | Inspection directe DB d'une org | Ces endpoints sont **invisibles** en prod : le contrôleur throw 404 si `NODE_ENV !== 'test_e2e'`. Aucun risque de fuite. ### DB de test isolée `rubis_test_e2e` est physiquement séparée de `rubis` (dev). Chaque test commence par `await resetDb()` qui TRUNCATE les tables. Aucune pollution croisée. Le TRUNCATE CASCADE prend ~50 ms ; bien plus rapide qu'un drop/recreate. Tests séquentiels (`workers: 1`) pour ne pas avoir 2 truncates en parallèle. ### Mocking Stripe au niveau navigateur ? **Non.** On mocke **côté API**, pas côté navigateur. Pourquoi : la SPA appelle de toute façon notre API, et notre API appelle Stripe. Mocker côté navigateur (via Playwright `route()`) ne couvrirait que les appels directs SPA → Stripe, ce qui n'existe pas dans notre archi (tout passe par l'API). L'avantage : on teste l'intégralité de notre code applicatif comme en prod, seul Stripe est rempl. ### Limites — ce qui n'est PAS testé - **L'UI Stripe Checkout** (3DS challenge, formulaire CB) — externe à notre app, mocké. Pour valider : utiliser le **playbook manuel** [stripe-trial-e2e-playbook.md](./stripe-trial-e2e-playbook.md) avec Stripe Test Clocks. - **Le prélèvement réel à J+14** — nécessite Stripe Test Clocks + advance, hors scope automation. - **Les emails sortants** — capturés par Mailpit en dev, mais les tests E2E ne vérifient pas le rendu HTML pixel-perfect (le visual regression viendrait en V2). --- ## Scénarios couverts (V1) | Fichier | Scénarios | |---|---| | `tests/signup.spec.ts` | Signup + onboarding 3 étapes → dashboard | | `tests/billing-trial.spec.ts` | Démarrer essai 14j (mock Stripe), fallback Free, retour `?trial=cancel`, inspection DB post-action | Chaque scénario tourne en **~3 s** en headless. La suite complète : ~30 s. --- ## Étendre Ajouter un nouveau test : créer `e2e/tests/.spec.ts` qui suit le pattern : ```ts import { test, expect } from '@playwright/test' import { resetDb } from './helpers/api' test.describe('Ma feature', () => { test.beforeEach(async () => { await resetDb() }) test('mon scénario', async ({ page }) => { await page.goto('/signup') // ... }) }) ``` Pour simuler un webhook Stripe au milieu du scénario : ```ts import { fireStripeWebhook } from './helpers/api' await fireStripeWebhook({ type: 'customer.subscription.trial_will_end', data: { object: { customer: 'cus_e2e_mock', id: 'sub_xxx' } }, }) ``` Pour inspecter l'état DB sans naviguer dans le SPA : ```ts import { getOrgState } from './helpers/api' const state = await getOrgState(orgId) expect(state?.plan).toBe('pro') ``` --- ## CI À ajouter dans le pipeline Gitea (suit le pattern de `apps/api` actuel) : ```yaml # .gitea/workflows/e2e.yml (à créer) e2e: steps: - run: pnpm install - run: pnpm dev:up # Postgres + Redis + Mailpit - run: pnpm exec playwright install --with-deps chromium - run: pnpm e2e:setup - run: pnpm e2e - if: failure() uses: actions/upload-artifact@v4 with: name: playwright-report path: playwright-report/ ``` Tant que la CI E2E n'est pas montée, les tests se lancent **uniquement en local** avant les déploiements sensibles (changement signup, billing, onboarding). --- ## Troubleshooting - **« could not connect to server: Connection refused »** → `pnpm dev:up` pour démarrer Postgres. - **« Database "rubis_test_e2e" does not exist »** → `pnpm e2e:setup`. - **« Timed out waiting for http://localhost:3333/api/v1/health »** → l'API ne boot pas. Vérifier `apps/api/.env` (APP_KEY notamment). Lancer manuellement `cd apps/api && NODE_ENV=test_e2e pnpm dev` pour voir les erreurs. - **« Stripe SDK not initialized »** → l'endpoint `/__test__/stripe/mock` n'a pas été appelé. `resetDb()` le fait par défaut au début de chaque test. - **Tests flaky** → augmenter `timeout` dans playwright.config.ts. La SPA peut être lente sur certaines machines.