DOCS/test-plan-manager-app.md
Thomas Fransolet fdd0213757 Plan de test manager-app pour les 8 commits du 9 au 12 août
356 lignes couvrant ce qui a été livré sur manager-app et jamais ouvert dans un
navigateur : écran Guide IA, éditeur de parcours refondu, écran d'audit log,
compteur d'utilisateurs, compression des images.

Le fichier n'était pas suivi par git — un add explicite ne l'avait jamais vu,
et il serait resté sur un seul disque.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 17:50:50 +02:00

357 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Plan de test — manager-app (modifications du 2026-08-09 au 2026-08-12)
Périmètre : les 8 commits livrés entre le 9 et le 12 août 2026 sur `manager-app`.
Rien ici n'a été vérifié à l'œil dans un navigateur — c'est justement l'objet de ce document.
Mode d'emploi : coche la case si le comportement attendu est constaté, laisse-la vide sinon
et note l'écart sur la ligne. `→` = résultat attendu.
Commits couverts :
| Réf | Commit | Sujet |
|---|---|---|
| §1 | `eb8e849` | Socle visuel (constants.dart) |
| §2 | `bb4d4fe` `eb8e849` | Guide IA — 2 onglets |
| §3 | `bb4d4fe` | Statistiques refondues + export PDF |
| §4 | `bb4d4fe` | Onboarding self-service (auth, abonnement, quota IA) |
| §5 | `b39854a` | DB4 — éditeur de parcours unifié |
| §6 | `bb4d4fe` | Mode de progression du parcours |
| §7 | `5066b6c` | Lot E — PDF en média d'étape, QuestionType |
| §8 | `762448c` | Lot F — écran Activité + compteur d'utilisateurs |
| §9 | `608231f` | C4 — compression des images à l'upload |
| §10 | `9d9f4bc` | Nettoyage du client généré |
| §11 | — | i18n FR / EN / NL et non-régression |
---
## §0. Porte d'entrée
- [ ] `flutter build web` passe sans erreur
- [ ] `flutter analyze` ne remonte que les 3 problèmes connus de `test/widget_test.dart`
- [ ] Connexion, sélection d'instance, chargement du menu latéral → aucun écran blanc
---
## §1. Socle visuel
Le socle (11 rôles typo, 8 espacements, 5 rayons) n'est appliqué que sur les écrans neufs :
Guide IA, Statistiques, Activité. Le reste de l'app garde son style d'origine — c'est voulu.
- [ ] Les écrans Guide IA / Statistiques / Activité utilisent la même palette que le reste de l'app (pas de seconde identité visuelle)
- [ ] Titres, sous-titres et cartes cohérents entre ces trois écrans
- [ ] En 1280 px de large : pas de débordement horizontal, pas de texte tronqué
- [ ] En ~900 px (fenêtre réduite) : les cartes passent en colonne au lieu de se compresser
---
## §2. Guide IA
Menu conditionné à `isAssistant` (même drapeau que la garde d'`AiController`).
### 2.1 Accès
- [ ] Instance avec assistant activé → l'entrée « Guide IA » apparaît dans le menu
- [ ] Instance sans assistant → l'entrée est absente
### 2.2 Onglet « Configuration »
- [ ] Les deux onglets sont visibles et basculent sans rechargement
- [ ] Persona : saisie puis « Enregistrer » → message de succès, valeur retrouvée après F5
- [ ] Réponses de repli : ajout, modification, suppression d'une ligne
- [ ] Wakeword vocal affiché avec le nom configuré
- [ ] Carte « Ce que connaît votre guide » (`GET /api/Ai/knowledge/{id}`) : le nombre de morceaux de contenu s'affiche
- [ ] Une section désactivée puis réindexée → le compteur baisse (l'index vectoriel est la source, pas les tables de contenu)
- [ ] Bouton de réindexation : lancement, retour visible, pas de double envoi si on reclique
- [ ] Aperçu de conversation : une question envoyée reçoit une vraie réponse (`POST /api/AI/chat`, pas une simulation)
- [ ] Aperçu avec des modifications non enregistrées → mention « non enregistré » affichée
- [ ] Échec réseau sur l'enregistrement → snackbar rouge, la saisie n'est pas perdue
### 2.3 Onglet « Ce que demandent vos visiteurs »
Alimenté par `GET /api/Ai/insights/{id}`. **L'endpoint backend n'existe peut-être pas encore** :
si c'est le cas, seul le premier point ci-dessous s'applique, le reste est à rejouer après livraison.
- [ ] Aucune donnée / endpoint absent → état vide illustré (icône + texte), **pas** de cadre creux ni d'erreur
- [ ] Avec des données : les 4 tuiles (questions, sans réponse, thèmes, langues) affichent les bons totaux
- [ ] La tuile « sans réponse » est en ambre, les trois autres en encre normale
- [ ] Bloc ambre « questions sans réponse » listé avec le compteur `n ×` à droite
- [ ] Une carte dont la liste est vide (thèmes non encore regroupés) est **masquée**, pas affichée vide
- [ ] Barres : la plus longue correspond bien à la valeur la plus haute, une seule teinte par carte
- [ ] > 1100 px : les cartes sont côte à côte ; en dessous : empilées
- [ ] Note de confidentialité affichée en bas
---
## §3. Statistiques — écran « Fréquentation »
⚠️ Écran réécrit (+1832 lignes) et **jamais ouvert dans un navigateur** avant ce test.
### 3.1 Chargement et filtres
- [ ] Instance sans droit statistiques → message « indisponible » explicite (pas d'écran vide)
- [ ] Erreur réseau → message d'erreur avec icône, pas de spinner infini
- [ ] Instance sans aucune donnée → message « pas de données »
- [ ] Sélecteur de période : 7 / 30 / 90 / 365 jours → la plage de dates affichée en sous-titre suit
- [ ] Filtre canal : « Tous » + un bouton par canal (Mobile / Tablette / Web / VR / Voix)
- [ ] Chaque bouton de canal affiche son volume
- [ ] Un canal sans donnée sur la période est absent ou inactif
- [ ] Filtre sur un canal unique → message « pas de données pour ce type » si le canal est vide
- [ ] Retour à « Tous » → les valeurs redeviennent celles du total
### 3.2 KPI et bandeau
- [ ] 4 KPI affichés : visites, durée moyenne, contenus par visite, et part vocale **ou** vues totales
- [ ] Chaque KPI porte sa variation vs période précédente (flèche + %)
- [ ] Variation nulle → « stable » avec l'icône neutre, pas « 0 % »
- [ ] Les variations sont cohérentes : passer de 30 à 7 jours change les chiffres ET les variations
- [ ] Bandeau « à retenir » : phrases cohérentes avec les chiffres affichés au-dessus
- [ ] Durée : `1 min 30 s` au-delà de 60 s, `45 s` en dessous
### 3.3 Courbe et tableaux
- [ ] Courbe en aire des visites par jour, un point par jour de la période
- [ ] Bandes de week-end visibles et alignées sur les bons jours (vérifier un samedi précis)
- [ ] Jour de pic annoté avec la bonne date et la bonne valeur
- [ ] Barres horizontales : top contenus, canaux, langues
- [ ] Tableaux détaillés : POI, agenda, quiz, jeux, articles, menu — un tableau vide est masqué
- [ ] Les totaux des tableaux ne contredisent pas les KPI
### 3.4 Export PDF
- [ ] Bouton d'export → le PDF se télécharge
- [ ] Nom du fichier : nom d'instance + intitulé + date
- [ ] **Les chiffres du PDF sont identiques à ceux de l'écran** (KPI, pic, tops) — c'est le point critique
- [ ] La plage de dates du PDF correspond au filtre actif
- [ ] Export avec un filtre canal actif → le PDF reflète ce filtre
- [ ] Le sommaire ne promet **pas** de données inexistantes (parcours terminés, questions au guide IA)
- [ ] Échec de génération → snackbar rouge, l'écran reste utilisable
- [ ] Export sur une période sans données → soit bouton désactivé, soit PDF cohérent (à noter selon le constat)
---
## §4. Onboarding self-service
⚠️ Aucun parcours joué de bout en bout avant ce test.
### 4.1 Mot de passe oublié
- [ ] Lien « mot de passe oublié » accessible depuis l'écran de connexion
- [ ] E-mail inconnu → message neutre (pas de fuite d'existence de compte)
- [ ] E-mail connu → confirmation d'envoi
- [ ] Le mail arrive et son lien ouvre l'écran de définition du mot de passe
### 4.2 Définition du mot de passe
- [ ] Lien valide → formulaire affiché
- [ ] Lien expiré ou déjà consommé → message clair, pas d'erreur technique brute
- [ ] Mot de passe trop court / confirmation différente → erreur de validation avant envoi
- [ ] Définition réussie → redirection vers la connexion, connexion effective avec le nouveau mot de passe
### 4.3 Écran Abonnement
- [ ] Entrée « Abonnement » présente dans le menu
- [ ] Période d'essai en cours → « essai actif » + date de fin correcte
- [ ] Essai sans date de fin → texte de repli, pas de date vide ni de `null`
- [ ] Plan payant actif → intitulé et description du plan
- [ ] Liste « inclus dans votre plan » cohérente avec le plan réel de l'instance
- [ ] Bouton de montée en gamme → ouvre bien la page cible dans un nouvel onglet
- [ ] Section modules complémentaires → mention « bientôt disponible »
### 4.4 Indicateur de quota IA
- [ ] Sous le bouton « Traduire via IA » : `Quota IA : X / Y utilisés ce mois`
- [ ] Plan sans plafond (quota = 0) → « Quota IA : illimité »
- [ ] ≥ 80 % → texte orange + gras + mention « partagé avec l'assistant visiteur »
- [ ] ≥ 95 % → texte rouge
- [ ] Après une traduction, le compteur se met à jour (il ne se rafraîchit que si la clé change — à vérifier)
- [ ] Endpoint quota en échec → **rien** ne s'affiche, la traduction reste possible
---
## §5. Éditeur de parcours unifié (DB4)
Les trois anciennes fenêtres (`showNewOrUpdateGuidedPath` / `GuidedStep` / `QuizQuestion`) sont supprimées.
Profondeur maximale attendue : 2 surfaces (l'éditeur, puis la traduction).
### 5.1 Structure
- [ ] Ouverture d'un parcours → une seule fenêtre : rail d'étapes à gauche, détail à droite
- [ ] Ajouter une question → elle se déplie **sur place**, aucune fenêtre supplémentaire
- [ ] Traduire un champ → la fenêtre de traduction est la seule surface superposée
- [ ] Fenêtre large (≈ 1180 px max) et centrée, pas de barre de défilement horizontale
### 5.2 Sauvegarde au fil de l'eau
Il n'y a **plus** de bouton « Sauvegarder », et plus d'avertissement de perte de travail (garde-fou retiré volontairement).
- [ ] Saisie dans un champ → écriture partie ~700 ms après la dernière frappe (vérifier dans l'onglet Réseau)
- [ ] Frappe continue → une seule requête à la fin, pas une par caractère
- [ ] Ajout / suppression / réordonnancement d'étape → écriture immédiate, sans attendre le débounce
- [ ] Fermer la fenêtre juste après une frappe → la dernière saisie est bien enregistrée (purge à la fermeture)
- [ ] F5 après édition → tout est retrouvé
- [ ] Ouvrir une fenêtre neuve puis la refermer sans rien toucher → **aucun parcours créé en base**
- [ ] Première modification sur une fenêtre neuve → le parcours est créé à ce moment-là
### 5.3 Erreurs et fermeture
- [ ] Backend coupé pendant l'édition → la fenêtre **refuse de se fermer**, un « Réessayer » apparaît en pied de page
- [ ] Backend rétabli + « Réessayer » → l'écriture passe et la fermeture devient possible
- [ ] Retour arrière du navigateur pendant l'édition → passe par la même fermeture (rien n'est perdu)
- [ ] Suppression d'étape → demande de confirmation
- [ ] Confirmation refusée → l'étape reste, aucune requête partie
### 5.4 Pièges backend à vérifier en base
- [ ] Ajouter deux étapes d'affilée → **pas de doublon** en base (les étapes sans id partent par `CreateGuidedStep`)
- [ ] Créer une question, fermer, rouvrir → la question a le bon id et n'est pas dupliquée
- [ ] Réordonner puis ajouter une question → la question reste rattachée à la bonne étape (récupération de l'id par `order`)
- [ ] Supprimer une étape du milieu → les `order` des suivantes sont recalculés
### 5.5 Les deux hébergements du parcours
- [ ] Parcours sous une **SectionParcours** : création, édition, suppression
- [ ] Parcours sous une **SectionMap** : mêmes opérations, même comportement
- [ ] Aucun écart de comportement entre les deux
---
## §6. Mode de progression du parcours
3 questions au lieu des 9 booléens précédents.
- [ ] Trois modes proposés : Libre / Dans l'ordre / Étape par étape, chacun avec sa description
- [ ] Un parcours existant s'ouvre sur le mode correspondant à ses booléens actuels
- [ ] « Libre » → en base : `isLinear = false`, `requireSuccessToAdvance = false`, `hideNextStepsUntilComplete = false`
- [ ] « Dans l'ordre » → `isLinear = true`, `requireSuccessToAdvance = false`
- [ ] « Étape par étape » → `isLinear = true`, `requireSuccessToAdvance = true`
- [ ] Aller-retour entre deux modes puis rechargement → le mode affiché est celui choisi
- [ ] Le comportement côté visitapp correspond au mode choisi (test croisé, cf. `test-plan.md` §19.13)
---
## §7. Lot E — médias d'étape et types de question
- [ ] Média d'une **étape de parcours** : le sélecteur propose Image, Vidéo, Audio **et PDF**
- [ ] Média d'un **slider** : la liste est inchangée (pas de PDF)
- [ ] PDF sélectionné sur une étape → enregistré, retrouvé après rechargement
- [ ] Types de question : Simple / Choix multiple / Puzzle correctement libellés (plus de `number0/1/2`)
- [ ] Changer le type d'une question existante → les champs affichés suivent le type
- [ ] Une question Puzzle enregistrée se rouvre bien en Puzzle
- [ ] Champ « fournisseur de carte » toujours présent, présenté comme réglage mobile/tablette (visitapp-web reste sur Leaflet)
---
## §8. Lot F — Activité et utilisateurs
### 8.1 Accès à l'écran Activité
- [ ] SuperAdmin → entrée « Activité » visible dans le menu (icône historique)
- [ ] InstanceAdmin → entrée **absente**
- [ ] Utilisateur standard → entrée absente
- [ ] Passer de SuperAdmin à un autre rôle sans recharger → l'entrée disparaît
### 8.2 Journal
- [ ] Liste chargée avec colonnes : date, instance, entité, action, utilisateur, id d'entité
- [ ] Actions traduites (Créer / Modifier / Supprimer), pas les valeurs brutes
- [ ] Entités traduites (Section, Ressource, Configuration, Device, Utilisateur)
- [ ] Ids d'instance et d'utilisateur résolus en **noms**
- [ ] Un id qui ne correspond plus à rien (entité supprimée) reste affiché tel quel, sans casser la ligne
- [ ] Clic sur une ligne → détail avant/après en **table**, pas de JSON brut
- [ ] Une création (pas de valeur « avant ») s'affiche proprement
- [ ] Journal vide → message dédié
- [ ] Erreur backend → message d'erreur, pas de spinner infini
### 8.3 Filtres et pagination
- [ ] Filtre instance
- [ ] Filtre type d'entité
- [ ] Filtre utilisateur
- [ ] Filtres de date « du » / « au »
- [ ] Combinaison de plusieurs filtres → résultats cohérents
- [ ] Tout changement de filtre ramène à la page 1
- [ ] **« Réinitialiser les filtres » vide aussi l'affichage des listes déroulantes** (c'était le bug corrigé)
- [ ] Pagination 50 : suivant / précédent, compteur « XY sur Z » exact
- [ ] Bouton précédent inactif en page 1, suivant inactif en dernière page
### 8.4 Compteur d'utilisateurs
- [ ] Écran Utilisateurs : compteur « X / 5 » affiché
- [ ] À 5 utilisateurs → bouton d'ajout désactivé
- [ ] SuperAdmin → **pas** de compteur ni de blocage (sa liste couvre toutes les instances)
- [ ] Création avec un e-mail déjà utilisé (409) → snackbar rouge avec le message serveur
- [ ] Création avec un rôle refusé (403) → snackbar rouge
- [ ] Création valide → utilisateur ajouté à la liste
- [ ] InstanceAdmin → le rôle SuperAdmin n'est pas proposé dans la liste des rôles
> Dettes serveur connues, hors périmètre de ce test : le plafond de 5 n'est pas appliqué par
> `UserController` (un POST direct passe), et aucune section n'est journalisée dans l'audit.
---
## §9. C4 — compression des images à l'upload
Règle : redimensionnement à 2560 px sur le côté long, JPEG q82 — sauf PNG à canal alpha qui reste PNG.
- [ ] Upload d'un JPEG de 6000 px → l'image stockée fait 2560 px sur son côté long
- [ ] Photo en **portrait** → c'est bien la hauteur qui est ramenée à 2560, pas la largeur
- [ ] Le poids affiché dans la liste des ressources correspond au fichier **compressé**, pas à l'original
- [ ] PNG **avec transparence** → reste un PNG, transparence intacte (pas de fond noir)
- [ ] PNG **sans transparence** → ressort en JPEG, et le type MIME suit (vérifier le `Content-Type` servi par Firebase)
- [ ] Petite image déjà bien encodée → l'original est conservé (pas de fichier plus lourd qu'avant)
- [ ] Fichier image corrompu → l'upload passe quand même avec l'original, pas de blocage
- [ ] Fichier non image (PDF, vidéo, audio) → aucun traitement, upload inchangé
- [ ] **Les deux chemins d'upload** (création de ressource et ajout de fichier) compressent identiquement
- [ ] Le quota de stockage augmente de la taille compressée, pas de la taille d'origine
- [ ] Le second chemin d'upload renseigne désormais `sizeBytes` (avant : 0 octet au quota)
- [ ] Upload multiple de plusieurs images → toutes compressées, aucune perdue
> Les ressources créées avant ce commit par le second chemin comptent 0 octet au quota :
> c'est l'existant, il attend le backfill C2 — ne pas le noter comme une régression.
---
## §10. Nettoyage du client généré
- [ ] `flutter analyze manager_api_new` : 3 avertissements légitimes, plus les 67 d'avant
- [ ] `lib/api/openApiTest.dart` a bien disparu (le déclencheur de génération est verrouillé)
- [ ] Aucun écran ne casse à cause d'un modèle supprimé (statistiques, carte, utilisateurs surtout)
- [ ] `tablet-app` compile toujours avec ce client
- [ ] `mymuseum-visitapp` compile toujours avec ce client
- [ ] Le mapping `isGood``isCorrect` des QCM est toujours en place
---
## §11. i18n et non-régression
### 11.1 Langues
- [ ] Sélecteur de langue dans le menu latéral : FR / EN / NL
- [ ] Changement de langue → l'interface bascule immédiatement, sans rechargement
- [ ] La langue est conservée après F5
- [ ] Guide IA : aucune clé manquante en EN, aucune en NL
- [ ] Statistiques : idem
- [ ] Activité : idem (40 clés ajoutées au lot F)
- [ ] Éditeur de parcours : idem (14 clés ajoutées, 3 retirées)
- [ ] Aucun texte du type `guideIaXxx` ou `auditXxx` affiché brut à l'écran
- [ ] En NL et EN, les libellés longs ne débordent pas des boutons et des cartes
### 11.2 Écrans non touchés (contrôle rapide)
- [ ] Configurations : ouverture, édition, enregistrement d'une section de chaque type
- [ ] Ressources : liste, filtre, suppression
- [ ] Applications / liaison configuration : aperçu bento toujours fonctionnel
- [ ] Devices kiosk
- [ ] Clés API
- [ ] Notifications push
- [ ] Déconnexion / reconnexion
---
## Écarts constatés
| § | Ce qui a été observé | Gravité |
|---|---|---|
| | | |
| | | |