import { nextTick, watchEffect } from 'vue'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { useChatImageUploads } from './useChatImageUploads'; const mediaApi = vi.hoisted(() => ({ deleteAgentChatImage: vi.fn(), uploadAgentChatImage: vi.fn(), })); vi.mock('./mediaApi', () => mediaApi); describe('useChatImageUploads', () => { afterEach(() => { vi.restoreAllMocks(); mediaApi.deleteAgentChatImage.mockReset(); mediaApi.uploadAgentChatImage.mockReset(); }); it('reactively exposes the ready state after upload', async () => { let resolveUpload: (value: any) => void = () => undefined; mediaApi.uploadAgentChatImage.mockReturnValue( new Promise((resolve) => { resolveUpload = resolve; }), ); vi.spyOn(URL, 'createObjectURL').mockReturnValue('blob:test-image'); vi.spyOn(URL, 'revokeObjectURL').mockImplementation(() => undefined); const uploads = useChatImageUploads(); const observedStatuses: (string | undefined)[] = []; const stop = watchEffect(() => { observedStatuses.push(uploads.items.value[0]?.status); }); const pending = uploads.addFiles( [new File(['image'], 'test.png', { type: 'image/png' })], { agentId: 'agent-1', mode: 'FORMAL', sessionId: 'session-1' }, ); await nextTick(); resolveUpload({ data: { height: 1, mimeType: 'image/png', name: 'test.png', previewUrl: '/api/v1/agent/media/content?reference=draft%3Atest', size: 5, uploadId: 'upload-1', width: 1, }, errorCode: 0, }); await pending; await nextTick(); stop(); expect(observedStatuses).toContain('uploading'); expect(observedStatuses.at(-1)).toBe('ready'); expect(uploads.uploadIds.value).toEqual(['upload-1']); }); });