mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-20 05:56:53 +00:00
163 lines
6.2 KiB
TypeScript
163 lines
6.2 KiB
TypeScript
import { fireEvent, render, screen } from '@testing-library/react';
|
|
import { describe, expect, it, vi } from 'vitest';
|
|
import { TripRouteOverviewPanel, TripRouteOverviewPill } from './TripRouteOverview';
|
|
import type { TripRouteOverview } from './useTripRouteOverview';
|
|
|
|
const overview = (over: Partial<TripRouteOverview> = {}): 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(<TripRouteOverviewPill active={false} onToggle={onToggle} />);
|
|
|
|
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(<TripRouteOverviewPill active onToggle={onToggle} />);
|
|
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(<TripRouteOverviewPanel overview={overview()} unit="metric" />);
|
|
expect(screen.getByText('222.5 km')).toBeInTheDocument();
|
|
|
|
rerender(<TripRouteOverviewPanel overview={overview()} unit="imperial" />);
|
|
expect(screen.getByText('138.3 mi')).toBeInTheDocument();
|
|
});
|
|
|
|
it('FE-MAP-TROU-003: names every day, its distance and how it is travelled', () => {
|
|
render(<TripRouteOverviewPanel overview={overview()} unit="metric" />);
|
|
|
|
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(
|
|
<TripRouteOverviewPanel overview={overview({ loading: true })} unit="metric" />
|
|
);
|
|
expect(container.textContent).toContain('…');
|
|
|
|
rerender(<TripRouteOverviewPanel overview={overview()} unit="metric" />);
|
|
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(<TripRouteOverviewPanel overview={overview()} unit="metric" selectedDayId={2} onSelectDay={onSelectDay} />);
|
|
|
|
fireEvent.click(screen.getByText('Coast road'));
|
|
expect(onSelectDay).toHaveBeenCalledWith(2);
|
|
});
|
|
|
|
it('FE-MAP-TROU-006: read-only shells get rows, not buttons', () => {
|
|
render(<TripRouteOverviewPanel overview={overview()} unit="metric" />);
|
|
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(<TripRouteOverviewPanel overview={overview()} unit="metric" />);
|
|
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(<TripRouteOverviewPanel overview={overview()} unit="metric" maxWidth={240} />);
|
|
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(
|
|
<TripRouteOverviewPanel overview={overview({ days: [], totalDistance: 0 })} unit="metric" />
|
|
);
|
|
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(<TripRouteOverviewPanel overview={short} unit="metric" />);
|
|
|
|
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(<TripRouteOverviewPanel overview={running} unit="metric" />);
|
|
|
|
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(<TripRouteOverviewPanel overview={overview({ unroutedLegs: 0 })} unit="metric" />);
|
|
|
|
expect(screen.queryByTestId('trip-overview-unrouted')).toBeNull();
|
|
expect(screen.queryByRole('img', { name: 'map.overview.dayUnrouted' })).toBeNull();
|
|
});
|
|
});
|