Files
regnum/client/test/unit/game.store.test.js
T
Kevin L'Hereec 11cba0467b feat: écran de fin de partie + tests unitaires client et E2E Playwright
- Fix: UIScene n'était jamais lancée (active: false, jamais scene.launch)
  donc l'event 'game-over' du serveur n'était jamais affiché — la partie
  semblait ne pas avoir de fin. Remplacé par un panneau Vue dans GameView
  (vainqueur, classement trié, bouton Quitter via vue-router). UIScene.js
  supprimée (code mort).
- Extraction de client/src/utils/hudUtils.js (constantes ATTRS/couleurs et
  gaugePercent) depuis GameView.vue pour les rendre testables isolément.
- Tests unitaires client (Vitest) : store Pinia (game.js) et hudUtils
  (24 tests, client/test/unit/).
- Tests d'intégration E2E (Playwright, e2e/) avec de vrais clients
  Socket.io et rendu Phaser réel dans Chromium :
  * game-flow.spec.js : lobby → démarrage → main de 4 cartes → résolution
  * item-shop.spec.js : boutique, bouton désactivé si jauge insuffisante,
    achat retire l'objet pour tous + effet appliqué + affiché sur la table
  * game-over.spec.js : partie complète (12 tours) → panneau de fin
  webServer démarre automatiquement client+serveur ; ajout d'une route
  GET /health côté Express pour permettre à Playwright de détecter un
  serveur déjà démarré.
- README : documentation des 3 niveaux de tests (unitaires serveur,
  unitaires client, intégration E2E) et de la nouvelle arborescence.
2026-08-21 15:27:44 +02:00

163 lines
5.5 KiB
JavaScript

import { describe, it, expect, beforeEach } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useGameStore } from '../../src/stores/game'
describe('stores/game (Pinia)', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
it('a un état initial vide/par défaut', () => {
const store = useGameStore()
expect(store.playerName).toBe('')
expect(store.players).toEqual([])
expect(store.currentTurn).toBe(0)
expect(store.maxTurns).toBe(12)
expect(store.phase).toBe('idle')
expect(store.hand).toEqual([])
expect(store.myTeamIndex).toBe(0)
expect(store.selectedCard).toBeNull()
expect(store.myItems).toEqual([])
expect(store.pendingBuyItemId).toBeNull()
expect(store.availableItems).toEqual([])
expect(store.firstPlayerName).toBeNull()
expect(store.gameOverResults).toBeNull()
})
it('setPlayer met à jour playerName', () => {
const store = useGameStore()
store.setPlayer('Alice')
expect(store.playerName).toBe('Alice')
})
describe('updateState', () => {
it('met à jour tous les champs de base depuis un game-state serveur', () => {
const store = useGameStore()
store.updateState({
players: [{ name: 'Alice', score: 5 }],
currentTurn: 3,
maxTurns: 12,
phase: 'selecting',
hand: [{ id: 'queen' }],
myTeamIndex: 1
})
expect(store.players).toEqual([{ name: 'Alice', score: 5 }])
expect(store.currentTurn).toBe(3)
expect(store.maxTurns).toBe(12)
expect(store.phase).toBe('selecting')
expect(store.hand).toEqual([{ id: 'queen' }])
expect(store.myTeamIndex).toBe(1)
})
it('retombe sur les valeurs par défaut si les champs sont absents (sauf hand/items qui restent inchangés)', () => {
const store = useGameStore()
store.updateState({})
expect(store.players).toEqual([])
expect(store.currentTurn).toBe(0)
expect(store.maxTurns).toBe(12)
expect(store.phase).toBe('idle')
expect(store.myTeamIndex).toBe(0)
})
it('ne touche PAS à hand si state.hand est undefined (évite d\'effacer la main en cours)', () => {
const store = useGameStore()
store.updateState({ hand: [{ id: 'prince' }] })
store.updateState({ phase: 'waiting' }) // pas de champ hand cette fois
expect(store.hand).toEqual([{ id: 'prince' }])
})
it('met à jour les champs liés aux objets uniquement s\'ils sont fournis', () => {
const store = useGameStore()
store.updateState({
myItems: ['trebuchet'],
pendingBuyItemId: 'plow',
availableItems: ['medkit', 'royal_seal'],
firstPlayerName: 'Bob'
})
expect(store.myItems).toEqual(['trebuchet'])
expect(store.pendingBuyItemId).toBe('plow')
expect(store.availableItems).toEqual(['medkit', 'royal_seal'])
expect(store.firstPlayerName).toBe('Bob')
// Un second appel sans ces champs ne doit pas les réinitialiser
store.updateState({ phase: 'resolve' })
expect(store.myItems).toEqual(['trebuchet'])
expect(store.pendingBuyItemId).toBe('plow')
})
it('accepte explicitement pendingBuyItemId=null (achat annulé/résolu) sans le confondre avec "absent"', () => {
const store = useGameStore()
store.updateState({ pendingBuyItemId: 'plow' })
store.updateState({ pendingBuyItemId: null })
expect(store.pendingBuyItemId).toBeNull()
})
})
describe('selectCard / clearSelection', () => {
it('selectCard définit la carte sélectionnée', () => {
const store = useGameStore()
const card = { id: 'knight', war: 5 }
store.selectCard(card)
expect(store.selectedCard).toEqual(card)
})
it('clearSelection remet selectedCard à null', () => {
const store = useGameStore()
store.selectCard({ id: 'knight' })
store.clearSelection()
expect(store.selectedCard).toBeNull()
})
})
describe('setGameOver', () => {
it('définit gameOverResults avec les résultats fournis', () => {
const store = useGameStore()
const results = [{ name: 'Alice', score: 42 }, { name: 'Bob', score: 30 }]
store.setGameOver(results)
expect(store.gameOverResults).toEqual(results)
})
})
describe('reset', () => {
it('remet tout l\'état à ses valeurs par défaut', () => {
const store = useGameStore()
store.setPlayer('Alice')
store.updateState({
players: [{ name: 'Alice' }],
currentTurn: 5,
phase: 'resolve',
hand: [{ id: 'queen' }],
myTeamIndex: 2,
myItems: ['trebuchet'],
pendingBuyItemId: 'plow',
availableItems: ['medkit'],
firstPlayerName: 'Bob'
})
store.selectCard({ id: 'queen' })
store.setGameOver([{ name: 'Alice', score: 10 }])
store.reset()
expect(store.players).toEqual([])
expect(store.currentTurn).toBe(0)
expect(store.maxTurns).toBe(12)
expect(store.phase).toBe('idle')
expect(store.hand).toEqual([])
expect(store.myTeamIndex).toBe(0)
expect(store.selectedCard).toBeNull()
expect(store.myItems).toEqual([])
expect(store.pendingBuyItemId).toBeNull()
expect(store.availableItems).toEqual([])
expect(store.firstPlayerName).toBeNull()
expect(store.gameOverResults).toBeNull()
// playerName n'est PAS réinitialisé par reset() (comportement existant :
// le nom du joueur est conservé pour rejouer une partie sans le re-saisir)
expect(store.playerName).toBe('Alice')
})
})
})