Files
Genarrative/src/services/puzzle-runtime/puzzleRuntimeClient.test.ts
T
kdletters 7dd53e95d8 统一推荐页游客运行态与切换队列
统一推荐页各玩法正式 runtime 的游客鉴权透传。

收口推荐页首页展示队列和嵌入运行态切换队列。

补齐未登录读档、签名资产和个人数据读取的游客态处理。

新增运行态 HUD 小尺寸 logo 资源并更新拼图与抓鹅展示。

补充推荐切换、runtime guest 启动和客户端请求回归测试。

更新玩法链路、后端契约和团队记忆文档。
2026-06-10 22:00:19 +08:00

95 lines
2.4 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
const apiClientMocks = vi.hoisted(() => ({
requestJson: vi.fn(),
}));
vi.mock('../apiClient', async () => {
const actual =
await vi.importActual<typeof import('../apiClient')>('../apiClient');
return {
...actual,
requestJson: apiClientMocks.requestJson,
};
});
import {
getPuzzleRun,
swapPuzzlePieces,
updatePuzzleRunPause,
} from './puzzleRuntimeClient';
describe('puzzleRuntimeClient', () => {
beforeEach(() => {
vi.clearAllMocks();
apiClientMocks.requestJson.mockResolvedValue({ runId: 'run-1' });
});
it('reads runs through the shared encoded runtime path', async () => {
await getPuzzleRun('run/1');
expect(apiClientMocks.requestJson).toHaveBeenCalledWith(
'/api/runtime/puzzle/runs/run%2F1',
{ method: 'GET' },
'读取拼图运行快照失败',
expect.objectContaining({
retry: expect.objectContaining({ maxRetries: 1 }),
}),
);
});
it('submits puzzle swaps through the shared json request skeleton', async () => {
await swapPuzzlePieces('run/1', {
firstPieceId: 'piece-a',
secondPieceId: 'piece-b',
});
expect(apiClientMocks.requestJson).toHaveBeenCalledWith(
'/api/runtime/puzzle/runs/run%2F1/swap',
expect.objectContaining({
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
firstPieceId: 'piece-a',
secondPieceId: 'piece-b',
}),
}),
'交换拼图块失败',
expect.objectContaining({
retry: expect.objectContaining({ retryUnsafeMethods: true }),
}),
);
});
it('uses runtime guest auth for pause requests when provided', async () => {
await updatePuzzleRunPause(
'run/1',
{ paused: true },
{
authImpact: 'local',
runtimeGuestToken: 'runtime-guest-token',
skipRefresh: true,
},
);
const [, init, , options] = apiClientMocks.requestJson.mock.calls[0];
expect(init).toEqual(
expect.objectContaining({
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer runtime-guest-token',
},
body: JSON.stringify({ paused: true }),
}),
);
expect(options).toEqual(
expect.objectContaining({
authImpact: 'local',
skipAuth: true,
skipRefresh: true,
}),
);
});
});