fix(frontend): restore default session context store in vertical slice
This commit is contained in:
@@ -1,18 +1,15 @@
|
|||||||
import type { ApiClient } from '../api/client';
|
import type { ApiClient } from '../api/client';
|
||||||
import type { SessionDetailResponse } from '../api/types';
|
import type { SessionDetailResponse } from '../api/types';
|
||||||
|
import {
|
||||||
|
createSessionContextStore,
|
||||||
|
type SessionContext,
|
||||||
|
type SessionContextInput,
|
||||||
|
type SessionContextStore as PersistedSessionContextStore
|
||||||
|
} from './session-context-store';
|
||||||
|
|
||||||
export type AsyncState = 'idle' | 'loading' | 'success' | 'error';
|
export type AsyncState = 'idle' | 'loading' | 'success' | 'error';
|
||||||
|
|
||||||
export interface SessionContext {
|
export type SessionContextStore = Pick<PersistedSessionContextStore, 'get' | 'set'>;
|
||||||
sessionCode: string;
|
|
||||||
playerToken: string;
|
|
||||||
nickname: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SessionContextStore {
|
|
||||||
get(): SessionContext | null;
|
|
||||||
set(context: SessionContext): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface VerticalSliceState {
|
export interface VerticalSliceState {
|
||||||
sessionCode: string;
|
sessionCode: string;
|
||||||
@@ -30,14 +27,9 @@ export interface VerticalSliceController {
|
|||||||
startRound(sessionCode: string, categorySlug: string): Promise<VerticalSliceState>;
|
startRound(sessionCode: string, categorySlug: string): Promise<VerticalSliceState>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NOOP_SESSION_CONTEXT_STORE: SessionContextStore = {
|
|
||||||
get: () => null,
|
|
||||||
set: () => undefined
|
|
||||||
};
|
|
||||||
|
|
||||||
export function createVerticalSliceController(
|
export function createVerticalSliceController(
|
||||||
api: ApiClient,
|
api: ApiClient,
|
||||||
sessionContextStore: SessionContextStore = NOOP_SESSION_CONTEXT_STORE
|
sessionContextStore: SessionContextStore = createSessionContextStore()
|
||||||
): VerticalSliceController {
|
): VerticalSliceController {
|
||||||
const persistedContext = sessionContextStore.get();
|
const persistedContext = sessionContextStore.get();
|
||||||
|
|
||||||
@@ -96,11 +88,12 @@ export function createVerticalSliceController(
|
|||||||
state.joinState = 'success';
|
state.joinState = 'success';
|
||||||
state.sessionCode = normalizeCode(join.data.session.code || requestCode);
|
state.sessionCode = normalizeCode(join.data.session.code || requestCode);
|
||||||
|
|
||||||
sessionContextStore.set({
|
const nextContext: SessionContextInput = {
|
||||||
sessionCode: state.sessionCode,
|
sessionCode: state.sessionCode,
|
||||||
playerToken: join.data.player.session_token,
|
playerId: join.data.player.id,
|
||||||
nickname: join.data.player.nickname
|
token: join.data.player.session_token
|
||||||
});
|
};
|
||||||
|
sessionContextStore.set(nextContext);
|
||||||
|
|
||||||
return hydrateLobby(state.sessionCode);
|
return hydrateLobby(state.sessionCode);
|
||||||
}
|
}
|
||||||
@@ -131,3 +124,5 @@ export function createVerticalSliceController(
|
|||||||
startRound
|
startRound
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type { SessionContext };
|
||||||
|
|||||||
@@ -68,11 +68,43 @@ function makeSessionContextStore(initial: SessionContext | null = null): Session
|
|||||||
get: vi.fn(() => value),
|
get: vi.fn(() => value),
|
||||||
set: vi.fn((next: SessionContext) => {
|
set: vi.fn((next: SessionContext) => {
|
||||||
value = next;
|
value = next;
|
||||||
|
return next;
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('vertical slice controller: lobby -> join -> start round', () => {
|
describe('vertical slice controller: lobby -> join -> start round', () => {
|
||||||
|
it('uses createSessionContextStore by default (no manual injection)', async () => {
|
||||||
|
vi.resetModules();
|
||||||
|
const defaultStore = {
|
||||||
|
get: vi.fn(() => null),
|
||||||
|
set: vi.fn((next: SessionContext) => next),
|
||||||
|
clear: vi.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
vi.doMock('../src/spa/session-context-store', async () => {
|
||||||
|
const actual = await vi.importActual<typeof import('../src/spa/session-context-store')>('../src/spa/session-context-store');
|
||||||
|
return {
|
||||||
|
...actual,
|
||||||
|
createSessionContextStore: vi.fn(() => defaultStore)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const { createVerticalSliceController: createControllerWithMock } = await import('../src/spa/vertical-slice');
|
||||||
|
const api = makeApiMock();
|
||||||
|
const controller = createControllerWithMock(api);
|
||||||
|
|
||||||
|
await controller.joinLobby('ABCD12', 'Maja');
|
||||||
|
|
||||||
|
expect(defaultStore.set).toHaveBeenCalledWith({
|
||||||
|
sessionCode: 'ABCD12',
|
||||||
|
playerId: 9,
|
||||||
|
token: 'token-1'
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.doUnmock('../src/spa/session-context-store');
|
||||||
|
vi.resetModules();
|
||||||
|
});
|
||||||
it('tracks loading and success state for join + start flow', async () => {
|
it('tracks loading and success state for join + start flow', async () => {
|
||||||
const api = makeApiMock();
|
const api = makeApiMock();
|
||||||
const controller = createVerticalSliceController(api);
|
const controller = createVerticalSliceController(api);
|
||||||
@@ -102,8 +134,8 @@ describe('vertical slice controller: lobby -> join -> start round', () => {
|
|||||||
|
|
||||||
expect(sessionContextStore.set).toHaveBeenCalledWith({
|
expect(sessionContextStore.set).toHaveBeenCalledWith({
|
||||||
sessionCode: 'ABCD12',
|
sessionCode: 'ABCD12',
|
||||||
playerToken: 'token-1',
|
playerId: 9,
|
||||||
nickname: 'Maja'
|
token: 'token-1'
|
||||||
});
|
});
|
||||||
expect(controller.getState().sessionCode).toBe('ABCD12');
|
expect(controller.getState().sessionCode).toBe('ABCD12');
|
||||||
});
|
});
|
||||||
@@ -112,8 +144,8 @@ describe('vertical slice controller: lobby -> join -> start round', () => {
|
|||||||
const api = makeApiMock();
|
const api = makeApiMock();
|
||||||
const sessionContextStore = makeSessionContextStore({
|
const sessionContextStore = makeSessionContextStore({
|
||||||
sessionCode: 'wxyz99',
|
sessionCode: 'wxyz99',
|
||||||
playerToken: 'token-old',
|
playerId: 5,
|
||||||
nickname: 'Maja'
|
token: 'token-old'
|
||||||
});
|
});
|
||||||
const controller = createVerticalSliceController(api, sessionContextStore);
|
const controller = createVerticalSliceController(api, sessionContextStore);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user