合并主分支
合并画布素材导出主线,保留钱包与充值修复。
This commit is contained in:
@@ -298,6 +298,78 @@ describe('ImageCanvasExportModel', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('falls back when OSS returns 206 but its response body fails during export', async () => {
|
||||
const originalFetch = globalThis.fetch;
|
||||
const signedResponseBlob = vi
|
||||
.fn()
|
||||
.mockRejectedValue(new TypeError('Failed to fetch'));
|
||||
const fetchMock = vi.fn(async (url: string) => {
|
||||
if (url.startsWith('/api/assets/read-url?')) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
ok: true,
|
||||
data: {
|
||||
read: {
|
||||
objectKey: 'generated/export-body-failure.png',
|
||||
signedUrl: 'https://signed.example.com/export-body-failure.png',
|
||||
expiresAt: '2099-01-01T00:10:00Z',
|
||||
},
|
||||
},
|
||||
error: null,
|
||||
meta: {
|
||||
apiVersion: '2026-06-16',
|
||||
routeVersion: '2026-06-16',
|
||||
latencyMs: 1,
|
||||
timestamp: '2099-01-01T00:00:00Z',
|
||||
},
|
||||
}),
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
if (url === 'https://signed.example.com/export-body-failure.png') {
|
||||
return {
|
||||
ok: true,
|
||||
status: 206,
|
||||
statusText: 'Partial Content',
|
||||
headers: new Headers({
|
||||
'Content-Range': 'bytes 0-2/3',
|
||||
'Content-Type': 'image/png',
|
||||
}),
|
||||
blob: signedResponseBlob,
|
||||
} as unknown as Response;
|
||||
}
|
||||
if (url.startsWith('/api/assets/read-bytes?')) {
|
||||
return new Response(new Blob(['fallback'], { type: 'image/png' }));
|
||||
}
|
||||
return new Response(null, { status: 404 });
|
||||
});
|
||||
globalThis.fetch = fetchMock as typeof fetch;
|
||||
|
||||
try {
|
||||
const blob = await readLayerAssetBlob(
|
||||
buildLayer({
|
||||
src: '/generated-editor-images/export-body-failure.png',
|
||||
objectKey: 'generated/export-body-failure.png',
|
||||
}),
|
||||
);
|
||||
|
||||
expect(signedResponseBlob).toHaveBeenCalledTimes(1);
|
||||
await expect(blob.text()).resolves.toBe('fallback');
|
||||
expect(fetchMock).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'/api/assets/read-bytes?objectKey=generated%2Fexport-body-failure.png',
|
||||
),
|
||||
expect.any(Object),
|
||||
);
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch;
|
||||
}
|
||||
});
|
||||
|
||||
it('reads private image-sequence frame object keys through same-origin bytes', async () => {
|
||||
const originalFetch = globalThis.fetch;
|
||||
const fetchMock = vi.fn(async (url: string) => {
|
||||
|
||||
Reference in New Issue
Block a user