import { describe, it, expect, vi } from 'vitest'; import { PhotoUploadStore } from '../../src/lib/client/photo-upload.svelte'; const validRecipe = { id: null, title: 'T', description: 'D', source_url: null, source_domain: null, image_path: null, servings_default: null, servings_unit: null, prep_time_min: null, cook_time_min: null, total_time_min: null, cuisine: null, category: null, ingredients: [], steps: [{ position: 1, text: 'S' }], tags: [] }; function fakeFetch(responses: Response[]): typeof fetch { let i = 0; return vi.fn(async () => responses[i++]) as unknown as typeof fetch; } function mkFile(): File { return new File([new Uint8Array([1, 2, 3])], 'x.jpg', { type: 'image/jpeg' }); } describe('PhotoUploadStore', () => { it('starts in idle', () => { const s = new PhotoUploadStore(); expect(s.status).toBe('idle'); }); it('transitions loading → success on happy path', async () => { const s = new PhotoUploadStore({ fetchImpl: fakeFetch([ new Response(JSON.stringify({ recipe: validRecipe }), { status: 200 }) ]) }); await s.upload(mkFile()); expect(s.status).toBe('success'); expect(s.recipe?.title).toBe('T'); }); it('transitions to error with code on 422', async () => { const s = new PhotoUploadStore({ fetchImpl: fakeFetch([ new Response( JSON.stringify({ code: 'NO_RECIPE_IN_IMAGE', message: 'nope' }), { status: 422 } ) ]) }); await s.upload(mkFile()); expect(s.status).toBe('error'); expect(s.errorCode).toBe('NO_RECIPE_IN_IMAGE'); }); it('reset() brings store back to idle', async () => { const s = new PhotoUploadStore({ fetchImpl: fakeFetch([new Response('{"code":"X"}', { status: 503 })]) }); await s.upload(mkFile()); expect(s.status).toBe('error'); s.reset(); expect(s.status).toBe('idle'); expect(s.errorCode).toBeNull(); expect(s.lastFile).toBeNull(); }); it('retry re-uploads lastFile', async () => { const s = new PhotoUploadStore({ fetchImpl: fakeFetch([ new Response('{"code":"X"}', { status: 503 }), new Response(JSON.stringify({ recipe: validRecipe }), { status: 200 }) ]) }); await s.upload(mkFile()); expect(s.status).toBe('error'); await s.retry(); expect(s.status).toBe('success'); }); });