docs: rapport QA
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 changed file +54 −0
added
docs/QA_REPORT.md
+54 −0
@@ -0,0 +1,54 @@ | ||
| 1 | +# Rapport de vérification (QA) — PHI Conseil | |
| 2 | + | |
| 3 | +Date : 2026-11-08. Environnement : macOS, Node 26.13, pnpm 11.1, Next.js 16.4.5, build de production local (`pnpm build && pnpm start -p 3100`, `CONTACT_TRANSPORT=log`). | |
| 4 | + | |
| 5 | +## Résultats | |
| 6 | + | |
| 7 | +| Vérification | Commande | Résultat | | |
| 8 | +|---|---|---| | |
| 9 | +| Lint | `pnpm lint` | ✅ 0 erreur, 0 avertissement | | |
| 10 | +| Types | `pnpm typecheck` | ✅ | | |
| 11 | +| Tests unitaires | `pnpm test` | ✅ 28/28 (contenu/Zod, validation, limitation de débit, dédoublonnage, CSP, route `/api/contact` incl. honeypot et délai anti-robot, composants, géométrie de la spirale) | | |
| 12 | +| Build de production | `pnpm build` | ✅ 10 routes statiques prérendues + `/api/contact` dynamique | | |
| 13 | +| Tests de bout en bout | `pnpm test:e2e` | ✅ 40 réussis, 8 ignorés volontairement (tests réservés au projet desktop ou mobile), 0 échec — projets Chromium 1440 × 900 et WebKit iPhone 13 | | |
| 14 | +| Accessibilité automatisée | axe-core (WCAG 2.0/2.1/2.2 A+AA) sur les 6 pages, desktop + mobile | ✅ 0 violation | | |
| 15 | +| Débordement horizontal | 360, 390, 768, 1024, 1440, 1920 px sur `/`, `/nous-joindre`, `/services` | ✅ aucun | | |
| 16 | +| Lighthouse mobile (accueil) | lighthouse 12, émulation mobile, Chromium headless local | ✅ Performance 100 · Accessibilité 100 · Bonnes pratiques 100 · SEO 100 — LCP 0,9 s, CLS 0, TBT 20 ms | | |
| 17 | +| En-têtes de sécurité | test e2e `en-têtes de sécurité présents` | ✅ CSP (`frame-ancestors 'none'`, `object-src 'none'`), `nosniff`, `X-Frame-Options`, `Referrer-Policy`, `Permissions-Policy`, HSTS ; `X-Powered-By` retiré | | |
| 18 | +| Formulaire | e2e : erreurs associées aux champs (`aria-invalid`, `aria-describedby`), soumission valide → confirmation ; API : 400 sur payload invalide | ✅ | | |
| 19 | +| Menu mobile | e2e WebKit : ouverture, focus sur « Fermer », Échap, retour du focus, navigation | ✅ | | |
| 20 | +| Liens | e2e : aucun lien interne mort sur l'accueil, 6 pages en 200, 404 personnalisée, sitemap/robots/manifest/icônes servis | ✅ | | |
| 21 | + | |
| 22 | +## Comparaison visuelle avec la maquette | |
| 23 | + | |
| 24 | +Captures dans `docs/screenshots/` (`home-1024.png` à la largeur de la maquette, `home-1440.png`, `home-mobile-390.png`, pages internes). Comparaison section par section à 1024 px : | |
| 25 | + | |
| 26 | +| Section | Fidélité | Écarts connus | | |
| 27 | +|---|---|---| | |
| 28 | +| En-tête | ✅ logo + nom + signature, 5 liens, CTA bleu arrondi, lien actif souligné | signature masquée sous 640 px (place) | | |
| 29 | +| Hero | ✅ fond ivoire, titre serif 3 lignes, sous-titre, bouton, spirale dorée superposée, vagues ivoire/bleu pâle | **photo remplacée par une illustration vectorielle** (droits de la photo de maquette inconnus) ; titre un peu plus grand que la maquette à 1024 px | | |
| 30 | +| Nos services | ✅ titre entre filets dorés, 4 disques bleu-gris + icônes au trait, textes exacts | icônes redessinées (proches, non identiques) | | |
| 31 | +| À propos | ✅ image gauche + courbe ivoire, surtitre doré, titre, paragraphe, bouton contour, 4 coches dorées avec filet vertical | **photo remplacée** (idem) ; surtitre doré assombri (#7c5e34 au lieu de ~#bea177) pour atteindre le contraste AA 4,5:1 | | |
| 32 | +| Témoignages | ✅ encadré bleu pâle arrondi, guillemets dorés, serif italique, pagination, pause, clavier, `prefers-reduced-motion` | **masqués en production** (`visible=false`, aucun avis autorisé) ; visibles sur le site de démonstration avec bandeau « exemple non vérifié » (`NEXT_PUBLIC_CONTENT_PREVIEW=1`) | | |
| 33 | +| Bandeau final | ✅ fond bleu ardoise, titre blanc, bouton ivoire, spirale + feuillage dorés | sous-titre en blanc pur (maquette : blanc légèrement transparent) pour le contraste | | |
| 34 | +| Pied de page | ✅ logo + nom, liens séparés par filets, icône courriel, copyright dynamique, signature, liens légaux | icône LinkedIn masquée tant que `social.linkedin` est vide | | |
| 35 | + | |
| 36 | +Le rendu n'a pas été qualifié de « pixel-perfect » : polices (EB Garamond / Figtree) et illustrations diffèrent nécessairement des actifs de la maquette. | |
| 37 | + | |
| 38 | +## Limites de mesure | |
| 39 | + | |
| 40 | +- Lighthouse mesuré en local (latence nulle) : à refaire sur l'hébergement final ; les Core Web Vitals terrain (p75) ne sont disponibles qu'avec du trafic réel. | |
| 41 | +- Le limiteur de débit est en mémoire : comportement validé pour une instance unique. | |
| 42 | +- L'envoi SMTP réel n'a pas été testé (aucun fournisseur/destinataire fourni) ; le transport `log` est explicitement signalé à l'utilisateur dans l'écran de confirmation. Le code SMTP (nodemailer) est en place et testé via un faux mailer. | |
| 43 | +- Tests manuels effectués dans Chromium et WebKit (Playwright) ; Firefox non testé. | |
| 44 | + | |
| 45 | +## Points restant à valider par le client | |
| 46 | + | |
| 47 | +1. Logo vectoriel officiel (sinon approuver la recréation SVG). | |
| 48 | +2. Photos sous licence pour le hero et la section À propos. | |
| 49 | +3. Coordonnées (courriel, téléphone, adresse) et URL LinkedIn. | |
| 50 | +4. Témoignage(s) réel(s) avec autorisation écrite → `approved: true`, `visible: true`. | |
| 51 | +5. Textes juridiques (confidentialité / mentions légales) → `privacy.reviewed: true`. | |
| 52 | +6. Fournisseur SMTP, expéditeur et destinataire du formulaire. | |
| 53 | +7. Choix de la gestion de contenu : fichiers JSON versionnés (livré) ou CMS (Payload/Sanity) — voir `docs/IMPLEMENTATION_PLAN.md` §4. | |
| 54 | +8. Nom de domaine définitif et hébergement. | |
| 55 | ||