test(issue-301): align host gating specs with canonical phases
All checks were successful
CI / test-and-quality (pull_request) Successful in 3m3s
CI / test-and-quality (push) Successful in 3m5s

This commit is contained in:
2026-03-16 12:50:33 +00:00
parent 3acaf3e370
commit f0142f33b6
2 changed files with 16 additions and 5 deletions

View File

@@ -183,7 +183,11 @@ describe('HostShellComponent gameplay wiring', () => {
const fetchMock: FetchMock = vi
.fn()
.mockResolvedValueOnce(jsonResponse(200, { session: { code: 'ABCD12', status: 'lie', current_round: 2 } }))
.mockResolvedValueOnce(jsonResponse(200, sessionDetailPayload('lie', { roundQuestionId: 99 })));
.mockResolvedValueOnce(jsonResponse(200, sessionDetailPayload('lie', { roundQuestionId: 99 })))
.mockResolvedValueOnce(jsonResponse(200, { session: { code: 'ABCD12', status: 'guess', current_round: 2 } }))
.mockResolvedValueOnce(jsonResponse(200, sessionDetailPayload('guess', { roundQuestionId: 77 })))
.mockResolvedValueOnce(jsonResponse(200, { session: { code: 'ABCD12', status: 'reveal', current_round: 2 } }))
.mockResolvedValueOnce(jsonResponse(200, sessionDetailPayload('reveal', { roundQuestionId: 77 })));
vi.stubGlobal('fetch', fetchMock);
@@ -206,8 +210,8 @@ describe('HostShellComponent gameplay wiring', () => {
it('runs next-round transition without reload and clears scoreboard payload', async () => {
const fetchMock: FetchMock = vi
.fn()
.mockResolvedValueOnce(jsonResponse(200, { session: { code: 'ABCD12', status: 'lobby', current_round: 2 } }))
.mockResolvedValueOnce(jsonResponse(200, sessionDetailPayload('lobby', { roundQuestionId: null })));
.mockResolvedValueOnce(jsonResponse(200, { session: { code: 'ABCD12', status: 'lie', current_round: 2 } }))
.mockResolvedValueOnce(jsonResponse(200, sessionDetailPayload('lie', { roundQuestionId: 99 })));
vi.stubGlobal('fetch', fetchMock);
@@ -216,6 +220,7 @@ describe('HostShellComponent gameplay wiring', () => {
component.scoreboardPayload = '{"leaderboard":[]}';
component.finalLeaderboardPayload = '{"leaderboard":[{"nickname":"Old","score":1}]}' ;
component.finalLeaderboard = [{ id: 9, nickname: 'Old', score: 1 }];
component.session = sessionDetailPayload('reveal', { roundQuestionId: 77 }) as any;
await component.startNextRound();
@@ -252,6 +257,7 @@ describe('HostShellComponent gameplay wiring', () => {
const component = new HostShellComponent();
component.sessionCode = 'ABCD12';
component.session = sessionDetailPayload('reveal', { roundQuestionId: 77 }) as any;
await component.finishGame();
expect(component.finishError).toContain('Finish game failed: Final leaderboard timeout');
@@ -275,6 +281,7 @@ describe('HostShellComponent gameplay wiring', () => {
const component = new HostShellComponent();
component.sessionCode = ' ';
component.session = sessionDetailPayload('reveal', { roundQuestionId: 77 }) as any;
await component.startNextRound();
await component.finishGame();
@@ -359,8 +366,12 @@ describe('HostShellComponent gameplay wiring', () => {
expect(component.canStartNextRound).toBe(false);
expect(component.canFinishGame).toBe(false);
component.session = sessionDetailPayload('scoreboard') as any;
component.session = sessionDetailPayload('reveal') as any;
expect(component.canStartNextRound).toBe(true);
expect(component.canFinishGame).toBe(true);
component.session = sessionDetailPayload('scoreboard') as any;
expect(component.canStartNextRound).toBe(false);
expect(component.canFinishGame).toBe(false);
});
});

View File

@@ -81,7 +81,7 @@ export function deriveGameplayPhase(session: SessionDetailResponse | null): Game
export function isHostGameplayActionAllowed(session: SessionDetailResponse | null, action: HostGameplayAction): boolean {
if (!session) {
return true;
return action === 'startRound';
}
const host = session.phase_view_model?.host;