# Plan de Test — Rêve de Dragon FoundryVTT v13

> Dernière mise à jour : 2026-07-22
> System version : 13.0.43
> Foundry compatible : v13, v14

---

## Conventions

| Champ | Description |
|---|---|
| **ID** | `RDD-TC-{domaine}-{NNN}` |
| **Automation** | `PW` = Playwright, `DTC` = Chrome DevTools CLI (démarrage froid), `DTH` = Chrome DevTools Hot (session active), `MAN` = manuel uniquement |
| **Prérequis** | `GM_ONLY` = GM connecté, `PLAYER` = joueur connecté, `ACTOR_PC` = acteur personnage existant, `ACTOR_NPC` = acteur créature/entité existant, `COMPENDIUM` = packs chargés, `SCENE` = scène active |
| **Niveau** | `SMOKE` = test de fumée (critique), `FUNCTIONAL` = fonctionnel, `EDGE` = cas limite, `REGRESSION` = régression |

---

## TC-01 — Infrastructure Cœur

Objectif : valider que le système charge et s'initialise correctement.

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-01-001 | **Le système se charge sans erreur F12** | Foundry démarré, monde ouvert | SMOKE | DTH |
| TC-01-002 | `game.system.id === 'foundryvtt-reve-de-dragon'` | idem | SMOKE | DTH |
| TC-01-003 | `Hooks.on('init')` → `SystemReveDeDragon.onInit()` s'exécute | idem | SMOKE | DTH |
| TC-01-004 | Tous les settings système sont enregistrés (`game.settings.settings.get(game.system.id)` → vérifier 6+ clés) | idem | FUNCTIONAL | DTH |
| TC-01-005 | Tous les document classes sont enregistrés (`CONFIG.Actor.documentClass`, `CONFIG.Item.documentClass`, `CONFIG.ActiveEffect.documentClass`) | idem | SMOKE | DTH |
| TC-01-006 | Toutes les feuilles d'acteur sont enregistrées (5 types : personnage, creature, entite, vehicule, commerce) | idem | FUNCTIONAL | DTH |
| TC-01-007 | Toutes les feuilles d'item sont enregistrées (vérifier 44+ sheets dans `CONFIG.Item.sheetClasses`) | idem | FUNCTIONAL | DTH |
| TC-01-008 | Bannière ASCII affichée dans la console au démarrage | idem | SMOKE | DTH |
| TC-01-009 | Migration exécutée au `ready` (vérifier `game.settings.get('foundryvtt-reve-de-dragon', 'systemMigrationVersion')`) | idem | SMOKE | DTH |
| TC-01-010 | Socket handlers enregistrés (vérifier `game.socket` a des handlers pour ce système) | idem | FUNCTIONAL | DTH |

---

## TC-02 — Acteur Personnage

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-02-001 | **Création d'un Personnage** : `Actor.create({type:'personnage', name:'Test'})` → sheet ouverte, items par défaut injectés (compétences + monnaies) | GM_ONLY | SMOKE | DTH |
| TC-02-002 | **Feuille V2 s'ouvre** : double-clic sur le personnage → `RdDActorSheetV2` rendue sans erreur | ACTOR_PC | SMOKE | DTH |
| TC-02-003 | **Caractéristiques** : modifier une valeur de carac → `actor.updateCarac()` mis à jour, total XP ajusté | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-004 | **XP Carac** : cliquer +/- sur une carac → `updateCaracXP()` → XP dépensé mis à jour | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-005 | **Compétence** : modifier un niveau de compétence → `actor.updateCompetence()` → total XP ajusté | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-006 | **XP Compétence** : cliquer +/- sur une compétence → `updateCompetenceXP()` → XP dépensé mis à jour | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-007 | **Santé (Vie)** : décrémenter `sante.vie` → la barre du token se met à jour | ACTOR_PC, SCENE | FUNCTIONAL | DTH |
| TC-02-008 | **Santé (Endurance)** : décrémenter `sante.endurance` → les segments de fatigue se mettent à jour | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-009 | **Fatigue** : `actor._calculRecuperationSegment()` → segments corrects basés sur Endurance max | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-010 | **Moral** : cliquer +/- → `actor.moralIncDec()` → valeur change, ajustement affiché | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-011 | **Jet de Moral** : déclencher `actor._jetDeMoral()` → message chat avec résultat | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-012 | **Chance** : cliquer +/- → `actor.chanceActuelleIncDec()` → valeur mise à jour | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-013 | **Rêve** : cliquer +/- → `actor.reveActuelIncDec()` → valeur mise à jour | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-014 | **Éthylisme** : `actor.jetEthylisme()` → message chat, malus appliqué si échec | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-015 | **Refoulement** : `actor.ajouterRefoulement()` → refoulement ajouté, `actionRefoulement()` fonctionne | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-016 | **Nourriture** : `actor.mangerNourriture()` → item nourriture consommé, faim soif mises à jour | ACTOR_PC, item NOURRITURE | FUNCTIONAL | DTH |
| TC-02-017 | **Signes Draconiques** : glisser un item `signedraconique` sur la feuille → ajouté dans l'onglet draconique | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-018 | **Sorts Réservés** : `actor.addSortReserve()` → sort ajouté, onglet sorts mis à jour | ACTOR_PC, item SORT | FUNCTIONAL | DTH |
| TC-02-019 | **Expérience** : `actor.distribuerStress()` → stress ajouté, log d'expérience créé | ACTOR_PC | FUNCTIONAL | DTH |
| TC-02-020 | **Signe draconique — suppression** : supprimer un `signedraconique` → retiré de l'onglet draconique, effets annulés | ACTOR_PC | FUNCTIONAL | DTH |

---

## TC-03 — Acteur Créature

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-03-001 | **Création** : `Actor.create({type:'creature', name:'Test'})` → sheet `RdDCreatureSheetV2` rendue | GM_ONLY | SMOKE | DTH |
| TC-03-002 | **Compétences Créature** : ajouter une `competencecreature` → actions disponibles dans MappingCreatureArme | ACTOR_NPC (creature) | FUNCTIONAL | DTH |
| TC-03-003 | **Barres token** : `sante.vie` et `sante.endurance` s'affichent sur le token | ACTOR_NPC, SCENE | FUNCTIONAL | DTH |

---

## TC-04 — Acteur Entité

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-04-001 | **Création entité incarnée** : type `entite`, subtype `incarnee` → sheet V2 rendue | GM_ONLY | SMOKE | DTH |
| TC-04-002 | **Création entité non-incarnée** : subtype `non-incarnee` → sheet V2 rendue | GM_ONLY | FUNCTIONAL | DTH |
| TC-04-003 | **Blurette** : subtype `blurette` → sheet V2 rendue | GM_ONLY | FUNCTIONAL | DTH |
| TC-04-004 | **Possession** : entité → actor personnage → `actor.ajouterPossession()` → possession active créée | ACTOR_PC + entité | FUNCTIONAL | DTH |

---

## TC-05 — Acteur Véhicule

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-05-001 | **Création** : `Actor.create({type:'vehicule', name:'Test'})` → sheet `RdDActorVehiculeSheetV2` | GM_ONLY | SMOKE | DTH |
| TC-05-002 | **Structure/Résistance** : modifier `structure`, `resistance` → barres token mises à jour | ACTOR_NPC (vehicule) | FUNCTIONAL | DTH |

---

## TC-06 — Acteur Commerce

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-06-001 | **Création** : `Actor.create({type:'commerce', name:'Marchand'})` → sheet V2 | GM_ONLY | SMOKE | DTH |
| TC-06-002 | **Achat** : cliquer "Acheter" sur un item du commerce → `DialogItemAchat` s'ouvre, monnaie déduite | ACTOR_PC + ACTOR_NPC (commerce) | FUNCTIONAL | DTH |
| TC-06-003 | **Vente** : glisser un item du joueur vers le commerce → `DialogItemVente` s'ouvre, monnaie créditée | ACTOR_PC + ACTOR_NPC (commerce) | FUNCTIONAL | DTH |

---

## TC-07 — Feuilles d'Item (44 types)

Stratégie : tester les types principaux, les autres suivent le même pattern.

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-07-001 | **Création Arme** : `Item.create({type:'arme', name:'Epée'})` → sheet s'ouvre sans erreur | GM_ONLY | SMOKE | DTH |
| TC-07-002 | **Création Armure** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-003 | **Création Compétence** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-004 | **Création Sort** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-005 | **Création Blessure** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-006 | **Création Maladie** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-007 | **Création Poison** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-008 | **Création Potion** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-009 | **Création Race** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-010 | **Création Tarot** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-011 | **Création Monnaie** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-012 | **Création Signe Draconique** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-013 | **Création Rencontre** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-014 | **Création Service** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-015 | **Création Tâche** : idem | GM_ONLY | SMOKE | DTH |
| TC-07-016 | **Scroll infini** : ouvrir chaque item sheet → vérifier que `.item-sheet-scrollable-body` défile sans overflow caché | ACTOR_PC + items | FUNCTIONAL | DTH |
| TC-07-017 | **Drag item sur acteur** : glisser un item du compendium sur une feuille → ajouté à l'inventaire | ACTOR_PC, COMPENDIUM | FUNCTIONAL | DTH |
| TC-07-018 | **Drop item sur token** : glisser un item du compendium sur un token de scène → item ajouté | ACTOR_PC, COMPENDIUM, SCENE | FUNCTIONAL | DTH |
| TC-07-019 | **Consommation item** : clic droit "Consommer" sur une potion/nourriture → `DialogConsommer` s'ouvre, effet appliqué | ACTOR_PC + item consommable | FUNCTIONAL | DTH |

---

## TC-08 — Système de Jet V1 (RdDRoll)

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-08-001 | **Jet Compétence** : cliquer une compétence → `RdDRoll.create(actor, data, config, 'competence')` → dialogue V2 s'ouvre avec template `dialog-roll-competence.hbs` | ACTOR_PC | SMOKE | DTH |
| TC-08-002 | **Jet Compétence — modificateurs** : ajouter +10 au jet → résultat affiché dans le chat | ACTOR_PC | FUNCTIONAL | DTH |
| TC-08-003 | **Jet Compétence — conditions** : cocher "Fatigué" → malus appliqué au résultat | ACTOR_PC | FUNCTIONAL | DTH |
| TC-08-004 | **Jet Attaque** : cliquer une arme → dialogue attaque avec options (une main, deux mains, lancer, tir) | ACTOR_PC + ARME | SMOKE | DTH |
| TC-08-005 | **Jet Parade** : cliquer "Parade" dans le chat → paramètres de parade (bouclier/arme) → résultat | ACTOR_PC + ARME | FUNCTIONAL | DTH |
| TC-08-006 | **Jet Esquive** : cliquer "Esquive" dans le chat → jet basé sur Esquive compétence → résultat | ACTOR_PC | FUNCTIONAL | DTH |
| TC-08-007 | **Jet Sort** : cliquer un sort → dialogue `dialog-roll-sort.hbs` → résultat avec coût en rêve | ACTOR_PC + SORT | SMOKE | DTH |
| TC-08-008 | **Jet Rêve de Dragon** : clic droit "Rêve de Dragon" → dialogue `dialog-roll-reve-de-dragon.hbs` → résultat | ACTOR_PC | FUNCTIONAL | DTH |
| TC-08-009 | **Jet Éthylisme** : déclencher `actor.jetEthylisme()` → modificateurs d'alcool → résultat chat | ACTOR_PC | FUNCTIONAL | DTH |
| TC-08-010 | **Jet Alchimie** : `DialogLancerRecette` → jet compétence Alchimie → résultat | ACTOR_PC + RECETTE_ALCHIMIQUE | FUNCTIONAL | DTH |
| TC-08-011 | **Message de résultat** : vérifier que les messages chat contiennent : résultat, palier (Particulière/Significative/Normale/Échec), marges, détail des dés | ACTOR_PC | SMOKE | DTH |

---

## TC-09 — Système de Jet V2 (Roll Dialog)

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-09-001 | **Toggle V2 activé** : `game.settings.set('foundryvtt-reve-de-dragon','ROLL_DIALOG_V2',true)` → les jets utilisent `RollDialog` au lieu de `RdDRoll` | ACTOR_PC | FUNCTIONAL | DTH |
| TC-09-002 | **Roll V2 — Compétence** : cliquer compétence → `roll-dialog.mjs` → interface modulaire affichée | ACTOR_PC | FUNCTIONAL | DTH |
| TC-09-003 | **Roll V2 — Attaque** : cliquer arme → dialogue V2 avec roll parts (carac, comp, diff, conditions, état, moral) | ACTOR_PC + ARME | FUNCTIONAL | DTH |
| TC-09-004 | **Roll V2 — Chat Result** : résultat V2 formaté avec `chat-roll-result.mjs` → message chat complet | ACTOR_PC | FUNCTIONAL | DTH |
| TC-09-005 | **Toggle V2 désactivé** : remettre `ROLL_DIALOG_V2: false` → ancien système V1 fonctionne toujours | ACTOR_PC | REGRESSION | DTH |

---

## TC-10 — Dés Custom

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-10-001 | **Dé TMR (d8)** : `game.system.rdd.Dice.roll("1dt")` → `Roll` évalué, résultat 1-8, reroll des 8 | — | FUNCTIONAL | DTH |
| TC-10-002 | **Dé Draconique (d8 explosif)** : `game.system.rdd.Dice.roll("1dd")` → `Roll` évalué, résultat 1-8, explode sur 7 | — | FUNCTIONAL | DTH |
| TC-10-003 | **Dé Heure (d12)** : `game.system.rdd.Dice.rollHeure()` → résultat 0-11 (heure RdD) | — | FUNCTIONAL | DTH |
| TC-10-004 | **DiceSoNice** : si module présent → `Hooks.on('diceSoNiceReady')` → dés 3D custom chargés | DiceSoNice installé | FUNCTIONAL | MAN |
| TC-10-005 | **Résolution d100** : `RdDResolutionTable.rollData({carac:12, level:0})` → résultat avec palier et marges | — | FUNCTIONAL | DTH |

---

## TC-11 — Combat

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-11-001 | **Création combat** : `Combat.create({scene: sceneId})` → `RdDCombat` utilisé, combat ajouté à la tracker | SCENE, GM_ONLY | SMOKE | DTH |
| TC-11-002 | **Initiative — phases** : lancer initiative → `RdDInitiative.roll()` → valeur phase.rang stockée dans `combatant.initiative` | ACTOR_PC, SCENE, combat actif | SMOKE | DTH |
| TC-11-003 | **Initiative — armes** : changer d'arme → `phaseArme()` retourne la bonne phase (Tir=8, Mêlée=5, Pugilat=4) | ACTOR_PC + ARME | FUNCTIONAL | DTH |
| TC-11-004 | **Initiative — premier round** : `processPremierRoundInit()` → ajustement si arme de jet | ACTOR_PC + ARME_TIR, combat actif | FUNCTIONAL | DTH |
| TC-11-005 | **Attaque (Particulière)** : jet attaque → résultat Particulière → choix Force/Finesse/Rapidité dans le chat | ACTOR_PC + ARME, ACTOR_NPC | FUNCTIONAL | DTH |
| TC-11-006 | **Parade** : cliquer "Parade" dans le message d'attaque → `_onParade()` → jet parade → résultat réussi/échoué | ACTOR_PC + ARME, combat | FUNCTIONAL | DTH |
| TC-11-007 | **Esquive** : cliquer "Esquive" → `_onEsquive()` → jet basé sur compétence Esquive | ACTOR_PC, combat | FUNCTIONAL | DTH |
| TC-11-008 | **Encaissement** : cliquer "Encaisser" → `encaisserDommages()` → dialogue validation (optionnel) → dommages réduits par armure | ACTOR_PC + ARMURE, combat | FUNCTIONAL | DTH |
| TC-11-009 | **Distance** : `Distance.typeAttaqueDistance()` → portée courte/moyenne/extreme/inatteignable selon arme et distance | ACTOR_PC + ARME_TIR, SCENE | FUNCTIONAL | DTH |
| TC-11-010 | **Détérioration arme** : parade réussie → `computeDeteriorationArme()` → usure incrémentée, destruction si > max | ACTOR_PC + ARME, combat | EDGE | DTH |
| TC-11-011 | **Empoignade** : `RdDEmpoignade.onAttaqueEmpoignade()` → item `empoignade` créé, chaîne d'effets (entrainer, immobiliser, projeter) | ACTOR_PC, combat | FUNCTIONAL | DTH |
| TC-11-012 | **Recul** : `computeRecul()` → déplacement du token si parade échouée | ACTOR_PC, SCENE, combat | EDGE | MAN |

---

## TC-12 — Calendrier / Temps

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-12-001 | **Calendrier visible** : `RdDCalendrier` rendu dans le header → affiche heure draconique, date, montre analogique | GM_ONLY | SMOKE | DTH |
| TC-12-002 | **Heure Draconique** : vérifier que l'affichage montre une des 12 heures (Vaisseau, Sirène, etc.) | GM_ONLY | SMOKE | DTH |
| TC-12-003 | **Avancement du temps** : `game.rdd.timestamp.addJours(1)` → calendrier mis à jour, heure draconique avancée | GM_ONLY | FUNCTIONAL | DTH |
| TC-12-004 | **Nombres Astraux** : `rdd-calendrier.js` → `nombresAstraux` calculés correctement pour l'heure courante | GM_ONLY | FUNCTIONAL | DTH |
| TC-12-005 | **Auto-Adjust Darkness** : `AutoAdjustDarkness` → obscurité de la scène ajustée selon l'heure | SCENE | FUNCTIONAL | DTH |
| TC-12-006 | **Éditeur de calendrier** : cliquer bouton crayon → `calendar-editor.hbs` dialog → modifier l'heure → calendrier mis à jour | GM_ONLY | FUNCTIONAL | DTH |
| TC-12-007 | **Chronologie** : `/chrono` → `DialogChronologie` s'ouvre, entrées affichées dans l'ordre | GM_ONLY | FUNCTIONAL | DTH |
| TC-12-008 | **Boutons non dupliqués** : ouvrir/fermer le calendrier 3× → un seul bouton crayon et astrologie dans le header | GM_ONLY | REGRESSION | DTH |

---

## TC-13 — Sommeil / Repos

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-13-001 | **Repos (ancien)** : `/sommeil` → `DialogChateauDormant` s'ouvre avec la liste des PJs | ACTOR_PC, GM_ONLY | SMOKE | DTH |
| TC-13-002 | **Château Dormant — exécution** : cliquer "Dormir" dans le dialog → chaque PJ exécute `$dormirChateauDormant()` → santé, chance, morale restaurés, stress→XP | ACTOR_PC, GM_ONLY | SMOKE | DTH |
| TC-13-003 | **Château Dormant — récupération rêve** : `actor.$jetRecuperationReve()` → seuil de rêve recalculé | ACTOR_PC | FUNCTIONAL | DTH |
| TC-13-004 | **Stress→XP** : `actor.distribuerStress()` → stress converti en XP, log créé dans l'historique | ACTOR_PC | FUNCTIONAL | DTH |
| TC-13-005 | **Distribution Stress GM** : `/stress` → `DialogStress` → sélectionner des PJs → stress distribué | ACTOR_PC, GM_ONLY | FUNCTIONAL | DTH |
| TC-13-006 | **Nouveau Repos** : `DialogNouveauRepos` → sélection d'heures → Château Dormant intégré | ACTOR_PC | FUNCTIONAL | DTH |
| TC-13-007 | **Nouveau Repos CD** : `DialogNouveauReposCD` → repos avec intégration complète Château Dormant | ACTOR_PC | FUNCTIONAL | DTH |
| TC-13-008 | **Prepare Château Dormant** : clic droit "Refaire le monde" → `prepareChateauDormant()` → santé, chance, morale remis à zéro | ACTOR_PC | FUNCTIONAL | DTH |

---

## TC-14 — Voyage

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-14-001 | **Dialogue Voyage** : `/voyage` → `DialogFatigueVoyage` s'ouvre avec `dialog-fatigue-voyage.hbs` | ACTOR_PC, GM_ONLY | SMOKE | DTH |
| TC-14-002 | **Fatigue selon terrain** : sélectionner terrain "Difficile" → fatigue calculée selon `TABLEAU_FATIGUE_MARCHE` | ACTOR_PC, GM_ONLY | FUNCTIONAL | DTH |
| TC-14-003 | **Compétence survie** : `DialogFatigueVoyage` affiche les compétences de survie pour chaque PJ (Extérieur, Forêt, Montagne, etc.) | ACTOR_PC, GM_ONLY | FUNCTIONAL | DTH |
| TC-14-004 | **Application fatigue** : cliquer "Appliquer" → fatigue ajoutée aux PJs sélectionnés | ACTOR_PC, GM_ONLY | FUNCTIONAL | DTH |

---

## TC-15 — TMR (Terres Médianes du Rêve)

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-15-001 | **Carte TMR** : `RdDTMRDialog` → grille A1-P12 affichée, PixiJS rendu | GM_ONLY | SMOKE | MAN |
| TC-15-002 | **Génération rencontre TMR** : `/tmrr` → rencontre aléatoire tirée depuis le compendium rencontres | COMPENDIUM, GM_ONLY | FUNCTIONAL | DTH |
| TC-15-003 | **Recherche TMR** : `/tmr` → chercher une case → coordonnées affichées | GM_ONLY | FUNCTIONAL | DTH |
| TC-15-004 | **TMR Aléatoire** : `/tmra` → case aléatoire tirée, coordonnées affichées | GM_ONLY | FUNCTIONAL | DTH |
| TC-15-005 | **Effet Draconique** : `EffetsDraconiques` → déclencher un effet → statut appliqué aux PJs | ACTOR_PC, GM_ONLY | FUNCTIONAL | DTH |
| TC-15-006 | **Coordonnées TMR acteur** : modifier `actor.system.coordTMR` → `updateCoordTMR()` → carte centrée | ACTOR_PC | FUNCTIONAL | DTH |
| TC-15-007 | **Réinsertion aléatoire** : `actor.reinsertionAleatoire()` → nouvelle position TMR aléatoire | ACTOR_PC | EDGE | DTH |

---

## TC-16 — Commandes Chat

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-16-001 | `/aide` ou `/help` → boîte d'aide DialogV2 avec la liste des commandes | — | SMOKE | DTH |
| TC-16-002 | `/liste comp` → liste des compétences dans le chat | COMPENDIUM | SMOKE | DTH |
| TC-16-003 | `/table queue` → tirage aléatoire Queue de Dragon | COMPENDIUM | FUNCTIONAL | DTH |
| TC-16-004 | `/table ombre` → tirage Ombre de Thanatos | COMPENDIUM | FUNCTIONAL | DTH |
| TC-16-005 | `/table tete` → tirage Tête de Dragon | COMPENDIUM | FUNCTIONAL | DTH |
| TC-16-006 | `/table souffle` → tirage Souffle de Dragon | COMPENDIUM | FUNCTIONAL | DTH |
| TC-16-007 | `/table tarot` → tirage Tarot Draconique | COMPENDIUM | FUNCTIONAL | DTH |
| TC-16-008 | `/table ideefixe` → tirage Idée Fixe | COMPENDIUM | FUNCTIONAL | DTH |
| TC-16-009 | `/table desir` → tirage Désir Lancinant | COMPENDIUM | FUNCTIONAL | DTH |
| TC-16-010 | `/table rencontre` → tirage Rencontre TMR | COMPENDIUM | FUNCTIONAL | DTH |
| TC-16-011 | `/tirer comp` → tirage direct dans le chat | COMPENDIUM | FUNCTIONAL | DTH |
| TC-16-012 | `/tirer queue` → idem Queue | COMPENDIUM | FUNCTIONAL | DTH |
| TC-16-013 | `/tirer tarot` → idem Tarot | COMPENDIUM | FUNCTIONAL | DTH |
| TC-16-014 | `/tirage` → `FenetreRechercheTirage` s'ouvre | COMPENDIUM | SMOKE | DTH |
| TC-16-015 | `/voyage` → `DialogFatigueVoyage` s'ouvre | ACTOR_PC | SMOKE | DTH |
| TC-16-016 | `/sommeil` → `DialogChateauDormant` s'ouvre | ACTOR_PC | SMOKE | DTH |
| TC-16-017 | `/meteo` → météo générée dans le chat (vent, mer, nuages, pluie) | — | FUNCTIONAL | DTH |
| TC-16-018 | `/nom` → nom aléatoire généré via `RdDNameGen` | — | FUNCTIONAL | DTH |
| TC-16-019 | `/xp comp {nom}` → coût XP pour monter la compétence | ACTOR_PC | FUNCTIONAL | DTH |
| TC-16-020 | `/xp carac {nom}` → coût XP pour monter la carac | ACTOR_PC | FUNCTIONAL | DTH |
| TC-16-021 | `/rdd {carac} {diff}` → jet de résolution avec valeur et difficulté | — | FUNCTIONAL | DTH |
| TC-16-022 | `/jet @target {carac} {diff}` → demande de jet envoyée à un joueur | ACTOR_PC | FUNCTIONAL | DTH |
| TC-16-023 | `/ddr` → lancer un dé draconique | — | FUNCTIONAL | DTH |
| TC-16-024 | `/payer {montant}` → demande de paiement envoyée | ACTOR_PC | FUNCTIONAL | DTH |
| TC-16-025 | `/astro` → heures de chance/malchance pour le personnage | ACTOR_PC | FUNCTIONAL | DTH |
| TC-16-026 | `/signe +` → création de signes draconiques pour les personnages | ACTOR_PC | FUNCTIONAL | DTH |
| TC-16-027 | `/signe -` → suppression des signes éphémères | ACTOR_PC | FUNCTIONAL | DTH |
| TC-16-028 | `/stress` → `DialogStress` s'ouvre | ACTOR_PC, GM_ONLY | SMOKE | DTH |
| TC-16-029 | `/chrono` → `DialogChronologie` s'ouvre | — | SMOKE | DTH |

---

## TC-17 — Token HUD

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-17-001 | **HUD s'ouvre** : clic sur un token → Token HUD affiché, hook `renderTokenHUD` déclenché | ACTOR_PC, SCENE | SMOKE | DTH |
| TC-17-002 | **Bouton Combat** : HUD → bouton "Combat" présent (si combat actif) → clic → ajoute au combat | ACTOR_PC, SCENE, combat actif | SMOKE | DTH |
| TC-17-003 | **HUD Attaques** : HUD → extension `addExtensionHudAttaques` → boutons par arme visibles • clic → jet d'attaque | ACTOR_PC + ARME, SCENE | FUNCTIONAL | DTH |
| TC-17-004 | **HUD Initiative** : HUD → boutons +/- initiative → `addExtensionHudInit` → valeur modifiée | ACTOR_PC, SCENE, combat actif | FUNCTIONAL | DTH |
| TC-17-005 | **HUD Soins** : HUD → `addExtensionHudSoins` → sélectionner blessure → soin appliqué | ACTOR_PC + BLESSURE, SCENE | FUNCTIONAL | DTH |
| TC-17-006 | **HUD token non-combat** : cliquer un token pas dans le combat → pas d'erreur (`if (!combatant) return`) | ACTOR_NPC, SCENE, combat actif | REGRESSION | DTH |
| TC-17-007 | **HUD sans token canvas** : `app.actor` fallback utilisé si token introuvable | ACTOR_PC pas sur scène | EDGE | DTH |

---

## TC-18 — Dialogues

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-18-001 | **Choix XP Carac** : ouvrir `DialogChoixXpCarac` → dialogue rendu sans erreur | ACTOR_PC | FUNCTIONAL | DTH |
| TC-18-002 | **Création Signe Draconique** : `DialogCreateSigneDraconique` → formulaire → signe créé | ACTOR_PC, GM_ONLY | FUNCTIONAL | DTH |
| TC-18-003 | **Fabriquer Potion** : `DialogFabriquerPotion` → sélection recette → potion créée si ingrédients OK | ACTOR_PC + INGREDIENTS | FUNCTIONAL | DTH |
| TC-18-004 | **Gérer Deniers** : `dialog-gerer-deniers.js` → interface de gestion de monnaie | ACTOR_PC | FUNCTIONAL | DTH |
| TC-18-005 | **Gérer Herbes** : idem pour herbes | ACTOR_PC + HERBES | FUNCTIONAL | DTH |
| TC-18-006 | **Consommer Item** : `DialogConsommer` → item consommé, effet appliqué | ACTOR_PC + POTION/NOURRITURE | FUNCTIONAL | DTH |
| TC-18-007 | **Lancer Recette** : `DialogLancerRecette` → jet Alchimie/Cuisine → résultat | ACTOR_PC + RECETTE | FUNCTIONAL | DTH |
| TC-18-008 | **Split Item** : `DialogSplitItem` → diviser un stack d'items → deux stacks | ACTOR_PC + ITEM stackable | FUNCTIONAL | DTH |
| TC-18-009 | **Validation Encaissement** : `dialog-validation-encaissement.js` → GM valide/invalide l'encaissement | ACTOR_PC, combat | FUNCTIONAL | DTH |
| TC-18-010 | **Enchantement** : `DialogEnchanter` → enchanter un item | ACTOR_PC | FUNCTIONAL | DTH |
| TC-18-011 | **Achat Item** : `DialogItemAchat` → acheter depuis un commerce | ACTOR_PC + ACTOR_COMMERCE | FUNCTIONAL | DTH |
| TC-18-012 | **Vente Item** : `DialogItemVente` → vendre au commerce | ACTOR_PC + ACTOR_COMMERCE | FUNCTIONAL | DTH |
| TC-18-013 | **Select (générique)** : `DialogSelect` → liste d'options, sélection → callback | — | FUNCTIONAL | DTH |
| TC-18-014 | **Dialogues V2 — window positioning** : chaque dialog peut être redimensionné et déplacé (pas de `height:fit-content`) | — | REGRESSION | DTH |
| TC-18-015 | **Dialogues V2 — boutons** : chaque dialog DialogV2 a au moins 1 bouton ("Fermer" minimum) | — | REGRESSION | DTH |

---

## TC-19 — Tirage (FenetreRechercheTirage)

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-19-001 | **Ouverture** : `/tirage` → `FenetreRechercheTirage` rendue avec `HandlebarsApplicationMixin` | COMPENDIUM | SMOKE | DTH |
| TC-19-002 | **Filtre par type** : sélectionner "Arme" → liste filtrée aux armes uniquement | COMPENDIUM | FUNCTIONAL | DTH |
| TC-19-003 | **Filtre par rareté** : sélectionner "Rare" → rareté filtrée | COMPENDIUM | FUNCTIONAL | DTH |
| TC-19-004 | **Filtre par milieu** : sélectionner "Forêt" → milieu filtré | COMPENDIUM | FUNCTIONAL | DTH |
| TC-19-005 | **Recherche texte** : taper "épée" → résultats filtrés | COMPENDIUM | FUNCTIONAL | DTH |
| TC-19-006 | **Tirage aléatoire** : cliquer "Tirer" → résultat aléatoire affiché dans le chat | COMPENDIUM | FUNCTIONAL | DTH |
| TC-19-007 | **Configuration sources** : cliquer "Config" → `FenetreRechercheConfiguration` → sélectionner/déselectionner des compendiums sources | COMPENDIUM | FUNCTIONAL | DTH |

---

## TC-20 — Génération Aléatoire de Personnage

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-20-001 | **Ouverture** : `AppPersonnageAleatoire` → fenêtre de génération rendue | GM_ONLY | SMOKE | DTH |
| TC-20-002 | **Génération complète** : cliquer "Générer" → personnage créé avec sexe, main, cheveux, yeux, taille, poids, heure de naissance, nom | GM_ONLY | FUNCTIONAL | DTH |
| TC-20-003 | **Génération nom** : `RdDNameGen.generate()` → nom cohérent (prénom + nom) | — | FUNCTIONAL | DTH |
| TC-20-004 | **Heure draconique de naissance** : vérifier que l'heure générée est dans DEFINITION_HEURES (0-11) | — | FUNCTIONAL | DTH |

---

## TC-21 — Migrations

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-21-001 | **Migration déclenchée** : `game.settings.get(...systemMigrationVersion)` < version courante → migration run | Monde pré-migration | SMOKE | MAN |
| TC-21-002 | **Migration — compétences parade** : `_10_0_17_MigrationCompetenceCreature` → catégories mises à jour | ACTOR_CREATURE | REGRESSION | MAN |
| TC-21-003 | **Migration — blessures** : `_10_7_0_MigrationBlessures` → blessures inline → items blessure | ACTOR_PC pré-migration | REGRESSION | MAN |
| TC-21-004 | **Migration — races** : `_12_0_32_MigrationRaces` → race text → item race | ACTOR_PC pré-migration | REGRESSION | MAN |
| TC-21-005 | **Migration — rêve actuel** : `_13_0_4_FixReveActuel` → ancien champ retiré | ACTOR_PC pré-migration | REGRESSION | MAN |
| TC-21-006 | **Migration — appréciation** : `_13_0_21_AjoutAppreciation` → données d'appréciation ajoutées aux items appréciables | ITEMS pré-migration | REGRESSION | MAN |

---

## TC-22 — Compendiums

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-22-001 | **32 packs chargés** : `game.packs.filter(p => p.metadata.system === 'foundryvtt-reve-de-dragon').length === 32` | — | SMOKE | DTH |
| TC-22-002 | **Compendium Compétences** : ouvrir → 30+ entités valides | COMPENDIUM | SMOKE | DTH |
| TC-22-003 | **Compendium Sorts** : ouvrir → 50+ sorts classés par voie Oniros/Hypnos/Narcos/Thanatos | COMPENDIUM | SMOKE | DTH |
| TC-22-004 | **Compendium Équipement** : ouvrir → armes, armures, objets listés | COMPENDIUM | SMOKE | DTH |
| TC-22-005 | **Compendium Macros** : ouvrir → macros système disponibles | COMPENDIUM | SMOKE | DTH |
| TC-22-006 | **Drag compendium → acteur** : glisser un item du compendium sur une feuille → item créé sur l'acteur | COMPENDIUM, ACTOR_PC | FUNCTIONAL | DTH |
| TC-22-007 | **Drag compendium → scène** : glisser un acteur du compendium sur la scène → token créé | COMPENDIUM, SCENE | FUNCTIONAL | DTH |

---

## TC-23 — CSS / UI / Layout

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-23-001 | **Police CaslonAntique chargée** : vérifier `getComputedStyle(document.body).fontFamily` contient "CaslonAntique" | — | SMOKE | DTH |
| TC-23-002 | **CSS layer** : `@import ... layer(system)` — les styles système ont la priorité attendue (vérifier propriété spécifique avec `!important`) | — | REGRESSION | MAN |
| TC-23-003 | **Scroll item sheets** : ouvrir chaque type d'item sheet → le contenu défile verticalement sans overflow caché | ACTOR_PC + 44 items | FUNCTIONAL | DTH |
| TC-23-004 | **Dialog styles** : DialogChronologie, CalendarEditor, Stress → fond, inputs, boutons dorés conformes au thème | — | SMOKE | DTH |
| TC-23-005 | **Boutons en `type="button"`** : `app-personnage-aleatoire.hbs` → boutons ne submitent pas par erreur | — | REGRESSION | DTH |
| TC-23-006 | **Sélecteurs natifs** : aucun sélecteur `:input` dans le CSS (remplacé par `input, select, textarea`) | — | REGRESSION | MAN |

---

## TC-24 — Export

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-24-001 | **Export PDF** : cliquer "Export PDF" sur la feuille → fichier PDF généré et téléchargé | ACTOR_PC | FUNCTIONAL | MAN |
| TC-24-002 | **Export Scriptarium** : `ExportScriptarium` → CSV généré avec les données du personnage | ACTOR_PC | FUNCTIONAL | MAN |

---

## TC-25 — Hotbar

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-25-001 | **Drop arme hotbar** : glisser une arme du sheet vers la hotbar → macro créée avec options (unemain, deuxmains, lancer, tir) | ACTOR_PC + ARME | SMOKE | DTH |
| TC-25-002 | **Drop compétence hotbar** : glisser une compétence → macro créée, bouton cliquable → jet | ACTOR_PC + COMPETENCE | FUNCTIONAL | DTH |
| TC-25-003 | **Drop compétence créature hotbar** : idem pour `competencecreature` | ACTOR_NPC + COMPETENCE_CREATURE | FUNCTIONAL | DTH |

---

## TC-26 — Possession V2

Objectif : valider le système de possession (entités, jets, résolution).

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-26-001 | **Possession — attaque** : `RdDPossession.attack()` → jet possession lancé, message chat avec boutons | ACTOR_ENTITE, ACTOR_PC | FUNCTIONAL | DTH |
| TC-26-002 | **Possession — défense** : cliquer "Défense Possession" dans le chat → `dialog-roll-defense-possession.hbs` → résultat | ACTOR_PC | FUNCTIONAL | DTH |
| TC-26-003 | **Possession — conjuration** : `actor.jetConjuration()` → résolution basée sur 2 points de possession | ACTOR_PC + entité possédante | FUNCTIONAL | DTH |
| TC-26-004 | **Possession V2 — socket** : `msg_possession_v2` → message reçu par les participants, état synchronisé | ACTOR_PC + ACTOR_ENTITE | FUNCTIONAL | DTH |

---

## TC-27 — Active Effects

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-27-001 | **Création effet** : `ActiveEffect.create({name:'Test', changes:[...]})` → `RdDActiveEffect` créé | ACTOR_PC | SMOKE | DTH |
| TC-27-002 | **Application effet sur acteur** : créer un effet avec changement sur `system.sante.vie` → valeur modifiée | ACTOR_PC | FUNCTIONAL | DTH |
| TC-27-003 | **Suppression effet** : supprimer l'effet → valeur restaurée | ACTOR_PC | FUNCTIONAL | DTH |
| TC-27-004 | **Effets de statut** : `game.rdd.statusEffects` → liste des statuts système disponibles | — | FUNCTIONAL | DTH |

---

## TC-28 — Journal Sheet

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-28-001 | **Journal système s'ouvre** : double-clic sur un journal → `RdDJournalSheet` rendue | JournalEntry existante | SMOKE | DTH |
| TC-28-002 | **Enrichissement roll** : taper `[[/r 1d100]]` dans le journal → enrichi en bouton cliquable | JournalEntry | FUNCTIONAL | DTH |

---

## TC-29 — Cœur (Attachment)

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-29-001 | **Création lien cœur** : `RdDCoeur.create(actor1, actor2, niveau)` → lien créé entre deux personnages | ACTOR_PC × 2 | FUNCTIONAL | DTH |
| TC-29-002 | **Modification niveau** : changer le niveau du lien → ajustements de caracs/moral appliqués | ACTOR_PC × 2 | FUNCTIONAL | DTH |

---

## TC-30 — Appréciation

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-30-001 | **Appréciation œuvre** : `Apprecier.apprecier(actor, item, 'oeuvre')` → niveau d'appréciation enregistré | ACTOR_PC + item appréciable | FUNCTIONAL | DTH |
| TC-30-002 | **Appréciation cuisine** : idem pour `nourritureboisson` avec catégorie CUISINE | ACTOR_PC + item NOURRITURE | FUNCTIONAL | DTH |
| TC-30-003 | **Appréciation musique** : idem pour `musique` avec catégorie MUSIQUE | ACTOR_PC + item MUSIQUE | FUNCTIONAL | DTH |

---

## TC-31 — Météo

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-31-001 | **Génération météo** : `RdDMeteo.generate()` → objet météo contenant vent, mer, nuages, pluie | — | FUNCTIONAL | DTH |
| TC-31-002 | **Affichage météo** : `/meteo` → message chat formaté avec les données météo | — | SMOKE | DTH |

---

## TC-32 — Sons

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-32-001 | **Son pièces** : `RdDAudio.play('coin')` → son joué (vérifier `Howl` instance créée) | ACTOR_PC | FUNCTIONAL | MAN |

---

## TC-33 — Remote / Socket

| ID | Titre | Prérequis | Niveau | Automatisation |
|---|---|---|---|---|
| TC-33-001 | **Remote call** : `Remote.call('chatMessage', ...)` → fonction exécutée sur le client distant | 2 clients connectés | FUNCTIONAL | MAN |
| TC-33-002 | **Socket notification** : émettre un message socket → tous les clients le reçoivent (`Hooks.on('socket')[msg]`) | 2 clients connectés | FUNCTIONAL | MAN |

---

## Annexe A — Automatisation avec Chrome DevTools

### A.1 Script type pour DTC (DevTools CLI)

```bash
# Exemple : vérifier que le système est chargé
chrome-devtools_evaluate_script \
  function='() => { return { id: game.system.id, version: game.system.version, ready: game.ready }; }'
```

### A.2 Script type pour Playwright

```javascript
// Exemple : ouvrir la fiche d'un personnage
await page.goto('http://localhost:31000/game');
await page.click('.actor[data-document-id="..."]');
await page.waitForSelector('.window-app.rdd-actor-sheet');
const title = await page.textContent('.window-header .window-title');
expect(title).toContain('Test');
```

### A.3 Compteurs de tests

| Section | Cas | Automatisables | Manuel |
|---|---|---|---|
| TC-01 Infrastructure | 10 | 10 | 0 |
| TC-02 Acteur Personnage | 20 | 20 | 0 |
| TC-03 Acteur Créature | 3 | 3 | 0 |
| TC-04 Acteur Entité | 4 | 4 | 0 |
| TC-05 Acteur Véhicule | 2 | 2 | 0 |
| TC-06 Acteur Commerce | 3 | 3 | 0 |
| TC-07 Item Sheets | 19 | 18 | 1 |
| TC-08 Roll V1 | 11 | 11 | 0 |
| TC-09 Roll V2 | 5 | 5 | 0 |
| TC-10 Dés Custom | 5 | 4 | 1 |
| TC-11 Combat | 12 | 10 | 2 |
| TC-12 Calendrier | 8 | 8 | 0 |
| TC-13 Sommeil | 8 | 8 | 0 |
| TC-14 Voyage | 4 | 4 | 0 |
| TC-15 TMR | 7 | 5 | 2 |
| TC-16 Commandes Chat | 29 | 29 | 0 |
| TC-17 Token HUD | 7 | 7 | 0 |
| TC-18 Dialogues | 15 | 15 | 0 |
| TC-19 Tirage | 7 | 7 | 0 |
| TC-20 Gen Aléatoire | 4 | 4 | 0 |
| TC-21 Migrations | 6 | 0 | 6 |
| TC-22 Compendiums | 7 | 7 | 0 |
| TC-23 CSS/UI | 6 | 4 | 2 |
| TC-24 Export | 2 | 0 | 2 |
| TC-25 Hotbar | 3 | 3 | 0 |
| TC-26 Possession V2 | 4 | 4 | 0 |
| TC-27 Active Effects | 4 | 4 | 0 |
| TC-28 Journal | 2 | 2 | 0 |
| TC-29 Cœur | 2 | 2 | 0 |
| TC-30 Appréciation | 3 | 3 | 0 |
| TC-31 Météo | 2 | 2 | 0 |
| TC-32 Sons | 1 | 0 | 1 |
| TC-33 Remote / Socket | 2 | 0 | 2 |
| **Total** | **227** | **208** | **19** |

---

*Fin du plan de test — 227 cas, 208 automatisables (92%)*
