import { describe, it, expect, vi, beforeEach } from 'vitest'; vi.mock('$env/dynamic/private', () => ({ env: { BACKEND_URL: 'http://localhost:8080' } })); const mockGet = vi.fn(); const mockPost = vi.fn(); vi.mock('$lib/server/api', () => ({ apiClient: () => ({ GET: mockGet, POST: mockPost }) })); describe('new recipe page — load', () => { let load: any; beforeEach(async () => { mockGet.mockReset(); mockPost.mockReset(); vi.resetModules(); const mod = await import('./+page.server'); load = mod.load; }); const mockTags = [ { id: 't1', name: 'Pasta', tagType: 'category' }, { id: 't2', name: 'Fleisch', tagType: 'category' } ]; it('fetches tags from GET /v1/tags', async () => { mockGet.mockResolvedValue({ data: mockTags, error: undefined }); await load({ fetch: vi.fn() } as any); expect(mockGet).toHaveBeenCalledWith('/v1/tags', expect.anything()); }); it('returns categories filtered from tags', async () => { mockGet.mockResolvedValue({ data: mockTags, error: undefined }); const result = await load({ fetch: vi.fn() } as any); expect(result.categories).toHaveLength(2); expect(result.categories[0].name).toBe('Pasta'); }); it('returns empty categories when API fails', async () => { mockGet.mockResolvedValue({ data: undefined, error: { status: 500 } }); const result = await load({ fetch: vi.fn() } as any); expect(result.categories).toEqual([]); }); it('returns null recipe for new form', async () => { mockGet.mockResolvedValue({ data: mockTags, error: undefined }); const result = await load({ fetch: vi.fn() } as any); expect(result.recipe).toBeNull(); }); }); describe('new recipe page — create action', () => { let actions: any; const makeFormData = (overrides: Record = {}) => { const base: Record = { name: 'Test Rezept', effort: 'Easy', tagIds: ['t1'], ingredientsJson: '[]', stepsJson: '[]', ...overrides }; const fd = new FormData(); for (const [key, val] of Object.entries(base)) { if (Array.isArray(val)) { for (const v of val) fd.append(key, v); } else { fd.append(key, val); } } return fd; }; beforeEach(async () => { mockGet.mockReset(); mockPost.mockReset(); vi.resetModules(); const mod = await import('./+page.server'); actions = mod.actions; }); it('returns fail(422) when name is missing', async () => { const result = await actions.create({ request: { formData: async () => makeFormData({ name: '' }) }, fetch: vi.fn() } as any); expect(result.status).toBe(422); }); it('returns fail(422) when effort is missing', async () => { const result = await actions.create({ request: { formData: async () => makeFormData({ effort: '' }) }, fetch: vi.fn() } as any); expect(result.status).toBe(422); }); it('returns fail(422) when effort is not a valid value', async () => { const result = await actions.create({ request: { formData: async () => makeFormData({ effort: 'InvalidEffort' }) }, fetch: vi.fn() } as any); expect(result.status).toBe(422); }); it('returns fail(422) when no tagIds', async () => { const result = await actions.create({ request: { formData: async () => makeFormData({ tagIds: [] }) }, fetch: vi.fn() } as any); expect(result.status).toBe(422); }); it('returns fail(400) when ingredientsJson is invalid JSON', async () => { const result = await actions.create({ request: { formData: async () => makeFormData({ ingredientsJson: 'not-json' }) }, fetch: vi.fn() } as any); expect(result.status).toBe(400); }); it('returns fail(400) when stepsJson is invalid JSON', async () => { const result = await actions.create({ request: { formData: async () => makeFormData({ stepsJson: '{broken' }) }, fetch: vi.fn() } as any); expect(result.status).toBe(400); }); it('calls POST /v1/recipes with correct body on success', async () => { mockPost.mockResolvedValue({ error: undefined }); const fd = makeFormData({ ingredientsJson: JSON.stringify([{ name: 'Spaghetti', quantity: 200, unit: 'g' }]), stepsJson: JSON.stringify(['Kochen']) }); await actions.create({ request: { formData: async () => fd }, fetch: vi.fn() } as any).catch( () => {} ); expect(mockPost).toHaveBeenCalledWith('/v1/recipes', expect.objectContaining({ body: expect.objectContaining({ name: 'Test Rezept', effort: 'Easy' }) })); }); it('returns fail(500) when API returns error', async () => { mockPost.mockResolvedValue({ error: { status: 500 } }); const result = await actions.create({ request: { formData: async () => makeFormData() }, fetch: vi.fn() } as any); expect(result.status).toBe(500); }); });