feat: add fetchTestimonials data function
This commit is contained in:
44
src/data/testimonials.test.ts
Normal file
44
src/data/testimonials.test.ts
Normal file
@@ -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<Testimonial[]>([
|
||||
{ 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' })
|
||||
})
|
||||
})
|
||||
28
src/data/testimonials.ts
Normal file
28
src/data/testimonials.ts
Normal file
@@ -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<Testimonial[]> {
|
||||
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),
|
||||
}))
|
||||
}
|
||||
Reference in New Issue
Block a user