diff --git a/src/components/Footer.test.tsx b/src/components/Footer.test.tsx index 2f6c0fe..a14736a 100644 --- a/src/components/Footer.test.tsx +++ b/src/components/Footer.test.tsx @@ -1,12 +1,44 @@ import { render, screen } from '@testing-library/react' import { MemoryRouter } from 'react-router-dom' -import { describe, it, expect } from 'vitest' +import { describe, it, expect, vi, beforeEach } from 'vitest' + +const singleMock = vi.fn() +const eqMock = vi.fn(() => ({ single: singleMock })) +const selectMock = vi.fn(() => ({ eq: eqMock })) +const fromMock = vi.fn<(table: string) => { select: typeof selectMock }>(() => ({ select: selectMock })) + +vi.mock('../lib/supabase', () => ({ + supabase: { from: (table: string) => fromMock(table) }, +})) +vi.mock('../lib/resolveImageUrl', () => ({ + resolveImageUrl: (path: string) => path, +})) + +const SITE_CONTENT_ROW = { + id: 'default', + hero_headline: 'Vos cheveux, votre couronne', + hero_tagline: 'Coiffures protectrices par Mira', + about_bio: '', + about_portrait_image: '', + contact_email: 'hello@braidsbymira.com', + contact_hours: 'Mar–Sam, 9h à 18h', +} + import Footer from './Footer' describe('Footer', () => { - it('renders contact info and quick links', () => { + beforeEach(() => { + singleMock.mockReset().mockResolvedValue({ data: SITE_CONTENT_ROW, error: null }) + eqMock.mockClear() + selectMock.mockClear() + fromMock.mockClear() + }) + + it('renders contact info and quick links from site content', async () => { render() expect(screen.getAllByText(/braids by mira/i).length).toBeGreaterThan(0) + expect(await screen.findByRole('link', { name: 'hello@braidsbymira.com' })).toHaveAttribute('href', 'mailto:hello@braidsbymira.com') + expect(screen.getByText('Mar–Sam, 9h à 18h')).toBeInTheDocument() expect(screen.getByRole('link', { name: /boutique/i })).toHaveAttribute('href', '/shop') expect(screen.getByRole('link', { name: /règlements/i })).toHaveAttribute('href', '/rules') }) diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index ccd046a..ec02bfc 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -1,7 +1,23 @@ +import { useEffect, useState } from 'react' import { Link } from 'react-router-dom' +import { fetchSiteContent, type SiteContent } from '../data/siteContent' import styles from './Footer.module.css' function Footer() { + const [content, setContent] = useState(null) + + useEffect(() => { + async function load() { + try { + setContent(await fetchSiteContent()) + } catch { + // Footer content is non-critical; leave contact info blank on failure + // rather than surfacing an error on every single page. + } + } + void load() + }, []) + return (