Files
Genarrative/src/components/image-editor/ImageCanvasExportModel.test.ts
kdletters 1f5605331f 拆分图片画布编辑器前端模型
抽出编辑器共享类型、画布模型、生成模型和导出模型

补充模型层单测覆盖素材、吸附、生成快照和导出规则

新增前端拆分计划并更新 TRACKING 浏览器回归记录
2026-06-17 01:53:59 +08:00

119 lines
3.2 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
buildLayerExportMetadata,
dataUrlToBlob,
formatExportDate,
getImageExtensionFromTypeOrSrc,
getLayerExportKey,
sanitizeExportFilePart,
} from './ImageCanvasExportModel';
import type { CanvasLayer } from './ImageCanvasEditorTypes';
describe('ImageCanvasExportModel', () => {
it('normalizes export file names and dates', () => {
expect(sanitizeExportFilePart(' 角色/草图:*? ', 'fallback')).toBe(
'角色 草图',
);
expect(sanitizeExportFilePart(' ', 'fallback')).toBe('fallback');
expect(formatExportDate(new Date('2026-06-17T01:02:03.000Z'))).toBe(
'20260617',
);
});
it('chooses stable image export keys by persistence identity', () => {
expect(
getLayerExportKey({
...buildLayer(),
assetObjectId: 'object-1',
objectKey: 'object-key',
sourceAssetId: 'asset-1',
src: 'data:image/png;base64,one',
}),
).toBe('object-1');
expect(
getLayerExportKey({
...buildLayer(),
objectKey: 'object-key',
sourceAssetId: 'asset-1',
src: 'data:image/png;base64,one',
}),
).toBe('object-key');
});
it('detects image extensions from content type before falling back to src', () => {
expect(getImageExtensionFromTypeOrSrc('image/jpeg', '/image.png')).toBe(
'jpg',
);
expect(getImageExtensionFromTypeOrSrc('', '/image.webp?x=1')).toBe('webp');
expect(getImageExtensionFromTypeOrSrc('', '/image.unknown')).toBe('png');
});
it('converts data URLs and builds layer metadata for manifest files', async () => {
const blob = dataUrlToBlob('data:text/plain;base64,SGVsbG8=');
expect(blob.type).toBe('text/plain');
expect(await blob.text()).toBe('Hello');
expect(buildLayerExportMetadata(buildLayer(), 'images/001-layer.png')).toEqual({
layerId: 'layer-1',
title: '导出图层',
file: 'images/001-layer.png',
sourceType: 'generated',
prompt: '生成提示',
actualPrompt: '实际提示',
model: 'gpt-image-2',
provider: 'VectorEngine',
taskId: 'task-1',
objectKey: 'generated/layer.png',
assetObjectId: undefined,
sourceResourceId: 'source-resource',
sourceAssetId: 'asset-1',
exportError: undefined,
canvas: {
x: 10,
y: 20,
width: 512,
height: 512,
originalWidth: 1024,
originalHeight: 1024,
zIndex: 3,
groupId: 'group-1',
hidden: true,
locked: false,
flipX: true,
flipY: false,
},
});
});
});
function buildLayer(): CanvasLayer {
return {
id: 'layer-1',
resourceId: 'resource-1',
title: '导出图层',
src: 'data:image/png;base64,one',
x: 10,
y: 20,
width: 512,
height: 512,
originalWidth: 1024,
originalHeight: 1024,
zIndex: 3,
sourceType: 'generated',
prompt: '生成提示',
actualPrompt: '实际提示',
model: 'gpt-image-2',
provider: 'VectorEngine',
taskId: 'task-1',
objectKey: 'generated/layer.png',
sourceResourceId: 'source-resource',
sourceAssetId: 'asset-1',
groupId: 'group-1',
hidden: true,
locked: false,
flipX: true,
flipY: false,
};
}