import { beforeEach, describe, expect, it, vi } from 'vitest'; import { hostApiFetch } from '@/lib/host-api'; import { fetchPromptMuseumEntry, fetchPromptMuseumPage, PromptMuseumApiError, } from '@/lib/image-prompt-museum'; vi.mock('@/lib/host-api', () => ({ hostApiFetch: vi.fn(), })); const hostApiFetchMock = vi.mocked(hostApiFetch); describe('Prompt Museum renderer API boundary', () => { beforeEach(() => { hostApiFetchMock.mockReset(); }); it('requests the server-backed list with a whitelisted, encoded query', async () => { hostApiFetchMock.mockResolvedValueOnce({ success: true, status: 200, data: { items: [], facets: { useCases: [], styles: [], subjects: [] }, nextCursor: null }, }); await fetchPromptMuseumPage({ q: '编辑感 海报', useCase: 'poster', style: 'editorial', subject: 'product', language: 'zh-CN', model: 'gpt-image-2', cursor: 'next cursor', limit: 24, }); expect(hostApiFetchMock).toHaveBeenCalledWith( '/api/works/image-prompt-museum?q=%E7%BC%96%E8%BE%91%E6%84%9F+%E6%B5%B7%E6%8A%A5&use_case=poster&style=editorial&subject=product&language=zh-CN&model=gpt-image-2&cursor=next+cursor&limit=24', ); }); it('encodes detail ids and preserves the server entry', async () => { const entry = { id: 'entry/one', title: '一条灵感' }; hostApiFetchMock.mockResolvedValueOnce({ success: true, status: 200, data: entry }); await expect(fetchPromptMuseumEntry('entry/one')).resolves.toBe(entry); expect(hostApiFetchMock).toHaveBeenCalledWith('/api/works/image-prompt-museum/entry%2Fone'); }); it('keeps structured server errors available to the page', async () => { hostApiFetchMock.mockResolvedValueOnce({ success: false, status: 503, code: 'PROMPT_MUSEUM_UNAVAILABLE', error: '灵感库正在维护', }); await expect(fetchPromptMuseumPage()).rejects.toEqual( expect.objectContaining>({ status: 503, code: 'PROMPT_MUSEUM_UNAVAILABLE', message: '灵感库正在维护', }), ); }); });