Commit graph

2 commits

Author SHA1 Message Date
Nicolas FRYDER
b5e3ef91ab test: couvrir adminAuth, réparer la CI Python et une couverture annoncée à tort
Some checks are pending
CI / javascript (push) Waiting to run
CI / python (push) Waiting to run
CI / mutation (push) Waiting to run
adminAuth.js était le fichier le moins couvert du dépôt — 52 % de score de
mutation, 22 mutants sans aucune couverture — alors qu'il porte JWT, bcrypt et
le verrouillage de compte. seedAdminUser, recordLoginAttempt, markLoginSuccess
et writeAuditLog n'avaient aucun test direct. writeAuditLog était le plus
gênant : il peut cesser d'enregistrer sans qu'aucune action admin n'échoue et
sans qu'aucun test ne rougisse, et un journal d'audit muet ne se remarque que
le jour où on en a besoin.

Mesuré après coup : adminAuth.js passe de 52,31 % à 84,29 %, les mutants sans
couverture de 22 à 1, et le score global de 82,20 % à 88,85 %.

Le job Python de la CI n'installait que ruff, pytest et pip-audit : psycopg2,
beautifulsoup4, lxml et hypothesis manquaient, et il aurait échoué dès la
collecte — ce que personne n'a jamais vu, faute de runner enregistré. Il part
désormais de requirements-dev.txt, et lance aussi la suite du crawler, qui
n'était pas exécutée du tout.

requirements-dev.txt épinglait psycopg2-binary==2.9.9, sans roue pour Python
>= 3.13 : la suite entière s'arrêtait dès la collecte sur un poste par ailleurs
sain. Épinglages assouplis en bornes basses.

Corrige enfin le commentaire de a11y.test.js, qui renvoyait à « l'audit
Lighthouse manuel du README de la CI » pour justifier deux règles désactivées.
Cet audit n'existe pas : README-CI.md documente le test e2e de l'admin, qui
couvre bien le contraste mais UNIQUEMENT pour le dashboard. Pour le site
public, ces règles ne sont vérifiées nulle part. La couverture n'a pas changé,
seule sa description était fausse.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 14:49:04 +02:00
60074fb015 feat(qualité): outillage de test complet, CI locale, annulation réelle des runs
Some checks are pending
CI / javascript (push) Waiting to run
CI / python (push) Waiting to run
CI / mutation (push) Waiting to run
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