import { render, screen, act } from '@testing-library/react' import { describe, it, expect, vi, afterEach } from 'vitest' import { axe } from 'vitest-axe' import { Countdown, CountdownSegment } from './countdown' const BASE = new Date('2026-06-19T00:00:00.000Z').getTime() const SECOND = 1000 function offset({ d = 0, h = 0, m = 0, s = 0 }) { return ((d * 24 + h) * 60 + m) * 60 * SECOND + s * SECOND } afterEach(() => { vi.useRealTimers() }) describe('Countdown', () => { it('breaks a future targetDate into day/hour/minute/second segments', () => { vi.useFakeTimers() vi.setSystemTime(BASE) render( , ) expect(screen.getByText('02')).toBeInTheDocument() expect(screen.getByText('05')).toBeInTheDocument() expect(screen.getByText('10')).toBeInTheDocument() expect(screen.getByText('30')).toBeInTheDocument() }) it('counts down as time passes', () => { vi.useFakeTimers() vi.setSystemTime(BASE) render( , ) expect(screen.getByText('30')).toBeInTheDocument() act(() => { vi.advanceTimersByTime(SECOND) }) expect(screen.getByText('29')).toBeInTheDocument() }) it('fires onComplete once when it reaches zero', () => { vi.useFakeTimers() vi.setSystemTime(BASE) const onComplete = vi.fn() render( , ) expect(onComplete).not.toHaveBeenCalled() act(() => { vi.advanceTimersByTime(3 * SECOND) }) expect(onComplete).toHaveBeenCalledOnce() act(() => { vi.advanceTimersByTime(5 * SECOND) }) expect(onComplete).toHaveBeenCalledOnce() }) it('exposes a timer role', () => { render( , ) expect(screen.getByRole('timer', { name: 'Sale ends in' })).toBeInTheDocument() }) it('forwards className to the root', () => { render( , ) expect(screen.getByRole('timer').className).toContain('custom-class') }) it('passes the parts to a render-prop child', () => { vi.useFakeTimers() vi.setSystemTime(BASE) render({(parts) => {parts.seconds}s left}) expect(screen.getByText('5s left')).toBeInTheDocument() }) }) describe('CountdownSegment', () => { it('renders a standalone value without a Countdown parent', () => { render() expect(screen.getByText('07')).toBeInTheDocument() }) it('zero-pads to minDigits', () => { render() expect(screen.getByText('005')).toBeInTheDocument() }) it('keeps digits in left-to-right order regardless of layout direction', () => { const { container } = render() // The digit roller row is pinned to LTR so numbers never mirror under dir="rtl". expect(container.querySelector('[data-slot="countdown-segment"] [aria-hidden="true"]')).toHaveAttribute( 'dir', 'ltr', ) }) it('has no accessibility violations', async () => { const { container } = render( , ) expect(await axe(container)).toHaveNoViolations() }) })