Files
pomodoro/src/App.test.tsx
T

82 lines
2.9 KiB
TypeScript

import { act, fireEvent, render, screen } from '@testing-library/react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import App from './App'
import type { CompletionSound } from './features/timer/sound'
function renderApp() {
const sound: CompletionSound = {
prepare: vi.fn(),
play: vi.fn(),
}
render(<App sound={sound} />)
return sound
}
describe('Pomodoro app', () => {
beforeEach(() => {
vi.useFakeTimers()
vi.setSystemTime(new Date('2026-07-22T10:08:00'))
})
afterEach(() => {
vi.useRealTimers()
})
it('shows a live clock and the initial focus timer', () => {
renderApp()
expect(screen.getByLabelText('Current time')).toHaveTextContent('10:08')
expect(screen.getByLabelText('Time remaining')).toHaveTextContent('25:00')
expect(screen.getByText('Focus session')).toBeInTheDocument()
expect(screen.getByText('0 / 4 sessions')).toBeInTheDocument()
})
it('starts, pauses, resumes, and resets the countdown', () => {
const sound = renderApp()
fireEvent.click(screen.getByRole('button', { name: 'Start' }))
expect(sound.prepare).toHaveBeenCalledOnce()
expect(screen.getByRole('button', { name: 'Pause' })).toBeInTheDocument()
act(() => vi.advanceTimersByTime(60_000))
expect(screen.getByLabelText('Time remaining')).toHaveTextContent('24:00')
fireEvent.click(screen.getByRole('button', { name: 'Pause' }))
act(() => vi.advanceTimersByTime(60_000))
expect(screen.getByLabelText('Time remaining')).toHaveTextContent('24:00')
fireEvent.click(screen.getByRole('button', { name: 'Resume' }))
act(() => vi.advanceTimersByTime(1_000))
expect(screen.getByLabelText('Time remaining')).toHaveTextContent('23:59')
fireEvent.click(screen.getByRole('button', { name: 'Reset' }))
expect(screen.getByLabelText('Time remaining')).toHaveTextContent('25:00')
expect(screen.getByRole('button', { name: 'Start' })).toBeInTheDocument()
})
it('announces completion and switches to a short break', () => {
const sound = renderApp()
fireEvent.click(screen.getByRole('button', { name: 'Start' }))
act(() => vi.advanceTimersByTime(25 * 60_000))
expect(sound.play).toHaveBeenCalledOnce()
expect(screen.getByRole('heading', { name: 'Short break' })).toBeInTheDocument()
expect(screen.getByLabelText('Time remaining')).toHaveTextContent('05:00')
expect(screen.getByText('1 / 4 sessions')).toBeInTheDocument()
})
it('lets the user select focus and break segments', () => {
renderApp()
fireEvent.click(screen.getByRole('button', { name: 'Long break' }))
expect(screen.getByLabelText('Time remaining')).toHaveTextContent('15:00')
fireEvent.click(screen.getByRole('button', { name: 'Short break' }))
expect(screen.getByLabelText('Time remaining')).toHaveTextContent('05:00')
fireEvent.click(screen.getByRole('button', { name: 'Focus' }))
expect(screen.getByLabelText('Time remaining')).toHaveTextContent('25:00')
})
})