0a8debef56
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
- 保留 master 的 DirectProject / ProjectChat 重构与测试重组:原 appSurface 的 project-commands / project-preview / supervisor-runtime 三个 suite 已被 master 删除,接受删除并把相关断言重写到 tests/previewActivation.test.tsx 等新用例 - 本分支改动重放到 master 结构:运行与预览成功的反馈改走 onRunNotice toast(带 tone),对话区不再写过程提示 - 运行页顶栏统一:预览地址改成「在浏览器打开」按钮,版本入口搬进同一动作区复用同一套按钮皮,状态行与预览地址小字退役 - 生成任务入口、面板与锚点不在运行页渲染,placement 里的 run 档一并删除 - 手工合并 App.tsx / WorkspaceLauncher.tsx / model.ts / check-config.mjs / decision-log / pitfalls,并把两条决策记录与一条排障记录补进 master 版本文档
120 lines
3.7 KiB
TypeScript
120 lines
3.7 KiB
TypeScript
/** @vitest-environment jsdom */
|
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import { createGameCreationAppManifest } from '../../../packages/shared/src/contracts/gameCreationApp';
|
|
import ProjectDevelopmentView from '../src/view/project-development';
|
|
|
|
const openUrl = vi.fn(async () => undefined);
|
|
vi.mock('@tauri-apps/plugin-opener', () => ({
|
|
openUrl: (url: string) => openUrl(url),
|
|
}));
|
|
|
|
const PREVIEW_URL = 'http://127.0.0.1:4173/';
|
|
|
|
function installInvoke() {
|
|
window.__TAURI__ = {
|
|
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}`);
|
|
}),
|
|
},
|
|
} as unknown as typeof window.__TAURI__;
|
|
}
|
|
|
|
function renderRunView(options: { withPreview?: boolean } = {}) {
|
|
installInvoke();
|
|
const manifest = createGameCreationAppManifest(
|
|
'run-preview-browser-open',
|
|
'运行页浏览器入口',
|
|
);
|
|
const onNotice = vi.fn();
|
|
render(
|
|
<ProjectDevelopmentView
|
|
projectName={manifest.name}
|
|
projectPath="/tmp/run-preview-browser-open"
|
|
manifest={manifest}
|
|
attachments={[]}
|
|
recentRunStatus={null}
|
|
recentRunStopReason={null}
|
|
preview={
|
|
options.withPreview === false
|
|
? null
|
|
: { status: 'running', url: PREVIEW_URL, port: 4173 }
|
|
}
|
|
supervisor={<div>项目总控</div>}
|
|
onHomeOpen={vi.fn()}
|
|
onProjectsOpen={vi.fn()}
|
|
onNotice={onNotice}
|
|
/>,
|
|
);
|
|
return { onNotice };
|
|
}
|
|
|
|
afterEach(() => {
|
|
document.body.innerHTML = '';
|
|
vi.clearAllMocks();
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
describe('运行页「在浏览器打开」', () => {
|
|
it('点顶栏那枚按钮就把当前预览地址交给系统浏览器', async () => {
|
|
renderRunView();
|
|
|
|
const entry = await screen.findByRole('button', {
|
|
name: '在浏览器打开',
|
|
});
|
|
// 入口住在工作台顶栏的动作区里,与版本入口同一排;预览地址本身不再以文字出现。
|
|
expect(entry.closest('.game-workbench-view-actions')).not.toBeNull();
|
|
expect(document.body.textContent ?? '').not.toContain(PREVIEW_URL);
|
|
expect(document.querySelector('.game-run-status-hint')).toBeNull();
|
|
fireEvent.click(entry);
|
|
|
|
await waitFor(() => expect(openUrl).toHaveBeenCalledWith(PREVIEW_URL));
|
|
// 成功不弹提示:浏览器真的起来了,用户自己看得见。
|
|
expect(openUrl).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('没有活预览时不渲染这枚入口', async () => {
|
|
renderRunView({ withPreview: false });
|
|
|
|
await screen.findByRole('tab', { name: '运行' });
|
|
expect(screen.queryByRole('button', { name: '在浏览器打开' })).toBeNull();
|
|
});
|
|
|
|
it('打开失败时把原因交给统一提示通道,而不是静默吞掉', async () => {
|
|
openUrl.mockRejectedValueOnce(new Error('permission denied'));
|
|
const { onNotice } = renderRunView();
|
|
|
|
fireEvent.click(
|
|
await screen.findByRole('button', { name: '在浏览器打开' }),
|
|
);
|
|
|
|
await waitFor(() =>
|
|
expect(onNotice).toHaveBeenCalledWith({
|
|
tone: 'error',
|
|
message: '在浏览器打开失败:permission denied',
|
|
}),
|
|
);
|
|
});
|
|
});
|