Files
Genarrative/apps/ai-game-creator-shell/tests/projectSnapshotWorkspace.test.tsx
T
k88936 25c5ecdf6e
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m58s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 6m34s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m29s
Project CI / Backend tests (pull_request) Failing after 4m38s
Project CI / Frontend tests (pull_request) Successful in 3m33s
Project CI / Repository checks (pull_request) Failing after 4m4s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m13s
Project CI / Native shell tests (pull_request) Successful in 6m35s
测试:全仓测试统一 Tauri 运行时替身安装点
- 78 处内联 window.__TAURI__ 赋值改为 installTauriRuntime,覆盖 appSurface 之外的 37 个测试文件
- 31 处 delete window.__TAURI__ / window.__TAURI__ = undefined 复位改为 resetTauriRuntime
- 删除 recentProjectsHook、projectCreationDirectory、projectResourceLiveIntegration、useProjectResourceCardPreviews、resourceVersionReplacementModel、unityProjectOpen 里的本地 asTauriInvoke / asTauriListen 适配器与相关类型别名
- designProjectRestore 的 setup 参数由 ReturnType<typeof vi.fn> 收窄为具体 invoke 签名
- 迁移后仅 tests/tauriRuntimeFake.ts 直接读写 window.__TAURI__
2026-10-03 20:19:45 +08:00

110 lines
4.0 KiB
TypeScript

/** @vitest-environment jsdom */
import { act, cleanup, render, waitFor } from '@testing-library/react';
import React, { StrictMode } from 'react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { useProjectSnapshotWorkspace } from '../src/features/app-shell/useProjectSnapshotWorkspace';
import { createProjectSnapshotWorkspaceRegistration } from '../src/services/projectSnapshotWorkspace';
import { installTauriRuntime, resetTauriRuntime } from './tauriRuntimeFake';
afterEach(() => {
cleanup();
resetTauriRuntime();
});
describe('项目快照窗口登记', () => {
it('在无 projectPath URL 的单窗口登记、切换、离开,StrictMode 不误关项目', async () => {
const invoke = vi.fn(async () => undefined);
installTauriRuntime({ core: { invoke } });
function Workspace({ path }: { path: string | null }) {
useProjectSnapshotWorkspace(path);
return null;
}
const view = (path: string | null) => (
<StrictMode>
<Workspace path={path} />
</StrictMode>
);
expect(new URL(window.location.href).searchParams.has('projectPath')).toBe(
false,
);
const rendered = render(view('/projects/first'));
await waitFor(() => expect(invoke).toHaveBeenCalledTimes(1));
expect(invoke).toHaveBeenLastCalledWith(
'set_active_project_snapshot_workspace',
{ projectPath: '/projects/first' },
);
rendered.rerender(view('/projects/first'));
await act(async () => {
await Promise.resolve();
});
expect(invoke).toHaveBeenCalledTimes(1);
rendered.rerender(view('/projects/second'));
await waitFor(() => expect(invoke).toHaveBeenCalledTimes(2));
expect(invoke).toHaveBeenLastCalledWith(
'set_active_project_snapshot_workspace',
{ projectPath: '/projects/second' },
);
rendered.rerender(view(null));
await waitFor(() => expect(invoke).toHaveBeenCalledTimes(3));
expect(invoke).toHaveBeenLastCalledWith(
'set_active_project_snapshot_workspace',
{ projectPath: null },
);
rendered.rerender(view('/projects/third'));
await waitFor(() => expect(invoke).toHaveBeenCalledTimes(4));
rendered.unmount();
await waitFor(() => expect(invoke).toHaveBeenCalledTimes(5));
expect(invoke).toHaveBeenLastCalledWith(
'set_active_project_snapshot_workspace',
{ projectPath: null },
);
});
it('原生登记未完成时顺序提交后续切换,不让迟到回包覆盖新项目', async () => {
let release!: () => void;
const first = new Promise<void>((resolve) => {
release = resolve;
});
const invoke = vi
.fn()
.mockImplementationOnce(() => first)
.mockResolvedValue(undefined);
const registration = createProjectSnapshotWorkspaceRegistration(invoke);
void registration.setProject('/projects/first');
void registration.setProject('/projects/second');
const idle = registration.setProject(null);
await Promise.resolve();
expect(invoke).toHaveBeenCalledTimes(1);
release();
await idle;
expect(invoke.mock.calls.map((call) => call[1]?.projectPath)).toEqual([
'/projects/first',
'/projects/second',
null,
]);
});
it('失败写固定诊断并允许再次登记,不能泄漏原生错误中的路径和凭据', async () => {
const invoke = vi
.fn()
.mockRejectedValueOnce(new Error('C:\\private\\project token=secret'))
.mockResolvedValue(undefined);
const registration = createProjectSnapshotWorkspaceRegistration(invoke);
await expect(
registration.setProject('/projects/first'),
).resolves.toBeUndefined();
expect(invoke).toHaveBeenLastCalledWith('append_application_log', {
level: 'error',
source: 'project-snapshot',
message: 'project_snapshot.workspace.registration.failed',
});
await registration.setProject('/projects/first');
expect(invoke).toHaveBeenCalledTimes(3);
expect(invoke).toHaveBeenLastCalledWith(
'set_active_project_snapshot_workspace',
{ projectPath: '/projects/first' },
);
});
});