import { render, screen, fireEvent } from '@testing-library/react' import { describe, it, expect, vi } from 'vitest' import { TripRouteOverviewPill, TripRouteOverviewPanel } from './TripRouteOverview' import type { TripRouteOverview } from './useTripRouteOverview' const overview = (over: Partial = {}): TripRouteOverview => ({ days: [ { dayId: 1, dayNumber: 1, date: '2025-06-01', title: null, color: { line: '#0a84ff', casing: '#0a5cc2' }, lines: [], segments: [], distance: 82000, duration: 3600, modes: ['driving'] }, { dayId: 2, dayNumber: 2, date: '2025-06-02', title: 'Coast road', color: { line: '#ff9f0a', casing: '#c2740a' }, lines: [], segments: [], distance: 140500, duration: 7200, modes: ['driving', 'walking'] }, ], lines: [], lineColors: [], segments: [], focusPoints: [], totalDistance: 222500, totalDuration: 10800, loading: false, ...over, }) describe('TripRouteOverviewPill', () => { it('FE-MAP-TROU-001: says which way it will take you, and reports its state', () => { const onToggle = vi.fn() const { rerender } = render() const button = screen.getByTestId('trip-overview-pill') expect(button).toHaveAttribute('aria-pressed', 'false') expect(button).toHaveAttribute('aria-label', 'map.overview.show') fireEvent.click(button) expect(onToggle).toHaveBeenCalledTimes(1) rerender() expect(screen.getByTestId('trip-overview-pill')).toHaveAttribute('aria-label', 'map.overview.hide') }) }) describe('TripRouteOverviewPanel', () => { it('FE-MAP-TROU-002: leads with the trip total in the reader\'s own unit', () => { const { rerender } = render() expect(screen.getByText('222.5 km')).toBeInTheDocument() rerender() expect(screen.getByText('138.3 mi')).toBeInTheDocument() }) it('FE-MAP-TROU-003: names every day, its distance and how it is travelled', () => { render() expect(screen.getByText('dayplan.dayN')).toBeInTheDocument() // A day with a title is named by it rather than by its number. expect(screen.getByText('Coast road')).toBeInTheDocument() expect(screen.getByText('82 km')).toBeInTheDocument() expect(screen.getByText('140.5 km')).toBeInTheDocument() }) it('FE-MAP-TROU-004: marks the total as partial while legs are still coming in', () => { const { container, rerender } = render() expect(container.textContent).toContain('…') rerender() expect(container.textContent).not.toContain('…') }) it('FE-MAP-TROU-005: a day row picks that day when the shell offers it', () => { const onSelectDay = vi.fn() render() fireEvent.click(screen.getByText('Coast road')) expect(onSelectDay).toHaveBeenCalledWith(2) }) it('FE-MAP-TROU-006: read-only shells get rows, not buttons', () => { render() expect(screen.queryAllByRole('button')).toHaveLength(0) }) it('FE-MAP-TROU-008: hugs its rows, and takes the cap the shell gives it', () => { const { container, rerender } = render() const card = () => screen.getByTestId('trip-overview-panel') expect(card().style.width).toBe('fit-content') expect(card().style.maxWidth).toBe('320px') // The phone shell asks for a narrower card so the map keeps the space. rerender() expect(card().style.maxWidth).toBe('240px') expect(container).not.toBeEmptyDOMElement() }) it('FE-MAP-TROU-007: draws nothing at all for a trip with no routed day', () => { const { container } = render() expect(container).toBeEmptyDOMElement() }) it('FE-MAP-TROU-009: says when legs could not be routed, and marks the day that is short', () => { // A refused leg stays a straight line and adds nothing to the sum, so a total shown // without a word about it reads as the whole trip when it is not. const days = overview().days const short = overview({ days: [{ ...days[0], unroutedLegs: 1 }, { ...days[1], unroutedLegs: 0 }], unroutedLegs: 1, }) render() expect(screen.getByTestId('trip-overview-unrouted')).toHaveTextContent('map.overview.unrouted') expect(screen.getAllByRole('img', { name: 'map.overview.dayUnrouted' })).toHaveLength(1) }) it('FE-MAP-TROU-010: does not call a leg unrouted while the round is still running', () => { // Every leg still waiting is unrouted too; the ellipsis already says the number grows. const days = overview().days const running = overview({ days: [{ ...days[0], unroutedLegs: 1 }, { ...days[1], unroutedLegs: 1 }], unroutedLegs: 2, loading: true, }) render() expect(screen.queryByTestId('trip-overview-unrouted')).toBeNull() expect(screen.queryByRole('img', { name: 'map.overview.dayUnrouted' })).toBeNull() }) it('FE-MAP-TROU-011: a fully routed trip carries no warning at all', () => { render() expect(screen.queryByTestId('trip-overview-unrouted')).toBeNull() expect(screen.queryByRole('img', { name: 'map.overview.dayUnrouted' })).toBeNull() }) })