Le panneau était découpé par table SQL, pas par question que se pose l'admin. Conséquence : « je constate ici, j'agis dans un autre onglet », et aucun moyen de voir ce qui coince réellement. Redécoupage — un onglet = une question - Pilotage : est-ce que ça tourne ? (fusionne l'ancien « Actions ») - Groupes : trouver et corriger - Localisations : qu'est-ce qui coince dans le géocodage ? ← NOUVEAU - Journal : que s'est-il passé ? - LLM & coûts : combien ça coûte ? Pilotage : chaque chiffre problématique porte son action - Bandeau de santé (groupes, géocodage, file, bloqués, coût) coloré par état - Alertes actionnables : « 12 localisations en erreur » + [Examiner] + [Tout remettre en file], au lieu d'un mur de boutons dans un autre onglet - Déclencheurs de traitements inline, opérations destructives repliées - L'ancien bloc « Éléments de genre » (des centaines de mots-clés jamais consultés) est retiré Localisations : la vue qui manquait totalement L'admin ne disposait que d'actions EN MASSE sur band_locations et d'aucun moyen de voir CE qui échouait. Débloquer un seul lieu supposait de relancer des milliers d'appels Geoapify/Groq facturés. - GET /admin/api/locations liste filtrable (statut, lieu, groupe, pays) - POST /admin/api/locations/:id/requeue relance UNE ligne - PATCH /admin/api/locations/:id saisie manuelle des coordonnées - Diagnostic lisible sans clic : lieu brut, statut, essais, erreur réelle Groupes : recherche d'abord Une barre de recherche et des filtres rapides en chips remplacent les 8 champs texte ; les filtres avancés sont repliés. Accessibilité - Lignes de tableau activables au clavier (role=button, tabindex, Entrée) - Modales : Échap ferme, focus piégé, focus rendu à l'élément d'origine - Contraste : --err (#c61a1a) échouait WCAG AA en texte sur fond sombre (3,4:1). Les messages d'erreur étaient difficiles à lire. Ajout de --err-text / --ok-text (~6,5:1) pour les usages en couleur de texte. Détecté par les nouveaux tests axe sur les vues rendues. - Statuts affichés en français au lieu des valeurs brutes de la base Tests - 36 tests API sur les trois nouveaux endpoints (allowlist de statuts, bornes des coordonnées, audit, 404) - 53 parcours Playwright sur la VRAIE app Fastify + faux pool, dans une topologie identique à la production (statique servi + /admin/* proxifié) - Tests axe sur les vues RENDUES : le test jsdom existant ne voyait que la coquille vide du dashboard, tout étant construit en JavaScript - e2e branché sur le hook pre-push, pas sur `check` : la boucle de développement reste à 6 s, le push coûte 28 s Correction trouvée par les tests Le routeur ne séparait pas la query string du nom de vue : « #/locations?status=error » ne correspondait à aucun alias et retombait sur Pilotage — les liens des alertes ne fonctionnaient pas. Co-Authored-By: Claude <noreply@anthropic.com>
57 lines
1.8 KiB
JavaScript
57 lines
1.8 KiB
JavaScript
import { defineConfig, devices } from "@playwright/test";
|
|
import path from "node:path";
|
|
|
|
/**
|
|
* Parcours de bout en bout du dashboard admin.
|
|
*
|
|
* Le serveur de test (apps/admin/test/e2e/server.mjs) reproduit la topologie de
|
|
* production — statique servi + `/admin/*` proxifié vers la VRAIE application
|
|
* Fastify — avec un faux pool à la place de Postgres. Démarrage ~1 s, aucun
|
|
* conteneur, conformément au principe suivi par le reste de la suite.
|
|
*
|
|
* Performance : les scénarios tournent en parallèle et partagent une session
|
|
* enregistrée une fois par le projet `setup`. Ils ne se marchent pas dessus car
|
|
* aucun ne reprogramme le faux pool : les variations de données passent par
|
|
* `page.route`, qui est propre à chaque onglet.
|
|
*/
|
|
const PORT = Number(process.env.E2E_PORT || 4319);
|
|
const STORAGE_STATE = path.join(process.cwd(), "node_modules/.cache/playwright/admin-auth.json");
|
|
|
|
export default defineConfig({
|
|
testDir: "apps/admin/test/e2e",
|
|
fullyParallel: true,
|
|
workers: process.env.CI ? 2 : 4,
|
|
forbidOnly: !!process.env.CI,
|
|
retries: 0,
|
|
reporter: [["list", { printSteps: false }]],
|
|
timeout: 15000,
|
|
expect: { timeout: 5000 },
|
|
outputDir: "node_modules/.cache/playwright/results",
|
|
|
|
use: {
|
|
baseURL: `http://127.0.0.1:${PORT}`,
|
|
trace: "retain-on-failure",
|
|
screenshot: "only-on-failure",
|
|
video: "off",
|
|
},
|
|
|
|
projects: [
|
|
{ name: "setup", testMatch: /auth\.setup\.js/ },
|
|
{
|
|
name: "chromium",
|
|
testMatch: /.*\.spec\.js/,
|
|
use: { ...devices["Desktop Chrome"], storageState: STORAGE_STATE },
|
|
dependencies: ["setup"],
|
|
},
|
|
],
|
|
|
|
webServer: {
|
|
command: "node apps/admin/test/e2e/server.mjs",
|
|
url: `http://127.0.0.1:${PORT}/`,
|
|
env: { E2E_STANDALONE: "1", E2E_PORT: String(PORT) },
|
|
reuseExistingServer: !process.env.CI,
|
|
timeout: 30000,
|
|
stdout: "ignore",
|
|
stderr: "pipe",
|
|
},
|
|
});
|