- 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.
62 lines
2.3 KiB
JavaScript
62 lines
2.3 KiB
JavaScript
import { test, expect } from '@playwright/test'
|
||
import { installPhaserDebugHook, createRoom, joinRoom, startGame, playFullTurn } from './helpers.js'
|
||
|
||
/**
|
||
* Test d'intégration E2E : partie complète jusqu'au bout (12 tours), affichage
|
||
* du panneau de fin de partie (vainqueur + classement) et bouton Quitter.
|
||
*
|
||
* Ce test couvre la régression corrigée : le serveur émettait bien l'event
|
||
* 'game-over' après le 12e tour, mais rien côté client ne l'écoutait ni ne
|
||
* l'affichait — la partie "n'avait pas de fin" du point de vue du joueur.
|
||
*/
|
||
test.describe('Fin de partie', () => {
|
||
test('après 12 tours, le panneau de fin affiche un vainqueur, un classement, et un bouton Quitter fonctionnel', async ({ browser }) => {
|
||
test.setTimeout(120_000) // 12 tours × ~4.5s de résolution serveur + marge
|
||
|
||
const ctx1 = await browser.newContext()
|
||
const ctx2 = await browser.newContext()
|
||
const p1 = await ctx1.newPage()
|
||
const p2 = await ctx2.newPage()
|
||
const errors = []
|
||
p1.on('pageerror', e => errors.push(e.message))
|
||
p2.on('pageerror', e => errors.push(e.message))
|
||
await installPhaserDebugHook(p1)
|
||
await installPhaserDebugHook(p2)
|
||
|
||
const roomId = await createRoom(p1, 'Alice')
|
||
await joinRoom(p2, 'Bob', roomId)
|
||
await startGame(p1)
|
||
await p1.waitForTimeout(2000)
|
||
|
||
// Jouer les 12 tours. playCard (via playFullTurn) gère déjà le cas d'une
|
||
// main vide (retourne sans rien faire) pour les tours de fin de partie où
|
||
// le nombre de cartes en main diminue.
|
||
for (let t = 0; t < 12; t++) {
|
||
await playFullTurn([p1, p2])
|
||
}
|
||
|
||
// Laisser le temps au serveur d'émettre 'game-over' après le dernier tour
|
||
await p1.waitForTimeout(1000)
|
||
|
||
await expect(p1.locator('.game-over-overlay')).toBeVisible({ timeout: 10_000 })
|
||
await expect(p2.locator('.game-over-overlay')).toBeVisible({ timeout: 10_000 })
|
||
|
||
// Un vainqueur est annoncé
|
||
const winnerText = await p1.locator('.game-over-winner').textContent()
|
||
expect(winnerText).toMatch(/Alice|Bob/)
|
||
|
||
// Le classement liste bien les 2 joueurs
|
||
const rankingCount = await p1.locator('.ranking-item').count()
|
||
expect(rankingCount).toBe(2)
|
||
|
||
// Le bouton Quitter ramène à l'accueil
|
||
await p1.click('.quit-btn')
|
||
await expect(p1).toHaveURL('/')
|
||
|
||
expect(errors).toEqual([])
|
||
|
||
await ctx1.close()
|
||
await ctx2.close()
|
||
})
|
||
})
|