Dev #11

Merged
w-vandal merged 23 commits from dev into main 2026-09-04 19:13:42 +00:00
Showing only changes of commit 5e17e42dfa - Show all commits
@@ -0,0 +1,108 @@
// Bout en bout : une règle de collision "quete" doit réellement faire
// apparaître/avancer/disparaître la boîte de dialogue posée sur la scène
// — pas seulement chaque brique testée isolément (voir
// collision-rules-controller.test.js et dialogue-box-controller.test.js).
// Reproduit le scénario signalé : un objet "Mr. Pinguin" avec une règle
// "à la collision -> déclencher la quête « test »", une quête au statut
// "nouvelle" avec 2 répliques, un widget "💬 Boîte de dialogue" posé sur
// la même scène.
const test = require('node:test');
const assert = require('node:assert/strict');
global.window = global.window || {};
global.gameData = {};
global.screensData = [];
global.heldKeys = new Set();
const actionsMod = require('../actions.js');
Object.assign(global, actionsMod);
require('../personnage-controller.js');
const { forgeDialogueBoxAdvance } = require('../dialogue-box-controller.js'); // pas mocké : la vraie logique métier
const { forgeCollisionRuleTick } = require('../collision-rules-controller.js');
function fakeEl(style) {
const classes = new Set();
const children = [];
return {
style: style,
classList: { add: c => classes.add(c), remove: c => classes.delete(c), contains: c => classes.has(c) },
children,
appendChild(child) { children.push(child); },
querySelector(sel) {
if (sel === '.dialogueBoxWidget') return children.find(c => c._isDialogueBoxWidget);
if (sel === '[data-dialogue-role="header"]') return this._header;
if (sel === '[data-dialogue-role="body"]') return this._body;
return undefined;
},
getAttribute(attr) { return attr === 'data-object-id' ? this._objectId : null; },
};
}
test('collision "quete" -> boîte de dialogue affiche la 1ère réplique, "Suivant" avance, se masque à la fin', () => {
const player = { id: 1, kind: 'personnage', personnage_role: 'joueur' };
const mrPinguin = {
id: 2, kind: 'personnage',
collision_rules: [{ trigger: 'collision', action: { type: 'quete', quete_id: 99 } }],
};
const box = { id: 3, kind: 'dialogue_box' };
const playerEl = fakeEl({ left: '0px', top: '0px', width: '20px', height: '20px' });
const pinguinEl = fakeEl({ left: '5px', top: '5px', width: '20px', height: '20px' }); // chevauche playerEl
const boxWidget = fakeEl({});
boxWidget._isDialogueBoxWidget = true;
boxWidget._objectId = '3';
boxWidget._header = { textContent: '' };
boxWidget._body = { textContent: '' };
global.window.currentScreenId = 1;
global.gameData = {
personnage_animations: {},
quests: [{
id: 99, status: 'nouvelle',
dialogues: {
nouvelle: [
{ speaker: 'Mr. Pinguin', text: 'Bonjour !' },
{ speaker: 'Charlie', text: 'Salut !' },
],
en_cours: [], terminee: [],
},
}],
};
const previousDoc = global.document;
global.document = {
querySelector(sel) {
// forgeDialogueBoxWidgetOnCurrentScreen() cherche
// '.playScreen[data-screen-id="1"] .dialogueBoxWidget' — à vérifier
// AVANT les sélecteurs [data-object-id="..."] ci-dessous (le "1" du
// numéro de scène apparaît aussi comme sous-chaîne de cette
// requête, source d'ambiguïté sinon).
if (sel.indexOf('.dialogueBoxWidget') !== -1 && sel.indexOf('data-object-id') === -1) return boxWidget;
if (sel.indexOf('data-object-id="1"') !== -1) return playerEl;
if (sel.indexOf('data-object-id="2"') !== -1) return pinguinEl;
// forgeDialogueBoxWidgetById('3') — appelé par le clic "Suivant"
if (sel.indexOf('data-object-id="3"') !== -1) return boxWidget;
return null;
},
};
try {
const screenData = { elements: [player, mrPinguin, box] };
forgeCollisionRuleTick(screenData); // entrée en collision -> déclenche la quête
assert.equal(boxWidget._header.textContent, 'Mr. Pinguin');
assert.equal(boxWidget._body.textContent, 'Bonjour !');
assert.equal(boxWidget.classList.contains('is-active'), true);
forgeCollisionRuleTick(screenData); // toujours en collision -> ne redéclenche pas la quête
assert.equal(boxWidget._header.textContent, 'Mr. Pinguin'); // pas repartie de la 1ère réplique
forgeDialogueBoxAdvance('3'); // clic "Suivant" (bouton du widget)
assert.equal(boxWidget._header.textContent, 'Charlie');
assert.equal(boxWidget._body.textContent, 'Salut !');
assert.equal(boxWidget.classList.contains('is-active'), true);
forgeDialogueBoxAdvance('3'); // dernière réplique consommée -> la modale disparaît
assert.equal(boxWidget.classList.contains('is-active'), false);
} finally { global.document = previousDoc; }
});