Files
Genarrative/apps/ai-game-creator-shell/tests/runPreviewRefresh.test.tsx
T
suzmii 0e75d132a7
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m59s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 4m13s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m20s
Project CI / Backend tests (pull_request) Successful in 6m36s
Project CI / Frontend tests (pull_request) Successful in 3m15s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m16s
Project CI / Native shell tests (pull_request) Successful in 7m14s
Project CI / Repository checks (pull_request) Successful in 6m4s
修正运行页刷新用例的 preview 类型:改用 GameCreationAppPreviewState
- runPreviewRefresh 的 preview 形参从自造字面量类型改为契约类型,避免 status 被放宽成 string 与 view 的 props 冲突(tsconfig.tests.json 才会覆盖 tests/ 目录,此前只跑 tsc -p tsconfig.json 漏检)
- 已跑 npm run ai-game-creator-shell:typecheck(含 check:tests:types)与定向用例确认通过
2026-10-04 14:48:28 +08:00

116 lines
3.6 KiB
TypeScript

/** @vitest-environment jsdom */
import { cleanup, fireEvent, render, screen } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import {
createGameCreationAppManifest,
type GameCreationAppPreviewState,
} from '../../../packages/shared/src/contracts/gameCreationApp';
import ProjectDevelopmentView from '../src/view/project-development';
import { installTauriRuntime } from './tauriRuntimeFake';
const PREVIEW_URL = 'http://127.0.0.1:4173/';
function installInvoke() {
installTauriRuntime({
core: {
invoke: vi.fn(async (command: string, args?: Record<string, unknown>) => {
if (command === 'read_local_project_resource_graph') {
return {
resourceIds: [],
referenceEdges: [],
taskFlows: [],
categories: [],
diagnostics: [],
};
}
if (command === 'read_local_project_resource_canvas_layout') {
return {
schemaVersion: 'game-creator-resource-layout.v1',
projectId: args?.expectedProjectId,
mode: args?.mode,
revision: 0,
positions: [],
updatedAt: 0,
};
}
throw new Error(`unexpected invoke ${command}`);
}),
},
});
}
function renderRunView(
preview: GameCreationAppPreviewState = {
status: 'running',
url: PREVIEW_URL,
port: 4173,
},
) {
installInvoke();
const onPlay = vi.fn();
const manifest = createGameCreationAppManifest(
'run-preview-refresh',
'运行页刷新画面',
);
manifest.tasks = manifest.tasks.map((task) =>
task.id === 'code-prototype' ? { ...task, status: 'completed' } : task,
);
render(
<ProjectDevelopmentView
projectName={manifest.name}
projectPath="/tmp/run-preview-refresh"
manifest={manifest}
attachments={[]}
recentRunStatus="completed"
recentRunStopReason={null}
preview={preview}
chat={null}
onHomeOpen={vi.fn()}
onProjectsOpen={vi.fn()}
onNotice={vi.fn()}
onPlay={onPlay}
/>,
);
return { onPlay };
}
afterEach(() => {
cleanup();
vi.clearAllMocks();
vi.restoreAllMocks();
});
describe('运行页「刷新运行画面」', () => {
it('点一下就重新载入画面:iframe 换新节点、地址不变,并顺带把预览确认成活体', async () => {
const { onPlay } = renderRunView();
await screen.findByTitle('运行页刷新画面 游戏运行画面');
const before = document.querySelector('iframe');
expect(before).not.toBeNull();
expect(before?.getAttribute('src')).toBe(PREVIEW_URL);
fireEvent.click(screen.getByRole('button', { name: '刷新运行画面' }));
const after = document.querySelector('iframe');
// 换元素身份=浏览器重新载入这一页:游戏预览不是 vite dev 的实时刷新,只有这一条路。
expect(after).not.toBe(before);
expect(after?.getAttribute('src')).toBe(PREVIEW_URL);
expect(onPlay).toHaveBeenCalledTimes(1);
});
it('没有活预览时不渲染刷新,而不是留一个点了没反应的入口', async () => {
// 非 loopback 地址会被 `resolveEmbeddedPreviewUrl` 拒掉。此时切到运行页只有空态,
// 该走的是顶栏「运行」页签——刷新入口不该在没画面可刷的时候出现。
renderRunView({
status: 'running',
url: 'https://example.com/game',
port: 443,
});
fireEvent.click(screen.getByRole('tab', { name: '运行' }));
await screen.findByText('客户端运行画面尚未载入');
expect(screen.queryByRole('button', { name: '刷新运行画面' })).toBeNull();
});
});