import { cleanup, render, screen, within } from '@testing-library/react' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { CmsRouteProvider, type CmsRouteData } from '@/spa/cmsRoute' import About from '@/spa/pages/About' const viewport = vi.hoisted(() => ({ mobile: false, stacked: false })) vi.mock('@/spa/hooks/useIsMobile', () => ({ useIsMobile: (breakpoint = 768) => (breakpoint === 1024 ? viewport.stacked : viewport.mobile), })) vi.mock('next/navigation', () => ({ usePathname: () => '/der-bmp', useRouter: () => ({ push: vi.fn(), replace: vi.fn() }), })) vi.mock('@/spa/components/AwardsGridSection', () => ({ default: () =>
, })) vi.mock('@/spa/components/HomeWinnersSection', () => ({ default: () =>
, })) vi.mock('@/spa/components/TestimonialsSection', () => ({ default: () =>
, })) vi.mock('@/spa/components/ui/munich-skyline-bg', () => ({ default: () => null, })) const aboutRoute: CmsRouteData = { collection: 'pages', doc: { id: 'about-page', slug: 'der-bmp', spaPath: '/der-bmp', about: { prize: { image: { url: '/api/media/file/cms-prize.jpg', alt: 'CMS prize ceremony', focalX: 32, focalY: 68, }, imageAlt: 'Page-owned prize fallback alt', eyebrow: 'CMS prize eyebrow', heading: 'CMS PRIZE\nHEADING', body: [{ text: 'First CMS prize paragraph.' }, { text: 'Second CMS prize paragraph.' }], facts: [ { value: 'A', label: 'Founded' }, { value: 'B', label: 'An intentionally very long CMS-owned fact label that must remain readable', }, { value: 'C', label: 'Independent' }, ], imageLabel: 'CMS-owned prize image caption', }, }, }, } const renderAbout = () => render( , ) describe('/der-bmp prize facts and caption', () => { beforeEach(() => { viewport.mobile = false viewport.stacked = false }) afterEach(() => cleanup()) it('centers three equal fact cells and keeps full-height separators between them', () => { renderAbout() const facts = screen.getByTestId('prize-facts') const cells = within(facts).getAllByTestId('prize-fact') expect(facts.style.display).toBe('grid') expect(facts.style.gridTemplateColumns).toBe('repeat(3, minmax(0, 1fr))') expect(cells).toHaveLength(3) expect(cells.every((cell) => cell.style.minWidth === '0')).toBe(true) expect(cells.every((cell) => cell.style.alignItems === 'center')).toBe(true) expect(cells.every((cell) => cell.style.textAlign === 'center')).toBe(true) expect(cells.slice(0, 2).every((cell) => cell.style.borderRightWidth === '1px')).toBe(true) expect(cells[2]?.style.borderRightStyle).toBe('none') }) it('preserves long CMS fact labels without allowing them to escape their equal cells', () => { renderAbout() const labels = screen.getAllByTestId('prize-fact-label') const longLabel = screen.getByText( 'An intentionally very long CMS-owned fact label that must remain readable', ) expect(labels.map((label) => label.textContent)).toEqual([ 'Founded', 'An intentionally very long CMS-owned fact label that must remain readable', 'Independent', ]) expect(labels.every((label) => label.style.maxWidth === '100%')).toBe(true) expect(labels.every((label) => label.style.overflowWrap === 'anywhere')).toBe(true) expect(longLabel.style.hyphens).toBe('auto') }) it('keeps CMS media, alt text, focal point, and caption in a semantic contrast container', () => { renderAbout() const section = screen.getByTestId('prize-section') const figure = within(section).getByTestId('prize-figure') const image = within(section).getByRole('img', { name: 'CMS prize ceremony' }) const caption = within(section).getByTestId('prize-image-caption') expect(figure.tagName).toBe('FIGURE') expect(caption.tagName).toBe('FIGCAPTION') expect(image.getAttribute('src')).toBe('/api/media/file/cms-prize.jpg') expect(image.style.objectPosition).toBe('32% 68%') expect(caption.textContent).toBe('CMS-owned prize image caption') expect(caption.style.background).toBe('rgba(3, 9, 58, 0.92)') expect(caption.style.color).toBe('rgb(255, 255, 255)') expect(caption.style.borderLeftWidth).toBe('3px') expect(image.compareDocumentPosition(caption) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy() }) it('stacks the image first at tablet width while retaining equal fact structure', () => { viewport.stacked = true renderAbout() const layout = screen.getByTestId('prize-layout') const figure = screen.getByTestId('prize-figure') const copy = screen.getByTestId('prize-copy-panel') expect(layout.getAttribute('data-layout')).toBe('stacked') expect(layout.style.gridTemplateColumns).toBe('1fr') expect(figure.style.order).toBe('1') expect(figure.style.minHeight).toBe('420px') expect(copy.style.order).toBe('2') expect(copy.style.padding).toBe('56px 48px') expect(within(copy).getAllByTestId('prize-fact')).toHaveLength(3) }) it('uses a dedicated mobile caption area without changing CMS copy or media order', () => { viewport.mobile = true viewport.stacked = true renderAbout() const figure = screen.getByTestId('prize-figure') const visual = screen.getByTestId('prize-image-visual') const caption = screen.getByTestId('prize-image-caption') const copy = screen.getByTestId('prize-copy-panel') expect(figure.style.display).toBe('flex') expect(visual.style.minHeight).toBe('280px') expect(caption.style.position).toBe('relative') expect(caption.style.background).toBe('rgb(3, 9, 58)') expect(caption.textContent).toBe('CMS-owned prize image caption') expect(copy.compareDocumentPosition(figure) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy() expect(screen.getByText('First CMS prize paragraph.')).toBeTruthy() expect(screen.queryByText('BMP Preisverleihung · München')).toBeNull() }) })