forked from OurHike/OurHike
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHeader.test.tsx
More file actions
104 lines (81 loc) · 3.9 KB
/
Copy pathHeader.test.tsx
File metadata and controls
104 lines (81 loc) · 3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import { describe, it, expect, vi, afterEach } from 'vitest'
import { render, screen, cleanup } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { Header } from './Header'
// WIREFRAMES.md, map screen §2 - the header is a READ-ONLY zone. Trail + state
// eyebrow, current mile + direction in mono, and on the right exactly two 38px
// icon buttons: legend then search. The doc's words are "Nothing else lives
// here," which is a real constraint worth a regression test - the header is
// prime screen space and the obvious place for scope to creep.
const PROPS = {
trailName: 'Appalachian Trail',
state: 'Virginia',
// Already decided by the shell since #312 - what the line SAYS, and which
// of eight situations it is saying it about, is lib/positionLine.ts's job
// and is tested there. What is left here is that the header renders it.
position: 'mi 1,407.2 · NOBO',
onOpenLegend: vi.fn(),
onOpenSearch: vi.fn(),
}
afterEach(() => {
cleanup()
vi.clearAllMocks()
})
describe('Header', () => {
it('names the trail and the state in the eyebrow', () => {
render(<Header {...PROPS} />)
expect(screen.getByText(/Appalachian Trail/)).toBeInTheDocument()
expect(screen.getByText(/Virginia/)).toBeInTheDocument()
})
it('renders the position line it is handed, in the mono slot', () => {
render(<Header {...PROPS} />)
// "mi 1,407.2 · NOBO" - thousands separator, one decimal place.
expect(screen.getByText('mi 1,407.2 · NOBO')).toBeInTheDocument()
})
it('renders a settled state in the same slot, without dressing it up', () => {
// The half of #312 this component owns. It used to render "Looking for
// GPS…" for every mile-less state, including three that never resolve, so
// the words could not be told apart from here. Now the slot says whatever
// the shell decided - and this test is what keeps it from growing its own
// opinion about which of those states deserves the mono slot.
render(<Header {...PROPS} position="Location is off" />)
expect(screen.getByText('Location is off')).toBeInTheDocument()
expect(screen.queryByText(/Looking for GPS/)).not.toBeInTheDocument()
})
it('has no trail logo when none is given', () => {
const { container } = render(<Header {...PROPS} />)
expect(container.querySelector('.map-header__trail-logo')).toBeNull()
})
it("renders the trail's own mark to the left of its name when one is given", () => {
const { container } = render(<Header {...PROPS} trailLogo="/at-logo.svg" />)
const logo = container.querySelector('.map-header__trail-logo')
expect(logo).toHaveAttribute('src', '/at-logo.svg')
// Decorative - the eyebrow text already names the trail in words.
expect(logo).toHaveAttribute('alt', '')
})
it('offers exactly two buttons - legend, then search - and nothing else', () => {
render(<Header {...PROPS} />)
const buttons = screen.getAllByRole('button')
expect(buttons).toHaveLength(2)
expect(buttons[0]).toHaveAccessibleName(/legend/i)
expect(buttons[1]).toHaveAccessibleName(/search/i)
})
it('opens the legend when the legend button is pressed', async () => {
const user = userEvent.setup()
render(<Header {...PROPS} />)
await user.click(screen.getByRole('button', { name: /legend/i }))
expect(PROPS.onOpenLegend).toHaveBeenCalledTimes(1)
expect(PROPS.onOpenSearch).not.toHaveBeenCalled()
})
it('opens search when the search button is pressed', async () => {
const user = userEvent.setup()
render(<Header {...PROPS} />)
await user.click(screen.getByRole('button', { name: /search/i }))
expect(PROPS.onOpenSearch).toHaveBeenCalledTimes(1)
expect(PROPS.onOpenLegend).not.toHaveBeenCalled()
})
it('is a banner landmark, so the read-only zone is skippable by screen reader', () => {
render(<Header {...PROPS} />)
expect(screen.getByRole('banner')).toBeInTheDocument()
})
})