995db645e2
统一 StageStatus 为 NoProblem、NeedReview 和 Blocked 移除 Pending 与 Passed 的前后端、LLM 草稿及持久化夹具用法 补充旧状态拒绝测试并更新 UI Editor 技术方案
139 lines
3.6 KiB
TypeScript
139 lines
3.6 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
getBindingOverview,
|
|
nodeHasBlockedComponents,
|
|
nodeHasPendingBinding,
|
|
nodeNeedsComponentReview,
|
|
} from '../src/features/ui-editor/bindingOverview';
|
|
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,
|
|
components: Component[],
|
|
componentsStatus: Node['metadata']['components_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',
|
|
components_status: componentsStatus,
|
|
allow_llm_edit_layout: true,
|
|
allow_llm_edit_component: true,
|
|
source: 'System',
|
|
},
|
|
components,
|
|
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'), text({ Bound: 'font-id' })],
|
|
'NoProblem',
|
|
[
|
|
node('review', [image(null)], { NeedReview: '确认素材' }),
|
|
node('blocked', [text('SystemFont')], { Blocked: '素材绑定失败' }),
|
|
],
|
|
),
|
|
},
|
|
];
|
|
|
|
describe('getBindingOverview', () => {
|
|
it('uses per-component helpers to include both image and text slots', () => {
|
|
expect(getBindingOverview(trees, sprites)).toEqual({
|
|
componentsNeedingAssets: 3,
|
|
assetSlots: 3,
|
|
boundSlots: 2,
|
|
pendingSlots: 1,
|
|
needsAttention: 2,
|
|
blocked: 1,
|
|
independentAssets: 2,
|
|
});
|
|
});
|
|
|
|
it('reuses the common preorder next-target search for every binding queue', () => {
|
|
expect(
|
|
getNextMatchingUiTreeNodeTarget(trees, null, (target) =>
|
|
nodeHasPendingBinding(target),
|
|
)?.node.id,
|
|
).toBe('review');
|
|
expect(
|
|
getNextMatchingUiTreeNodeTarget(trees, 'review', (target) =>
|
|
nodeHasPendingBinding(target),
|
|
)?.node.id,
|
|
).toBe('review');
|
|
expect(
|
|
getNextMatchingUiTreeNodeTarget(trees, null, nodeNeedsComponentReview)
|
|
?.node.id,
|
|
).toBe('review');
|
|
expect(
|
|
getNextMatchingUiTreeNodeTarget(trees, null, nodeHasBlockedComponents)
|
|
?.node.id,
|
|
).toBe('blocked');
|
|
});
|
|
});
|