171 lines
6.2 KiB
TypeScript
171 lines
6.2 KiB
TypeScript
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: () => <section data-testid="awards-stub" />,
|
|
}))
|
|
|
|
vi.mock('@/spa/components/HomeWinnersSection', () => ({
|
|
default: () => <section data-testid="winners-stub" />,
|
|
}))
|
|
|
|
vi.mock('@/spa/components/TestimonialsSection', () => ({
|
|
default: () => <section data-testid="testimonials-stub" />,
|
|
}))
|
|
|
|
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(
|
|
<CmsRouteProvider value={aboutRoute}>
|
|
<About />
|
|
</CmsRouteProvider>,
|
|
)
|
|
|
|
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()
|
|
})
|
|
})
|