fix: render prompt museum media

This commit is contained in:
2026-08-18 12:32:34 +08:00
parent 11b19832a3
commit f8d82e6c19
9 changed files with 609 additions and 37 deletions

View File

@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
import { hostApiFetch } from '@/lib/host-api';
import {
fetchPromptMuseumEntry,
fetchPromptMuseumMedia,
fetchPromptMuseumPage,
PromptMuseumApiError,
} from '@/lib/image-prompt-museum';
@@ -65,4 +66,38 @@ describe('Prompt Museum renderer API boundary', () => {
);
});
it('loads a controlled relative media path through Main and creates a data URL', async () => {
hostApiFetchMock.mockResolvedValueOnce({ mimeType: 'image/webp', dataBase64: 'AQID' });
await expect(fetchPromptMuseumMedia(
'/api/image-prompt-museum/entry-1:en/media/thumbnail',
)).resolves.toBe('data:image/webp;base64,AQID');
expect(hostApiFetchMock).toHaveBeenCalledWith(
'/api/works/image-prompt-museum/entry-1:en/media/thumbnail',
);
});
it.each([
'https://cdn.example/image.webp',
'/api/image-prompt-museum/../media/thumbnail',
'/api/image-prompt-museum/entry/media/original',
])('rejects unsafe media URL %s before IPC', async (url) => {
await expect(fetchPromptMuseumMedia(url)).rejects.toMatchObject({
status: 400,
code: 'PROMPT_MUSEUM_INVALID_MEDIA_URL',
});
expect(hostApiFetchMock).not.toHaveBeenCalled();
});
it('rejects an untrusted Main media payload', async () => {
hostApiFetchMock.mockResolvedValueOnce({ mimeType: 'text/html', dataBase64: 'PGgxPg==' });
await expect(fetchPromptMuseumMedia(
'/api/image-prompt-museum/entry/media/0',
)).rejects.toMatchObject({
status: 502,
code: 'PROMPT_MUSEUM_INVALID_MEDIA_RESPONSE',
});
});
});