Aller au contenu

Guide de tests terrain — PWA et mode hors-ligne

Contexte

La plateforme ESM est une PWA avec mode hors-ligne complet (Workbox + Dexie + SyncManager), pensée pour les agents de terrain en zone à connectivité faible/nulle. Guide de validation avant déploiement terrain (2026-06-17).

Contenu

Architecture offline (fichiers clés)

FrontEnd/src/shared/infrastructure/db/ESMDatabase.ts   ← Schéma Dexie (8 tables + pendingMutations + syncMeta)
FrontEnd/src/shared/infrastructure/db/offlineCache.ts  ← listerAvecCache / obtenirAvecCache
FrontEnd/src/shared/infrastructure/sync/SyncManager.ts ← Flush mutations + pull delta, écoute navigator.onLine
FrontEnd/src/shared/infrastructure/http/offlineQueue.ts← Détection URL→entité, enfilage pendingMutations
FrontEnd/src/shared/components/ui/OfflineBanner.tsx    ← Bandeau rouge/jaune/vert

Piège connu : le service worker ne s'active jamais en npm run dev — toujours tester avec un build de production (npm run build -w FrontEnd + npx serve FrontEnd/dist).

7 scénarios de test (DevTools, poste de dev)

  1. Manifest et installation PWA — icônes, couleur thème, SW activated and running, icône ➕ installable.
  2. App shell hors-ligne — cocher Offline dans DevTools, recharger : l'app doit se charger normalement (pas de ERR_INTERNET_DISCONNECTED).
  3. Hydratation Dexie après chargement en ligne — vérifier IndexedDB esm_offline alimentée + syncMeta.lastSync.
  4. Lecture hors-ligne depuis le cache — bandeau rouge visible, listes/fiches identiques à l'état en ligne, sur 6 modules (enfants, tuteurs, maîtres coraniques, accompagnements, évaluations, formations).
  5. Création hors-ligne (mutation enfilée) — message "enregistrée localement", entrée dans pendingMutations avec CUID généré côté client.
  6. Synchronisation automatique au retour réseau — bandeau jaune puis vert en ~2s, pendingMutations vidée, vérification serveur via curl.
  7. Résolution de conflits — deux onglets modifient le même enfant hors-ligne ; stratégie last-write-wins par updatedAt (pas d'arbitrage humain à ce stade — évolution à planifier si besoin).

Tests terrain réels (téléphone)

Exposition via npx localtunnel --port 3100 ou déploiement VPS direct. Checklists distinctes Android (Chrome, installation "Ajouter à l'écran d'accueil") et iOS (Safari, SW supporté seulement à partir d'iOS 16.4+ — versions antérieures fonctionnent en ligne uniquement). Test de throttling réseau (Slow 3G/2G) pour valider l'utilisabilité en conditions réelles.

Table de diagnostic rapide

Symptôme Cause probable Action
App ne charge pas offline SW non enregistré (testé en dev) Utiliser un build de production
IndexedDB vide après navigation listerAvecCache ne reçoit pas de données Vérifier la réponse réseau dans Network
Mutation absente de pendingMutations Pas en mode Offline au moment de la saisie Vérifier navigator.onLine en console
Bandeau sync bloqué Erreur lors du flush vers /sync Logs backend — chercher ERREUR_SERVEUR
Icône iOS absente/pixelisée apple-touch-icon.png manquant Vérifier FrontEnd/public/apple-touch-icon.png
Conflit mal résolu updatedAt non injecté dans la mutation Vérifier generateOfflineId + updatedAt dans le payload

Décision / Conclusion

3 critères de validation finale avant mise en terrain : zone sans réseau utilisable sans erreur, sync automatique au retour réseau, installation iOS fonctionnelle en plein écran. La stratégie de résolution de conflit (dernière écriture gagne) est un choix assumé, pas un manque — à documenter auprès des agents terrain pour éviter les surprises en cas de double saisie simultanée sur le même enfant.

Liens connexes