From a25286e385fec95f304fb3c9eb83dfb48a8df31e Mon Sep 17 00:00:00 2001 From: Marcel Raddatz Date: Fri, 3 Apr 2026 09:45:43 +0200 Subject: [PATCH] feat(recipes): load recipe list from API in page server Co-Authored-By: Claude Sonnet 4.6 --- .../src/routes/(app)/recipes/+page.server.ts | 21 +++++++++ .../routes/(app)/recipes/page.server.test.ts | 45 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 frontend/src/routes/(app)/recipes/+page.server.ts create mode 100644 frontend/src/routes/(app)/recipes/page.server.test.ts diff --git a/frontend/src/routes/(app)/recipes/+page.server.ts b/frontend/src/routes/(app)/recipes/+page.server.ts new file mode 100644 index 0000000..bff4ccb --- /dev/null +++ b/frontend/src/routes/(app)/recipes/+page.server.ts @@ -0,0 +1,21 @@ +import type { PageServerLoad } from './$types'; +import { apiClient } from '$lib/server/api'; + +export const load: PageServerLoad = async ({ fetch }) => { + const api = apiClient(fetch); + const { data, error } = await api.GET('/v1/recipes', {}); + + if (error || !data?.data) { + return { recipes: [] }; + } + + return { + recipes: data.data.map((r) => ({ + id: r.id!, + name: r.name!, + cookTimeMin: r.cookTimeMin, + effort: r.effort, + heroImageUrl: r.heroImageUrl + })) + }; +}; diff --git a/frontend/src/routes/(app)/recipes/page.server.test.ts b/frontend/src/routes/(app)/recipes/page.server.test.ts new file mode 100644 index 0000000..50c1358 --- /dev/null +++ b/frontend/src/routes/(app)/recipes/page.server.test.ts @@ -0,0 +1,45 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; + +vi.mock('$env/dynamic/private', () => ({ + env: { BACKEND_URL: 'http://localhost:8080' } +})); + +const mockGet = vi.fn(); +vi.mock('$lib/server/api', () => ({ + apiClient: () => ({ GET: mockGet }) +})); + +describe('recipe library page — load', () => { + let load: any; + + beforeEach(async () => { + mockGet.mockReset(); + vi.resetModules(); + const mod = await import('./+page.server'); + load = mod.load; + }); + + const mockRecipes = [ + { id: 'r1', name: 'Spaghetti', cookTimeMin: 30, effort: 'Easy' }, + { id: 'r2', name: 'Curry', cookTimeMin: 45, effort: 'Medium' } + ]; + + it('fetches recipes from GET /v1/recipes', async () => { + mockGet.mockResolvedValue({ data: { data: mockRecipes }, error: undefined }); + await load({ fetch: vi.fn() } as any); + expect(mockGet).toHaveBeenCalledWith('/v1/recipes', expect.any(Object)); + }); + + it('returns recipes in data', async () => { + mockGet.mockResolvedValue({ data: { data: mockRecipes }, error: undefined }); + const result = await load({ fetch: vi.fn() } as any); + expect(result.recipes).toHaveLength(2); + expect(result.recipes[0].name).toBe('Spaghetti'); + }); + + it('returns empty array when API fails', async () => { + mockGet.mockResolvedValue({ data: undefined, error: { status: 500 } }); + const result = await load({ fetch: vi.fn() } as any); + expect(result.recipes).toEqual([]); + }); +});