Skip to content

Commit ef0ed70

Browse files
committed
test: cover persisted store migration
1 parent 99c401f commit ef0ed70

1 file changed

Lines changed: 121 additions & 0 deletions

File tree

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
test('v2 persisted games migrate to the current store shape', async ({ page }) => {
4+
const consoleErrors: string[] = [];
5+
page.on('console', (msg) => {
6+
if (msg.type() === 'error') consoleErrors.push(msg.text());
7+
});
8+
9+
await page.addInitScript(() => {
10+
localStorage.setItem(
11+
'loupgarous-game',
12+
JSON.stringify({
13+
state: {
14+
phase: 'day',
15+
round: 1,
16+
playerNames: [],
17+
roleIds: ['werewolf', 'scapegoat', 'villager'],
18+
discussionTime: 5,
19+
optionalRules: { elder: true },
20+
players: [
21+
{
22+
id: 'p0',
23+
name: '',
24+
seatNumber: 1,
25+
roleId: 'werewolf',
26+
isAlive: true,
27+
isMayor: false,
28+
isLover: false,
29+
extraVotes: 0,
30+
usedAbilities: [],
31+
},
32+
{
33+
id: 'p1',
34+
name: '',
35+
seatNumber: 2,
36+
roleId: 'scapegoat',
37+
isAlive: true,
38+
isMayor: false,
39+
isLover: false,
40+
extraVotes: 0,
41+
usedAbilities: [],
42+
},
43+
{
44+
id: 'p2',
45+
name: '',
46+
seatNumber: 3,
47+
roleId: 'villager',
48+
isAlive: true,
49+
isMayor: false,
50+
isLover: false,
51+
extraVotes: 0,
52+
usedAbilities: [],
53+
},
54+
],
55+
nightSteps: [],
56+
nightStepStates: [],
57+
currentNightStepIndex: 0,
58+
eliminatedThisNight: [],
59+
discussionTimeSeconds: 5,
60+
timerRunning: true,
61+
timerRemaining: 999,
62+
loversIds: null,
63+
mayorId: null,
64+
log: [],
65+
usedGameAbilities: [],
66+
foxPowerActive: true,
67+
protectorHistory: [],
68+
wildChildModelId: null,
69+
wildChildTransformed: false,
70+
wolfDogChoice: null,
71+
enchantedPlayerIds: [],
72+
infectedPlayerIds: [],
73+
angelWon: false,
74+
firstDayExecutionDone: false,
75+
language: 'en',
76+
protectedPlayerId: null,
77+
lastProtectedPlayerId: null,
78+
rolePowerOverrides: {},
79+
},
80+
version: 2,
81+
})
82+
);
83+
});
84+
85+
await page.goto('/');
86+
87+
await expect(page.getByTestId('day-phase')).toBeVisible();
88+
await expect(page.getByTestId('recent-eliminations')).toHaveCount(0);
89+
await expect(page.getByTestId('timer-duration')).toHaveText('00:30');
90+
await expect(page.getByTestId('timer-display')).toHaveText('00:30');
91+
await expect(page.getByTestId('player-card-p1')).toContainText('#2 Villager');
92+
93+
const persisted = await page.evaluate(() => {
94+
const raw = localStorage.getItem('loupgarous-game');
95+
if (!raw) throw new Error('missing persisted state');
96+
return JSON.parse(raw) as {
97+
state: {
98+
pendingDayEliminations?: unknown;
99+
optionalRules?: unknown;
100+
discussionTime: number;
101+
discussionTimeSeconds: number;
102+
timerRemaining: number;
103+
timerRunning: boolean;
104+
roleIds: string[];
105+
players: { id: string; roleId: string }[];
106+
};
107+
version: number;
108+
};
109+
});
110+
111+
expect(persisted.version).toBe(3);
112+
expect(persisted.state.pendingDayEliminations).toEqual([]);
113+
expect(persisted.state.optionalRules).toBeUndefined();
114+
expect(persisted.state.discussionTime).toBe(30);
115+
expect(persisted.state.discussionTimeSeconds).toBe(30);
116+
expect(persisted.state.timerRemaining).toBe(30);
117+
expect(typeof persisted.state.timerRunning).toBe('boolean');
118+
expect(persisted.state.roleIds).toEqual(['werewolf', 'villager', 'villager']);
119+
expect(persisted.state.players.find((player) => player.id === 'p1')?.roleId).toBe('villager');
120+
expect(consoleErrors, 'console errors detected').toEqual([]);
121+
});

0 commit comments

Comments
 (0)