@jsenv/navi 0.29.69 → 0.29.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -168,8 +168,12 @@ consistency across the app, not from any single call site.
168
168
  default is right, how one link or one `navTo` overrides what the pair says
169
169
  for the length of a single navigation (`<Link routeTransition>`), marking the page
170
170
  area between fixed bars, and why a pair of routes is animated by
171
- `RouteTravel` or by a route transition but never both. Read it before
172
- animating any navigation.
171
+ `RouteTravel` or by a route transition but never both. It also says why a
172
+ test must wait for the page arriving rather than for its address — a back
173
+ taken before the page has rendered returns to a page that never left, which
174
+ looks exactly like the arriving page failing to load or refresh. Read it
175
+ before animating any navigation, and before believing a symptom that only
176
+ appears once a pair is animated.
173
177
  - `docs/navigation.md` — how to build navigation: declaring routes
174
178
  (`route()` / `setupRoutes()`), when a section is a route of its own rather
175
179
  than a param, search params bound to signals, rendering with `<Route>`,
@@ -4,6 +4,9 @@ When a write touches one item of a list, two questions decide what the user
4
4
  sees: **what goes back to the network**, and **what stays on screen meanwhile**.
5
5
  Getting either wrong turns "pause one row" into a full page reload.
6
6
 
7
+ The same two questions decide what a list does when the user leaves it and
8
+ comes back, which is the second half of this file.
9
+
7
10
  The short answer:
8
11
 
9
12
  - A write that returns the modified item fixes every list containing it, with
@@ -11,6 +14,8 @@ The short answer:
11
14
  - `useAsyncData(action, { loading: true })` keeps returning the previous data
12
15
  while the action re-runs — the list is never taken away unless the component
13
16
  throws it away.
17
+ - On the way back, the **source** decides whether anything is asked again — not
18
+ the navigation, and not a transition playing between the two pages.
14
19
 
15
20
  ## `loading: true` returns the previous value
16
21
 
@@ -173,10 +178,18 @@ it back. It never decides what the page arriving is allowed to ask for. Held by
173
178
  and without a relation on the pair — and walks the way back ten times on each,
174
179
  counting what goes out at every revisit.
175
180
 
176
- So the first thing to check, when a list stops refreshing after a transition was
177
- added, is which row of the table above it is on: a `GET_MANY` list never
178
- refreshed on its own, and what changed is whatever else in the app was doing the
179
- re-read.
181
+ When a list stops refreshing after a transition was added, two things account
182
+ for it, in this order:
183
+
184
+ 1. **The revisit did not happen.** A back taken before the page being opened was
185
+ ever on screen returns to a list that never left, and a page that never left
186
+ has nothing to come back from (see
187
+ [route_transitions.md](./route_transitions.md#waiting-for-a-navigation-the-address-is-not-the-page)).
188
+ This is what an automated walk does by default, and it is the answer far more
189
+ often than the next one.
190
+ 2. **The list is on the first row of the table.** A `GET_MANY` list never
191
+ refreshed on its own; what changed is whatever else in the app was doing the
192
+ re-read.
180
193
 
181
194
  ### Watching what the run asks for
182
195
 
@@ -228,6 +241,9 @@ the first revisit can start refreshing on the first two as soon as a
228
241
 
229
242
  An absence in the trace is a fact too: no line for a revisit means the run never
230
243
  rendered, which is about the list being mounted, not about what it asked for.
244
+ The usual cause is a revisit that never happened — a back taken before the page
245
+ being opened was ever on screen, which returns to a list that never left (see
246
+ [route_transitions.md](./route_transitions.md#waiting-for-a-navigation-the-address-is-not-the-page)).
231
247
 
232
248
  ## `rerunOn`, verb by verb
233
249
 
@@ -290,6 +306,9 @@ runs it again.
290
306
 
291
307
  ## See also
292
308
 
309
+ - [route_transitions.md](./route_transitions.md#waiting-for-a-navigation-the-address-is-not-the-page)
310
+ — why a walk away and back has to wait for the page arriving, and what a list
311
+ does when it did not
293
312
  - [resource.md](./resource.md) — `resource()`, relations, callback return
294
313
  contracts
295
314
  - [resource_dependencies.md](./resource_dependencies.md) — invalidating a
@@ -289,16 +289,60 @@ one app mounted twice, the two mounts differing by a single
289
289
  `defineRouteTransition` line, walked back and forth **ten times each** with what
290
290
  goes to the network counted on every revisit. The loop is the point — a
291
291
  difference that came and went would pass a single comparison often enough to
292
- look like an invariant.
293
-
294
- What the test holds is that shape: pages between fixed bars, a marked area, a
295
- list virtualized against its scroller, held on a row the url names. It is
296
- evidence about the mechanism, not a proof about every application; a page that
297
- loses its revisit only under a movement is worth reporting with the loop above
298
- run against it. See
292
+ look like an invariant. Three decors, chosen to be opposites: a long list
293
+ virtualized against its scroller, the same one held on a row the url names, and
294
+ a one-row list against the document scroller with its count known from
295
+ elsewhere.
296
+
297
+ One thing does make a page lose its revisit under a movement and not without
298
+ one, and it is not about data either: a back taken before the page being opened
299
+ has rendered, which returns to a page that never left. It has its own section
300
+ below. See
299
301
  [list_refresh.md](./list_refresh.md#who-decides-the-re-read--and-who-does-not)
300
302
  for which source refreshes on a revisit and which does not.
301
303
 
304
+ ## Waiting for a navigation: the address is not the page
305
+
306
+ A navigation changes the URL first and the screen after — always. Under a
307
+ transition the gap is wider on purpose: the rendering hold above spans the frame
308
+ the picture is taken in, so for that frame the address says one page and the
309
+ screen still shows the other. That is what makes the picture honest, and it is
310
+ also long enough to be walked through by mistake.
311
+
312
+ So a test that waits on the URL has not waited for anything to happen:
313
+
314
+ ```js
315
+ // ✗ resolves while the page being left is still the page on screen
316
+ await page.getByTestId("game_card").click();
317
+ await page.waitForURL(/\/games\//);
318
+ await page.goBack();
319
+ ```
320
+
321
+ That back does not come back from anywhere. Nothing was unmounted, so nothing
322
+ remounts — the list the user "returns to" is the element that never left, with
323
+ no first load, no revisit, and no re-read (see
324
+ [list_refresh.md](./list_refresh.md#who-decides-the-re-read--and-who-does-not)).
325
+ Every symptom of the arriving page being wrong follows from a walk that never
326
+ took place.
327
+
328
+ Wait for the page instead — anything only it can show:
329
+
330
+ ```js
331
+ await page.getByTestId("game_card").click();
332
+ await expect(page.getByTestId("game_edit_link")).toBeVisible();
333
+ await page.goBack();
334
+ ```
335
+
336
+ The window is **one frame**: the hold is given back inside the view
337
+ transition's callback, which the browser runs at its next rendering
338
+ opportunity. `tests/route_transition_list_revisit/` walks it the wrong way on
339
+ purpose in its last case — under a movement the list that comes back is the same
340
+ DOM element ten times out of ten and asks for nothing, while the same walk
341
+ without a movement is a real one — and the window measured there is a back at 0
342
+ or 8ms losing every round trip, at 16ms losing only the first, and past 64ms
343
+ losing none. No thumb moves in one frame; an automated click continues in the
344
+ same millisecond. This is a testing trap, not a user-facing behaviour.
345
+
302
346
  ## The rest, briefly
303
347
 
304
348
  - Pace: `--navi-route-transition-duration` (CSS, default 300ms) for everyone;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.69",
3
+ "version": "0.29.70",
4
4
  "type": "module",
5
5
  "description": "Library of components including navigation to create frontend applications",
6
6
  "repository": {