完善 AI 设计资产预览与视频首帧选择
需求:生成图片需要支持大图查看和本地下载;制作视频时需要从当前项目作品选择首帧,或上传本地图片。 实现:新增首帧选择弹窗、JPEG/PNG/WebP 有界上传、附件 Asset ID 透传、Main 到服务端 multipart 转发,并保留上传失败重试与私有图片下载链路。 验证:相关 57 项单测、TypeScript 类型检查、目标 ESLint 和 Vite 生产构建全部通过。
This commit is contained in:
@@ -223,6 +223,46 @@ describe('Works Square AI design adapter', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('uploads a local reference image as multipart data and maps the returned Asset', async () => {
|
||||
const fetchMock = vi.fn<typeof fetch>().mockResolvedValueOnce(jsonResponse({
|
||||
asset_id: 'asset-uploaded',
|
||||
media_type: 'image',
|
||||
mime_type: 'image/png',
|
||||
width: 1200,
|
||||
height: 800,
|
||||
duration_milliseconds: null,
|
||||
created_at: '2026-08-06T10:00:00Z',
|
||||
}));
|
||||
const adapter = new WorksSquareDesignWorkspace({
|
||||
apiBaseUrl: 'https://square.example',
|
||||
fetchImpl: fetchMock,
|
||||
});
|
||||
|
||||
await expect(adapter.uploadAsset({
|
||||
workspaceId: 'workspace-one',
|
||||
fileName: 'poster.webp',
|
||||
mimeType: 'image/webp',
|
||||
bytes: new Uint8Array([1, 2, 3]),
|
||||
})).resolves.toMatchObject({
|
||||
assetId: 'asset-uploaded',
|
||||
workspaceId: 'workspace-one',
|
||||
mimeType: 'image/png',
|
||||
contentPath: '/api/works/image-workspace/workspaces/workspace-one/assets/asset-uploaded/content',
|
||||
});
|
||||
|
||||
const [url, init] = fetchMock.mock.calls[0];
|
||||
expect(url).toBe('https://square.example/api/design/workspaces/workspace-one/assets');
|
||||
expect(init?.method).toBe('POST');
|
||||
expect((init?.headers as Record<string, string>).Authorization).toBe('Bearer access-one');
|
||||
expect((init?.headers as Record<string, string>)['Content-Type']).toBeUndefined();
|
||||
const form = init?.body as FormData;
|
||||
expect(form.get('file')).toBeInstanceOf(File);
|
||||
expect((form.get('file') as File).name).toBe('poster.webp');
|
||||
expect(await (form.get('file') as File).arrayBuffer()).toEqual(
|
||||
Uint8Array.from([1, 2, 3]).buffer,
|
||||
);
|
||||
});
|
||||
|
||||
it('completes a design turn from the connected WebSocket without polling the run endpoint', async () => {
|
||||
const { sockets, webSocketFactory } = scriptedSockets([{ open: true }]);
|
||||
const fetchMock = vi.fn<typeof fetch>(async (input) => {
|
||||
|
||||
Reference in New Issue
Block a user