Files
Genarrative/apps/ai-game-creator-shell/tests/resourceCanvasCodeOnlyProject.test.tsx
T
k88936 876529e668 删除 Project Supervisor 前端链路并将项目对话收敛到 DirectProject 与立项策划
- 删除 ProjectSupervisorView、SupervisorChatOnlyView、ProjectWorkspaceChatPane、AgentConversationOverlay、DeveloperProjectPanels、DeveloperRuntimePanels 与 features/agent-runtime/panels.tsx
- 删除 Supervisor 独立调试窗口:windows.rs 的 supervisor_chat_window_url / open_project_supervisor_chat_window、main.rs 的 invoke 注册、?supervisor-chat 与 ?agent-chat 前端入口、developer.json capability 和对应 Rust 用例
- 删除工作台壳的开发者 Agent 面板:DeveloperAgentPanel、useDeveloperAgentPanel、useDeveloperAgentState、developerAgentControls
- App.tsx 删除只服务退役面板的 state/ref/effect/handler(agentConversation*、文件/记忆/资产/画板/预览面板处理、commandLog、llmConfigStatus、editorBaseUrl、回放历史与 trace 面板状态、selectedAgent 等)以及由此产生的空分支,并把 requestRuntimeConfigOpen 接回本地 RuntimeConfigDialog
- 立项策划独立成模块:Design Agent 与 Planning V2 的容器和表现移到 view/project-development/planning/(PlanningChatView、PlanningUserInputCard、GddApprovalCard、DesignAgentSurface、PlanningLaneRuntimeStrip、planningLane、planningSessionV2、planningSessionContract)
- 改名到中性概念:ProjectSupervisorComponentProps→ProjectChatComponentProps、WorkspaceLauncherShellProps.ProjectSupervisor→ProjectChat、ProjectDevelopmentView.supervisor→chat、orchestrationMode→agentDockVisible、initialSupervisorMessageClaims→initialTurnClaims、ProjectManifestSnapshotSource 'supervisor'→'chat'、CSS project-supervisor-*/project-planning-*→project-chat-*
- 删除 PROJECT_SUPERVISOR_AGENT_ID 与 PROJECT_SUPERVISOR_PLAN_SOURCE 常量
- 工作台壳自己订阅 game-creator-manifest-invalidated,用 revision→清单→revision 配对读(source: asset-event)并入 currentProjectContext,且不重新检查项目目录;测试夹具改为按监听器集合广播该事件
- 删除只钉住退役界面的 appSurface 用例(旧调试窗口、开发者面板、Agent 对话浮层、运行历史面板)
- 同步文档:ADR、DirectProject 聊天模块抽离实施计划与里程碑、Provider 推理里程碑、策划会话 RuntimeV2、AI 游戏创作实施计划,并在 decision-log 新增 2026-09-19 条
- 删除随退役面板失去调用方的模块与导出:projectSummaryCommands.ts(1054 行旧 Supervisor 斜杠命令处理器)、AGENT_RUN_HISTORY_* 常量、agent-runtime/model.ts 与 project-summary/agentPresentation.ts 里的死导出,以及 agentRunTrace / memoryCommands / projectCommandPolicy 中无调用方的校验与解析函数
- 更新 scripts/check-config.mjs 与 scripts/check-native-shells.mjs 的窗口与命令守卫
2026-09-19 21:59:44 +08:00

134 lines
3.9 KiB
TypeScript

// @vitest-environment jsdom
import { afterEach, describe, expect, test, vi } from 'vitest';
import type { GameCreationAppManifest } from '../../../packages/shared/src/contracts/gameCreationApp';
import {
cleanup,
createGameCreationAppManifest,
createGameCreationAppSeedTasks,
ProjectDevelopmentView,
React,
render,
screen,
waitFor,
} from './appSurface/harness';
const PROJECT_PATH = '/tmp/workbench-code-only-project';
function installResourceCardIntersectionObserver() {
class ResourceCardIntersectionObserver {
readonly root = null;
readonly rootMargin = '160px';
readonly thresholds = [0];
readonly observed = new Set<Element>();
constructor(readonly callback: IntersectionObserverCallback) {}
observe(element: Element) {
this.observed.add(element);
}
unobserve(element: Element) {
this.observed.delete(element);
}
disconnect() {
this.observed.clear();
}
takeRecords() {
return [];
}
}
Object.defineProperty(window, 'IntersectionObserver', {
configurable: true,
value: ResourceCardIntersectionObserver,
});
}
/**
* 只登记游戏代码的项目:分区轴上没有代码栏目,代码资产(manifest 资产与已完成任务登记
* 的产物)按资产功能分类落入「待归类」。旧四栏目口径会把它们整体排除在可见栏目之外,
* 于是资源签名非空、画布已进入分页态,却四栏全空、一张卡都不显示。
*/
function createCodeOnlyManifest(): GameCreationAppManifest {
const manifest = createGameCreationAppManifest(
'workbench-code-only',
'只登记游戏代码的项目',
);
manifest.assets = [
{
id: 'asset-game-entry',
kind: 'code',
mediaType: 'text/html',
localPath: 'game/index.html',
source: { kind: 'generated' },
},
];
manifest.tasks = createGameCreationAppSeedTasks().map((task) =>
task.id === 'code-prototype'
? { ...task, status: 'completed' as const, artifacts: ['game/main.js'] }
: task,
);
return manifest;
}
function renderWorkbench(manifest: GameCreationAppManifest) {
return render(
React.createElement(ProjectDevelopmentView, {
projectName: manifest.name,
projectPath: PROJECT_PATH,
manifest,
attachments: [],
recentRunStatus: null,
recentRunStopReason: null,
chat: React.createElement('div', null, '项目总控'),
onHomeOpen: vi.fn(),
onProjectsOpen: vi.fn(),
onPlay: vi.fn(),
}),
);
}
describe('只登记游戏代码的项目分区', () => {
afterEach(() => {
cleanup();
});
test('代码资产落在待归类栏目并渲染出卡片,而不是四栏全空', async () => {
installResourceCardIntersectionObserver();
renderWorkbench(createCodeOnlyManifest());
// 左侧栏目大纲导航已删除:栏目清单改由「资源总览」缩略卡片承载。
await waitFor(() =>
expect(
document.querySelector('.game-resource-book-thumbnail'),
).not.toBeNull(),
);
const thumbnailLabels = Array.from(
document.querySelectorAll('.game-resource-book-thumbnail'),
(thumbnail) => thumbnail.getAttribute('aria-label'),
);
expect(thumbnailLabels).toContain('打开待归类');
// 项目版本仍然是末尾独立栏目,代码栏目不再存在。
expect(thumbnailLabels).toContain('打开项目版本');
expect(thumbnailLabels.some((label) => label?.includes('游戏代码'))).toBe(
false,
);
// 默认停留在顺序里第一个非空栏目,也就是代码资产所在的「待归类」。
expect(
await screen.findByRole('region', { name: '待归类' }),
).not.toBeNull();
// manifest 资产与已完成任务的代码产物都必须真的渲染成卡片。
await screen.findByRole('button', {
name: /选中资源:待归类 index\.html/,
});
await screen.findByRole('button', {
name: /选中资源:待归类 main\.js/,
});
});
});