import { beforeEach, describe, expect, it, vi } from 'vitest'; import { fetchWorksImageTask, submitWorksImageGeneration, WorksImageApiError, } from '@/lib/works-image'; const hostApiFetchMock = vi.hoisted(() => vi.fn()); vi.mock('@/lib/host-api', () => ({ hostApiFetch: (...args: unknown[]) => hostApiFetchMock(...args), })); describe('works image canvas client', () => { beforeEach(() => { hostApiFetchMock.mockReset(); }); it('submits an image generation task using the Works Square image gateway contract', async () => { hostApiFetchMock.mockResolvedValueOnce({ success: true, job: { task_id: 'task_2', status: 'queued', model: 'gpt-image-2', result_urls: [], }, }); await expect(submitWorksImageGeneration({ accessToken: 'access-token', prompt: '未来城市里的儿童编程课海报', aspectRatio: '1:1', quality: 'standard', })).resolves.toEqual({ id: 'task_2', status: 'queued', prompt: '未来城市里的儿童编程课海报', outputUrls: [], error: null, createdAt: undefined, updatedAt: undefined, }); expect(hostApiFetchMock).toHaveBeenCalledWith('/api/works/ai-gateway/images/generations', { method: 'POST', headers: { 'X-NianCode-Access-Token': 'access-token', }, body: JSON.stringify({ prompt: '未来城市里的儿童编程课海报', image_urls: [], size: '1:1', quality: 'medium', resolution: '2K', }), }); }); it('loads a generated image task by task id through the host api proxy', async () => { hostApiFetchMock.mockResolvedValueOnce({ success: true, job: { task_id: 'task_1', status: 'succeeded', result_urls: ['https://example.com/result.png'], }, }); await expect(fetchWorksImageTask('access-token', 'task_1')).resolves.toMatchObject({ id: 'task_1', status: 'succeeded', outputUrls: ['https://example.com/result.png'], }); expect(hostApiFetchMock).toHaveBeenCalledWith('/api/works/ai-gateway/images/tasks/task_1', { headers: { 'X-NianCode-Access-Token': 'access-token', }, }); }); it('throws api errors with upstream status while the server endpoint is still being built', async () => { hostApiFetchMock.mockResolvedValueOnce({ success: false, status: 501, error: 'Works Square image generation endpoint is not ready', }); await expect(fetchWorksImageTask('access-token', 'task_1')).rejects.toMatchObject({ name: 'WorksImageApiError', statusCode: 501, message: 'Works Square image generation endpoint is not ready', }); }); it('exposes an api error class for page-level copy', () => { const error = new WorksImageApiError('生图接口开发中', 501); expect(error.name).toBe('WorksImageApiError'); expect(error.statusCode).toBe(501); expect(error.message).toBe('生图接口开发中'); }); });