- Nouveaux personnages illustrés (12 PNG remplacés dans client/public/cards) - 4 objets achetables (Trébuchet, Charrue, Trousse du Médecin, Sceau Royal) avec effets permanents (double_gain, guaranteed_gain, copy_best_in_game), stock unique par partie, priorité d'achat tournante entre joueurs - Boutique en colonne à gauche du plateau : icônes compactes, carte détaillée agrandie au survol (taille découplée du displayScale du jeton), bouton ACHETER actif/grisé selon la jauge du joueur, retrait immédiat de la colonne une fois l'objet acheté (les autres remontent pour combler) - Objets achetés affichés "posés sur la table" : à côté de la main pour soi, sous le slot de jeu pour les adversaires - Icône du premier joueur (priorité d'achat) dans le HUD Vue - Refonte des cartes personnage (CardObject) : portrait plein cadre épuré, valeurs d'attribut discrètes aux 4 coins - Fix removePlayer : nettoyage de pendingBuys/pendingPlays et recalage de firstPlayerIndex à la déconnexion d'un joueur - 77 tests unitaires serveur (node:test) : cards, items, Room, RoomManager - README mis à jour avec les règles complètes du jeu - .gitignore : exclusion de .idea/ et .serena/ (artefacts d'outils locaux)
61 lines
2.0 KiB
JavaScript
61 lines
2.0 KiB
JavaScript
const { test, describe } = require('node:test')
|
|
const assert = require('node:assert/strict')
|
|
|
|
const { ITEMS, getItemById } = require('../../src/game/items')
|
|
|
|
describe('items.js', () => {
|
|
test('expose exactement 4 objets', () => {
|
|
assert.equal(ITEMS.length, 4)
|
|
})
|
|
|
|
test('chaque objet a un id unique', () => {
|
|
const ids = ITEMS.map(i => i.id)
|
|
assert.equal(new Set(ids).size, ids.length)
|
|
})
|
|
|
|
test('chaque objet est lié à un attribut valide et a un coût positif', () => {
|
|
const validAttrs = ['food', 'war', 'health', 'diplo']
|
|
for (const item of ITEMS) {
|
|
assert.ok(validAttrs.includes(item.attr), `${item.id}.attr doit être un attribut valide`)
|
|
assert.ok(item.cost > 0, `${item.id}.cost doit être positif`)
|
|
}
|
|
})
|
|
|
|
test('chaque objet a un effect reconnu par Room._applyItemEffects', () => {
|
|
const knownEffects = ['double_gain', 'guaranteed_gain', 'copy_best_in_game']
|
|
for (const item of ITEMS) {
|
|
assert.ok(knownEffects.includes(item.effect), `${item.id}.effect '${item.effect}' inconnu`)
|
|
}
|
|
})
|
|
|
|
test('guaranteed_gain (Trousse du Médecin) définit bien effectValue', () => {
|
|
const medkit = getItemById('medkit')
|
|
assert.ok(medkit)
|
|
assert.equal(medkit.effect, 'guaranteed_gain')
|
|
assert.equal(typeof medkit.effectValue, 'number')
|
|
})
|
|
|
|
test('aucun attribut n\'est couvert par 2 objets différents (pas de conflit de cumul)', () => {
|
|
const attrs = ITEMS.map(i => i.attr)
|
|
assert.equal(new Set(attrs).size, attrs.length)
|
|
})
|
|
|
|
describe('getItemById', () => {
|
|
test('retourne l\'objet correspondant à un id existant', () => {
|
|
const trebuchet = getItemById('trebuchet')
|
|
assert.ok(trebuchet)
|
|
assert.equal(trebuchet.name, 'Trébuchet')
|
|
assert.equal(trebuchet.attr, 'war')
|
|
})
|
|
|
|
test('retourne null pour un id inconnu', () => {
|
|
assert.equal(getItemById('does-not-exist'), null)
|
|
})
|
|
|
|
test('retourne null pour undefined/null', () => {
|
|
assert.equal(getItemById(undefined), null)
|
|
assert.equal(getItemById(null), null)
|
|
})
|
|
})
|
|
})
|