forked from OurHike/OurHike
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathliveMap.ts
More file actions
64 lines (61 loc) · 2.71 KB
/
Copy pathliveMap.ts
File metadata and controls
64 lines (61 loc) · 2.71 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
// Waiting for the map, rather than for the div it will be built in.
//
// This is the third time the same race has been written by hand, so it lives
// in one place now. The rule it encodes:
//
// `findByRole('region', { name: /trail map/i })` resolves the moment
// MapView's container div lands in the DOM - which is a commit BEFORE the
// effect that constructs the map runs.
//
// So `MockMap.live[0]` straight after it is a read of an array that is usually
// full and sometimes empty. It wins on a quiet machine and loses under load,
// which makes it the worst kind of test: green when you push it, red on
// somebody else's merge commit.
//
// It has cost three separate debugging sessions:
//
// - #86, `Cannot read properties of undefined (reading 'options')` - green on
// both PR runs, red on the merge.
// - the light/dark work, where one of the two reads in a single test was
// wrapped in `waitFor` and the other was not.
// - #232's map-overlay tests, `Cannot set properties of undefined (setting
// 'sourceIds')`, found by running the whole suite four times in a row
// (#331).
//
// CLAUDE.md already states the general rule these are all instances of: wait
// on something observable that proves the sequence completed, never on a
// longer timeout. A wider `findByText` window would not have saved any of
// them - the map was absent, not late.
import { expect } from 'vitest'
import { screen, waitFor } from '@testing-library/react'
import { MockMap } from './mocks/maplibre-gl'
/**
* The live map, once MapView's effect has actually built it.
*
* `MockMap.live` rather than `MockMap.instances`, deliberately: a map screen
* can build a NEW map and tear the old one down - switching background does
* exactly that, and so does finishing the first-run steps - so the first map
* ever constructed is not reliably the one that is up. Touching it would be
* touching nothing, silently.
*
* That used to happen on every single launch, because the trail lines landing
* from IndexedDB rebuilt the map too. It does not any more
* (App.mapLifecycle.test.tsx), which makes this distinction rarer than it was
* and no less necessary.
*/
export async function liveMap(): Promise<MockMap> {
await waitFor(() => expect(MockMap.live.length).toBeGreaterThan(0))
return MockMap.live[0]
}
/**
* The map screen, up and holding a live map.
*
* The pairing almost every test that touches the canvas actually wants: the
* screen is on, AND the thing it is about exists. Kept together because
* splitting them is precisely how the first half gets awaited and the second
* forgotten.
*/
export async function renderedMap(): Promise<MockMap> {
await screen.findByRole('region', { name: /trail map/i })
return liveMap()
}