import { describe, expect, it } from 'vitest'; import { createGameCreationAppManifest } from '../../../packages/shared/src/contracts/gameCreationApp'; import { projectResourcesFromReadModels } from '../src/view/project-development/resourceProjectionModel'; describe('项目资源投影', () => { it('只把明确资源投影到固定分类,未知任务产物不会伪装成项目版本', () => { const manifest = createGameCreationAppManifest( 'resource-projection', '资源投影测试', ); const designTask = manifest.tasks.find( (task) => task.id === 'design-foundation', ); const audioTask = manifest.tasks.find( (task) => task.id === 'audio-asset-plan', ); if (!designTask || !audioTask) { throw new Error('缺少资源投影测试任务'); } designTask.status = 'completed'; designTask.artifacts = [ 'memory/game-design.md', 'assets/ui-preview.svg', 'build/game.bundle', ]; audioTask.status = 'completed'; audioTask.artifacts = ['audio/unregistered-bgm.wav']; manifest.assets = [ { id: 'registered-bgm', kind: 'bgm', mediaType: 'audio/wav', localPath: 'audio/registered-bgm.wav', source: { kind: 'generated' }, }, { id: 'character-animation', kind: 'character-animation', mediaType: 'application/json', localPath: 'assets/character-animation.json', source: { kind: 'generated' }, }, { id: 'unknown-binary', kind: 'binary', mediaType: 'application/octet-stream', localPath: 'build/game.bundle', source: { kind: 'generated' }, }, ]; const resources = projectResourcesFromReadModels( manifest, [ { fileName: 'rules.yaml', mediaType: 'application/yaml', localPath: 'imports/rules.yaml', status: 'imported', }, { fileName: 'voice.ogg', mediaType: 'audio/ogg', localPath: 'imports/voice.ogg', status: 'imported', }, { fileName: 'archive.zip', mediaType: 'application/zip', localPath: 'imports/archive.zip', status: 'imported', }, ], [ { agentId: 'design-foundation', runId: 'final-run', label: '玩法策划 Agent', title: '玩法文档回执', content: '回执正文', updatedAt: 1, }, ], [ { versionId: 'version-1', label: '首个可运行版本', projectRevision: 7, parentVersionId: null, createdAt: 1, }, ], ); expect(resources.map(({ id, category }) => ({ id, category }))).toEqual( expect.arrayContaining([ { id: 'task:design-foundation:memory/game-design.md', category: 'document', }, { id: 'task:design-foundation:assets/ui-preview.svg', category: 'art', }, { id: 'asset:registered-bgm', category: 'audio' }, { id: 'asset:character-animation', category: 'art' }, { id: 'attachment:imports/rules.yaml', category: 'document' }, { id: 'attachment:imports/voice.ogg', category: 'audio' }, { id: 'agent-result:design-foundation:final-run', category: 'document', }, { id: 'version:version-1', category: 'version' }, ]), ); expect( resources.some(({ id }) => [ 'task:design-foundation:build/game.bundle', 'task:audio-asset-plan:audio/unregistered-bgm.wav', 'asset:unknown-binary', 'attachment:imports/archive.zip', ].includes(id), ), ).toBe(false); expect( resources.filter(({ category }) => category === 'version'), ).toHaveLength(1); }); it('显示名称变化不会改变正式资源身份', () => { const manifest = createGameCreationAppManifest( 'stable-resource-id', '稳定资源身份测试', ); const first = projectResourcesFromReadModels( manifest, [], [ { agentId: 'design-foundation', runId: 'stable-run', label: '策划 Agent', title: '旧标题', content: '正文', updatedAt: 1, }, ], [ { versionId: 'stable-version', label: '旧版本名', projectRevision: 1, parentVersionId: null, createdAt: 1, }, ], ); const second = projectResourcesFromReadModels( manifest, [], [ { agentId: 'design-foundation', runId: 'stable-run', label: '策划 Agent', title: '新标题', content: '正文', updatedAt: 2, }, ], [ { versionId: 'stable-version', label: '新版本名', projectRevision: 1, parentVersionId: null, createdAt: 1, }, ], ); expect(first.map(({ id }) => id)).toEqual(second.map(({ id }) => id)); }); });