Files
Genarrative/apps/ai-game-creator-shell/tests/separationOverview.test.ts
T
k88936 1509235c1b 统一自动切分素材工作流命名
将 UI 编辑器第三步和内部流程 ID 统一为自动切分素材。
重命名前端切分概览模块并更新完成、恢复和导航文案。
同步 Runtime 最终编辑器路由、测试与相关技术文档。
2026-09-10 15:11:29 +08:00

134 lines
3.5 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
getSeparationOverview,
nodeHasBlockedComponents,
nodeHasPendingSeparation,
nodeNeedsComponentReview,
} from '../src/features/ui-editor/separationOverview';
import { getNextMatchingUiTreeNodeTarget } from '../src/features/ui-editor/stageStatusOverview';
import type { Component } from '../src/features/ui-editor/types/Component';
import type { Node } from '../src/features/ui-editor/types/Node';
import type { SpriteAsset } from '../src/features/ui-editor/types/SpriteAsset';
import type { UITree } from '../src/features/ui-editor/types/UITree';
function image(targetGraphic: string | null): Component {
return {
Image: {
target_graphic: targetGraphic,
image_type: { Simple: { preserve_aspect: false } },
},
};
}
function text(font: 'SystemFont' | { Bound: string }): Component {
return {
Text: {
content: '文本',
font,
font_style: 'Normal',
font_sizing: { Fixed: 14 },
color: [255, 255, 255, 255],
alignment: 'UpperLeft',
horizontal_overflow: 'Wrap',
vertical_overflow: 'Truncate',
line_spacing: 1,
},
};
}
function node(
id: string,
component: Component | null,
componentStatus: Node['metadata']['component_status'] = 'NoProblem',
children: Node[] = [],
): Node {
return {
id,
layout: {
transform: {
anchor_min: [0, 0],
anchor_max: [1, 1],
offset_min: [0, 0],
offset_max: [0, 0],
},
custom_minimum_size: [0, 0],
size_flags_horizontal: 1,
size_flags_vertical: 1,
size_flags_stretch_ratio: 1,
container: 'None',
},
metadata: {
name: id,
description: '',
layout_status: 'NoProblem',
component_status: componentStatus,
allow_llm_edit_layout: true,
allow_llm_edit_component: true,
source: 'System',
},
component,
children,
};
}
function sprite(id: string): SpriteAsset {
return {
asset_id: id,
metadata: { name: id, asset_type: 'Normal' },
path: `${id}.png`,
pixel_size: [16, 16],
pixels_per_unit: 1,
border: { left: 0, right: 0, top: 0, bottom: 0 },
};
}
const sprites = {
validSprite: sprite('validSprite'),
unused: sprite('unused'),
};
const trees: UITree[] = [
{
src_ui_design: 'page-a',
root: node('root', image('validSprite'), 'NoProblem', [
node('review', image(null), { NeedReview: '确认素材' }),
node('blocked', text('SystemFont'), { Blocked: '素材绑定失败' }),
]),
},
];
describe('getSeparationOverview', () => {
it('uses per-component helpers to include both image and text slots', () => {
expect(getSeparationOverview(trees, sprites)).toEqual({
componentsNeedingAssets: 2,
assetSlots: 2,
boundSlots: 1,
pendingSlots: 1,
needsAttention: 2,
blocked: 1,
independentAssets: 2,
});
});
it('reuses the common preorder next-target search for every separation queue', () => {
expect(
getNextMatchingUiTreeNodeTarget(trees, null, (target) =>
nodeHasPendingSeparation(target),
)?.node.id,
).toBe('review');
expect(
getNextMatchingUiTreeNodeTarget(trees, 'review', (target) =>
nodeHasPendingSeparation(target),
)?.node.id,
).toBe('review');
expect(
getNextMatchingUiTreeNodeTarget(trees, null, nodeNeedsComponentReview)
?.node.id,
).toBe('review');
expect(
getNextMatchingUiTreeNodeTarget(trees, null, nodeHasBlockedComponents)
?.node.id,
).toBe('blocked');
});
});