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, }; }