forked from OurHike/OurHike
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStatusStrip.test.tsx
More file actions
236 lines (182 loc) · 9.47 KB
/
Copy pathStatusStrip.test.tsx
File metadata and controls
236 lines (182 loc) · 9.47 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
import { describe, it, expect, afterEach } from 'vitest'
import { render, screen, cleanup } from '@testing-library/react'
import { StatusStrip } from './StatusStrip'
// WIREFRAMES.md, map screen §1: time, GPS/offline state, sync age.
//
// This strip is where the map admits what it doesn't know. WIREFRAMES.md `7b`
// (no GPS fix) and its "loading/empty/error states are first-class" rule both
// land here: going offline or losing the fix is a normal condition on trail,
// not an error, and the strip has to say so plainly rather than silently
// showing a stale position as if it were live.
const AT_NOON = new Date('2026-07-29T12:00:00')
const PROPS = {
time: AT_NOON,
online: true,
hasGpsFix: true,
lastSyncedAt: new Date('2026-07-29T09:00:00'),
}
afterEach(() => {
cleanup()
})
describe('StatusStrip', () => {
it('shows the current time', () => {
render(<StatusStrip {...PROPS} />)
expect(screen.getByText(/12:00/)).toBeInTheDocument()
})
it('says nothing about connectivity while online - no badge for the normal case', () => {
render(<StatusStrip {...PROPS} />)
expect(screen.queryByText(/offline/i)).not.toBeInTheDocument()
})
it('states plainly that it is offline when there is no signal', () => {
render(<StatusStrip {...PROPS} online={false} />)
expect(screen.getByText(/offline/i)).toBeInTheDocument()
})
it('says the GPS fix is lost rather than showing a stale position as if it were live', () => {
render(<StatusStrip {...PROPS} hasGpsFix={false} />)
expect(screen.getByText(/no gps/i)).toBeInTheDocument()
})
it('reports how long ago the data last synced', () => {
render(<StatusStrip {...PROPS} />)
expect(screen.getByText(/3h ago/i)).toBeInTheDocument()
})
it('reports sync age in days once it is past a day old', () => {
render(
<StatusStrip {...PROPS} lastSyncedAt={new Date('2026-07-26T12:00:00')} />, // 3 days
)
expect(screen.getByText(/3d ago/i)).toBeInTheDocument()
})
it('says "just now" for a sync within the last minute', () => {
render(<StatusStrip {...PROPS} lastSyncedAt={new Date('2026-07-29T11:59:30')} />)
expect(screen.getByText(/just now/i)).toBeInTheDocument()
})
it('says the data has never synced rather than leaving the age blank', () => {
render(<StatusStrip {...PROPS} lastSyncedAt={null} />)
expect(screen.getByText(/never synced/i)).toBeInTheDocument()
})
it('announces offline and lost-fix changes politely to assistive tech', () => {
render(<StatusStrip {...PROPS} online={false} hasGpsFix={false} />)
expect(screen.getByRole('status')).toBeInTheDocument()
})
it('says the live map never loaded, which "Offline" cannot say', () => {
// The gap this closes: navigator.onLine is optimistic, so a captive
// portal, a filtered network or an outage at the tile host all read as a
// working connection. For a hiker who has downloaded nothing there is no
// archive underneath either, so the screen is blank paper - and until
// this flag existed, nothing anywhere said why.
render(<StatusStrip {...PROPS} backgroundProblem="live-unreachable" />)
expect(screen.getByText(/no live map/i)).toBeInTheDocument()
})
it('says a download is on the phone and not drawing', () => {
// The sentence #314 exists for. An archive that is present and unreadable
// kept every indicator green - "downloaded" on the card, an honoured
// offline background in the shell - while the map drew nothing, and the
// hiker had no way to connect the blank paper to the download.
render(<StatusStrip {...PROPS} backgroundProblem="download-not-drawing" />)
expect(screen.getByText(/downloaded map not drawing/i)).toBeInTheDocument()
})
it('says offline that there is no download to draw, beside "Offline"', () => {
// The other half of #314, and the reason this is no longer suppressed
// while offline. "Offline" says the phone has no connection; it does not
// say the download is the missing half - which is what someone who
// deleted the hiking sheet an hour ago actually needs told.
render(<StatusStrip {...PROPS} online={false} backgroundProblem="nothing-to-draw" />)
expect(screen.getByText(/no downloaded map/i)).toBeInTheDocument()
expect(screen.getByText(/offline/i)).toBeInTheDocument()
})
it('says when the trail line itself is not on the map', () => {
// Every other flag here is about the sheet UNDER the trail, and a hiker
// who loses the sheet still has the line they are walking. This is the
// one that says the line is gone - the state that read, to the person who
// reported it, as "the centerline isn't showing".
render(<StatusStrip {...PROPS} trailLinesMissing />)
expect(screen.getByText(/no trail line/i)).toBeInTheDocument()
})
it('says the trail line is missing even while the background is failing too', () => {
// Unlike the two readings of one blank screen below, these are two
// different things absent. Told only "No live map", a hiker would
// reasonably conclude the trail is under it somewhere.
render(
<StatusStrip {...PROPS} backgroundProblem="live-unreachable" trailLinesMissing />,
)
expect(screen.getByText(/no live map/i)).toBeInTheDocument()
expect(screen.getByText(/no trail line/i)).toBeInTheDocument()
})
it('stays quiet about the trail line when there is one', () => {
render(<StatusStrip {...PROPS} backgroundProblem="live-unreachable" />)
expect(screen.queryByText(/no trail line/i)).not.toBeInTheDocument()
})
it('drops "nothing downloaded yet" when the background has a real problem', () => {
// Two flags for one blank screen, and the reassuring one reads first:
// the override describes what the app is TRYING to draw, the problem what
// is actually arriving.
render(
<StatusStrip
{...PROPS}
online={false}
backgroundOverride="nothing-downloaded"
backgroundProblem="nothing-to-draw"
/>,
)
expect(screen.queryByText(/nothing downloaded yet/i)).not.toBeInTheDocument()
expect(screen.getByText(/no downloaded map/i)).toBeInTheDocument()
})
it('says when Data Saver is the reason the live map is missing', () => {
// lib/dataSaver.ts's rule is that the app may override a preference and
// may not do it silently. Settings said so; the map screen did not, and
// the map screen is where the override is actually visible - as nothing
// at all, on a phone with no download.
render(<StatusStrip {...PROPS} backgroundOverride="data-saver" />)
expect(screen.getByText(/data saver/i)).toBeInTheDocument()
})
it('says the live map is standing in for a download that is not there yet', () => {
// The opposite reason, and it must not borrow the Data Saver words: here
// the app is fetching tiles rather than withholding them.
render(<StatusStrip {...PROPS} backgroundOverride="nothing-downloaded" />)
expect(screen.getByText(/nothing downloaded yet/i)).toBeInTheDocument()
expect(screen.queryByText(/data saver/i)).not.toBeInTheDocument()
})
it('stays quiet about the background when nothing is wrong with it', () => {
render(<StatusStrip {...PROPS} />)
expect(screen.queryByText(/no live map/i)).not.toBeInTheDocument()
expect(screen.queryByText(/data saver/i)).not.toBeInTheDocument()
})
it('says when the view is zoomed out past what the download covers', () => {
// #216. Without this the app draws paper and offers no account of itself,
// which is exactly how a complete 314 MB download came to be reported as
// "no data downloaded".
render(<StatusStrip {...PROPS} belowArchiveZoom />)
expect(screen.getByText(/zoomed out past your download/i)).toBeInTheDocument()
})
it('does not call that an override, because nothing was overridden', () => {
// The chosen background IS what is drawn; it simply has no tiles at this
// scale. Borrowing either override's wording would be the quiet mismatch
// lib/dataSaver.ts exists to prevent, one condition further along.
render(<StatusStrip {...PROPS} belowArchiveZoom />)
expect(screen.queryByText(/data saver/i)).not.toBeInTheDocument()
expect(screen.queryByText(/nothing downloaded yet/i)).not.toBeInTheDocument()
})
it('stays quiet while the download does cover the view', () => {
render(<StatusStrip {...PROPS} />)
expect(screen.queryByText(/zoomed out past/i)).not.toBeInTheDocument()
})
})
describe('how old the closures are', () => {
it('says nothing when the closures came from a live read', () => {
// A caveat on data that has none teaches people to ignore caveats, which
// costs more than it buys the one time the caveat matters.
render(<StatusStrip {...PROPS} conditionsAge={null} />)
expect(screen.queryByText(/Conditions as of/)).toBeNull()
expect(screen.queryByText(/conditions unavailable/i)).toBeNull()
})
it('says how old a published baseline is', () => {
render(<StatusStrip {...PROPS} conditionsAge="Conditions as of 6h ago" />)
expect(screen.getByText('Conditions as of 6h ago')).toBeTruthy()
})
it('says conditions are unavailable rather than showing a reassuring blank', () => {
// The #249 fix as a hiker meets it. Before this, neither source being
// reachable rendered exactly like a stretch of trail with nothing closed
// on it - the strip is where those two stop looking identical.
render(<StatusStrip {...PROPS} conditionsAge="Trail conditions unavailable" />)
expect(screen.getByText('Trail conditions unavailable')).toBeTruthy()
})
})