metalfrom.eu/stryker.config.json
Nicolas Fryder 60074fb015
Some checks are pending
CI / javascript (push) Waiting to run
CI / python (push) Waiting to run
CI / mutation (push) Waiting to run
feat(qualité): outillage de test complet, CI locale, annulation réelle des runs
Le dépôt n'avait aucun test, aucun linter, aucune vérification de types.

Outillage
- ESLint 9 (flat config) sur api + les deux frontends, Ruff sur le Python
- tsc --checkJs sur l'API (pas de TypeScript, juste la vérification)
- Vitest : 401 tests JS ; pytest : 43 tests Python
- Tests de mutation (Stryker), deux profils : logique pure et API complète
- Hook pre-push `npm run check` (~17 s) — le déploiement Coolify est sur webhook,
  c'est donc la seule porte de qualité avant la mise en ligne
- Workflow Forgejo Actions prêt (inerte tant qu'aucun runner n'est enregistré)

Sécurité
- Injection SQL authentifiée dans resolve-conflict : `field` était interpolé
  dans le SET sans allowlist
- timingSafeEqual levait sur un jeton multi-octets (500 au lieu de 401)
- setErrorHandler écrasait tous les 4xx en 500
- .env.example : ADMIN_JWT_SECRET et ADMIN_SEED_* n'étaient documentés nulle part
  alors que leur absence casse toute connexion admin

Annulation réelle des crawl_run (migration 014)
- L'API posait status='error' sans que le crawler en sache rien : le process
  continuait, et son UPDATE final ne matchait plus (run réussi affiché en erreur)
- Protocole coopératif : drapeau cancel_requested lu à chaque lot, le crawler
  écrit lui-même status='cancelled'

Cohérence géographique (migration 014)
- Le trigger 013 supprimait les band_locations sans purger le point dénormalisé
- L'édition admin de lat/lon n'atteignait jamais band_locations : la carte
  ignorait la correction. Override step_order = -1, dans une transaction

Corrections
- limit/offset NaN → 500 au lieu de 400
- OPTIONS sans `return reply` (Fastify poursuivait le cycle de vie)
- listen() sans catch, cast ::text en dur sur les colonnes numériques
- /admin/api/logs ne renvoyait pas sa pagination
- a11y : sélecteur de langue annoncé comme liste vide (role=option manquant)

Nettoyage
- apps/web/quizz-site supprimé (sans rapport avec le projet)
- Code mort : openModal(), LANG_NAMES, double import, variables inutilisées
- .dockerignore ajoutés ; node_modules racine n'était pas gitignoré

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-18 10:05:40 +02:00

41 lines
No EOL
2.1 KiB
JSON

{
"$schema": "./node_modules/@stryker-mutator/core/schema/stryker-schema.json",
"_comment_role": "Tests de mutation : la seule mesure qui prouve qu'un test ÉCHOUE quand le code casse. La couverture de ligne ne dit que 'ce code a été exécuté', pas 'ce comportement est vérifié'. NE FAIT PAS partie de `npm run check` (cf. README-CI.md) : c'est un audit périodique, pas une porte de pré-push.",
"_comment_perf": "Trois réglages font l'essentiel du temps d'exécution : (1) concurrency alignée sur les cœurs disponibles, (2) coverageAnalysis perTest qui ne rejoue que les tests couvrant chaque mutant, (3) exclusion des mutants StringLiteral sur le code SQL — voir _comment_mutators.",
"_comment_mutators": "excludedMutations StringLiteral : adminRoutes.js et app.js sont à ~80 % des requêtes SQL en template literals. Muter le CONTENU d'une chaîne SQL produit des mutants soit triviaux (la requête ne compile plus), soit indétectables — dans les deux cas ils ne mesurent rien et représentaient la majorité des 1942 mutants. Ce qui compte réellement dans un handler de route, ce sont les CONDITIONS (gardes d'auth, bornes, branches d'erreur), qui restent toutes mutées.",
"packageManager": "npm",
"testRunner": "vitest",
"vitest": {
"configFile": "vitest.mutation.config.js"
},
"reporters": [
"progress",
"clear-text",
"html"
],
"htmlReporter": {
"fileName": "reports/mutation/index.html"
},
"mutate": [
"apps/api/src/validate.js",
"apps/api/src/adminAuth.js"
],
"mutator": {
"excludedMutations": [
"StringLiteral"
]
},
"coverageAnalysis": "perTest",
"ignoreStatic": true,
"concurrency": 10,
"timeoutMS": 15000,
"_comment_incremental": "Après un premier run complet, seuls les fichiers modifiés (et leurs tests) sont rejoués. Les runs suivants tombent de quelques minutes à quelques secondes. Supprimer reports/stryker-incremental.json force un run complet.",
"incremental": true,
"incrementalFile": "reports/stryker-incremental.json",
"thresholds": {
"high": 90,
"low": 75,
"break": 70
},
"tempDirName": ".stryker-tmp"
}