# 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 « X–Y 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é | |---|---|---| | | | | | | | |