119 lines
3.2 KiB
TypeScript
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,
|
|
};
|
|
}
|