Metal from Europe — carte interactive des groupes de metal européens (frontend statique + API Node.js + PostgreSQL/PostGIS + geocoder)
Find a file
Nicolas Fryder 83ea8030e7
Some checks are pending
CI / javascript (push) Waiting to run
CI / python (push) Waiting to run
CI / mutation (push) Waiting to run
test: propriétés généralisées, scraper HTML et couche réseau couverts
BUG trouvé par un test de propriété
parse_location_text("0/0") produisait deux lignes identiques. band_locations
impose UNIQUE (ma_id, step_order, location_raw) : le doublon était absorbé par
le ON CONFLICT DO NOTHING de l'enqueue, mais il faussait les compteurs et n'a
aucun sens métier — une étape ne se déroule pas deux fois au même endroit.
Déduplication par dict.fromkeys (ordre préservé) + tests de régression.
Contre-exemple minimal trouvé en 150 tirages, aucun test par l'exemple ne
l'aurait deviné.

SCRAPER HTML (42 tests) — module le plus exposé du crawler, aucun test
jusqu'ici. C'est lui qui extrait genre, statut, thèmes, line-up et dates. Si
Metal Archives change son HTML, il renvoie des champs vides et le crawler
enregistre des fiches creuses SANS lever d'erreur : la panne invisible, donc
la plus coûteuse.
Couvre les trois orthographes de « Lyrical themes » observées chez MA, les
variantes de « label » et « formed in », le regroupement du line-up par
section, l'audit trail, et surtout la dégradation : une page vide ou
malformée ne doit jamais lever et doit rendre une structure complète.

COUCHE RÉSEAU (57 tests) — ma_http et flaresolverr, sans une seule requête
réelle. Ce qui est testé, c'est la logique AUTOUR du réseau : quand réessayer,
quand abandonner, comment extraire les données d'une réponse enveloppée par
FlareSolverr.
Enjeu concret : ces bornes conditionnent le nombre de requêtes envoyées à
Metal Archives — une boucle de retry mal bornée nous ferait bannir. Vérifié
que retries=2 donne exactement 3 tentatives, qu'un 500 n'est PAS réessayé
(contrairement à 403/429/503, qui justifient une session Chrome neuve), et
que les appels de préchauffage Cloudflare sont comptés à part.

PROPRIÉTÉS GÉNÉRALISÉES
- Python (Hypothesis) : parseur de localisations, requêtes de repli,
  centroïdes. Invariants — jamais d'exception, structure toujours complète,
  aucun lieu vide, aucun doublon, nombre de requêtes facturées borné.
- Frontend (fast-check) : échappement HTML (une faille XSS, pas un défaut
  cosmétique — tout le rendu passe par innerHTML), filtrage tri-état, tri
  sans effet de bord ni perte d'éléments, clés de coordonnées.

max_examples fixé à 150 côté Python : ces tests étaient devenus le chemin
critique de `check` (11 s). 150 tirages suffisaient à trouver « 0/0 ».

Tests : 621 JS + 61 intégration, 162 Python, 89 Playwright. check à 9 s.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-18 22:09:37 +02:00
.forgejo/workflows feat(qualité): outillage de test complet, CI locale, annulation réelle des runs 2026-08-18 10:05:40 +02:00
.githooks feat(admin): refonte du panneau par intention, vue Localisations, tests e2e 2026-08-18 15:05:29 +02:00
apps test: propriétés généralisées, scraper HTML et couche réseau couverts 2026-08-18 22:09:37 +02:00
infra feat(qualité): outillage de test complet, CI locale, annulation réelle des runs 2026-08-18 10:05:40 +02:00
scripts perf(tests): porte de qualité 17 s → 6 s, mutation complète 5 min → 3 min 40 2026-08-18 13:49:54 +02:00
.gitignore feat(admin): refonte du panneau par intention, vue Localisations, tests e2e 2026-08-18 15:05:29 +02:00
docker-compose.dev.yml fix: sync du point principal + verrou de migration, redis mort retiré, tests par propriétés 2026-08-18 21:03:17 +02:00
docker-compose.test.yml feat: intégration SQL sur PostgreSQL réel + boutons de crawl conscients du crawler 2026-08-18 20:53:35 +02:00
docker-compose.yml fix: sync du point principal + verrou de migration, redis mort retiré, tests par propriétés 2026-08-18 21:03:17 +02:00
eslint.config.js feat(admin): refonte du panneau par intention, vue Localisations, tests e2e 2026-08-18 15:05:29 +02:00
jsconfig.json perf(tests): porte de qualité 17 s → 6 s, mutation complète 5 min → 3 min 40 2026-08-18 13:49:54 +02:00
package-lock.json fix: sync du point principal + verrou de migration, redis mort retiré, tests par propriétés 2026-08-18 21:03:17 +02:00
package.json fix: sync du point principal + verrou de migration, redis mort retiré, tests par propriétés 2026-08-18 21:03:17 +02:00
playwright.config.js feat(admin): refonte du panneau par intention, vue Localisations, tests e2e 2026-08-18 15:05:29 +02:00
pyproject.toml test: propriétés généralisées, scraper HTML et couche réseau couverts 2026-08-18 22:09:37 +02:00
README-CI.md feat: intégration SQL sur PostgreSQL réel + boutons de crawl conscients du crawler 2026-08-18 20:53:35 +02:00
README.md test deploy 4 2026-06-27 14:05:50 +02:00
requirements-dev.txt test: propriétés généralisées, scraper HTML et couche réseau couverts 2026-08-18 22:09:37 +02:00
stryker.config.json feat(qualité): outillage de test complet, CI locale, annulation réelle des runs 2026-08-18 10:05:40 +02:00
stryker.full.config.json fix(admin): passe de debug guidée par la mutation — 4 bugs, mutation 64 → 68 % 2026-08-18 15:42:52 +02:00
vitest.config.js feat: intégration SQL sur PostgreSQL réel + boutons de crawl conscients du crawler 2026-08-18 20:53:35 +02:00
vitest.integration.config.js feat: intégration SQL sur PostgreSQL réel + boutons de crawl conscients du crawler 2026-08-18 20:53:35 +02:00
vitest.mutation.config.js perf(tests): porte de qualité 17 s → 6 s, mutation complète 5 min → 3 min 40 2026-08-18 13:49:54 +02:00
vitest.mutation.full.config.js perf(tests): porte de qualité 17 s → 6 s, mutation complète 5 min → 3 min 40 2026-08-18 13:49:54 +02:00

Stack metalfrom.eu

test 4