diff --git a/src/data/testimonials.test.ts b/src/data/testimonials.test.ts new file mode 100644 index 0000000..9432da3 --- /dev/null +++ b/src/data/testimonials.test.ts @@ -0,0 +1,44 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' + +const orderMock = vi.fn() +const selectMock = vi.fn(() => ({ order: orderMock })) +const fromMock = vi.fn<(table: string) => { select: typeof selectMock }>(() => ({ select: selectMock })) +const resolveImageUrlMock = vi.fn((path: string) => `https://cdn.example/${path}`) + +vi.mock('../lib/supabase', () => ({ + supabase: { from: (table: string) => fromMock(table) }, +})) +vi.mock('../lib/resolveImageUrl', () => ({ + resolveImageUrl: (path: string) => resolveImageUrlMock(path), +})) + +const ROW = { id: 'a1', quote: 'Great!', author: 'Amara T.', avatar_image: 'testimonials/amara.jpg', sort_order: 0 } + +import { fetchTestimonials, type Testimonial } from './testimonials' + +describe('fetchTestimonials', () => { + beforeEach(() => { + orderMock.mockReset() + selectMock.mockClear() + fromMock.mockClear() + resolveImageUrlMock.mockClear() + }) + + it('fetches testimonials ordered by sort_order and maps to the Testimonial shape', async () => { + orderMock.mockResolvedValue({ data: [ROW], error: null }) + + const testimonials = await fetchTestimonials() + + expect(fromMock).toHaveBeenCalledWith('testimonials') + expect(orderMock).toHaveBeenCalledWith('sort_order') + expect(resolveImageUrlMock).toHaveBeenCalledWith('testimonials/amara.jpg') + expect(testimonials).toEqual([ + { id: 'a1', quote: 'Great!', author: 'Amara T.', avatarImage: 'https://cdn.example/testimonials/amara.jpg' }, + ]) + }) + + it('throws when the fetch fails', async () => { + orderMock.mockResolvedValue({ data: null, error: { message: 'network error' } }) + await expect(fetchTestimonials()).rejects.toEqual({ message: 'network error' }) + }) +}) diff --git a/src/data/testimonials.ts b/src/data/testimonials.ts new file mode 100644 index 0000000..c62ccda --- /dev/null +++ b/src/data/testimonials.ts @@ -0,0 +1,28 @@ +import { supabase } from '../lib/supabase' +import { resolveImageUrl } from '../lib/resolveImageUrl' + +export interface Testimonial { + id: string + quote: string + author: string + avatarImage: string +} + +interface TestimonialRow { + id: string + quote: string + author: string + avatar_image: string + sort_order: number +} + +export async function fetchTestimonials(): Promise { + const { data, error } = await supabase.from('testimonials').select('*').order('sort_order') + if (error) throw error + return ((data ?? []) as TestimonialRow[]).map((row) => ({ + id: row.id, + quote: row.quote, + author: row.author, + avatarImage: resolveImageUrl(row.avatar_image), + })) +}