f963b73576b5c69915366893da7dfa6afe633456
braney
  Sat Aug 8 14:04:23 2026 -0700
docent: add a tests directory and a browser-free derive mode, refs #37892

tests/ holds Docent scripts that assert with expect:, run by hand with `make
test` rather than by the tree's test target, since each one drives a real
server. Nine of them: the two-request composite split (#37953), hideKids on a
view and on a superTrack, the cCREs expansion that once overran the request
line, addCustomTrack, a 3x run, and the session/loadSession round trip. A
script named *.xfail.docent.yaml is expected to fail, which is how the
hideKids-aimed-at-the-composite trap is pinned rather than only written down,
and how expect: itself is checked.

DOCENT_DERIVE=1 prints what each track: step turns into and stops, with no
browser and no navigation. That derivation is where most of Docent's own
decisions are, and it was previously visible only in the log of a full run.
`make derive` diffs it against baselines in tests/expected/ for the scripts
whose derived set is small enough to be stable.

The track: verb now calls trackRounds() for that derivation instead of doing
it inline. No behaviour change intended; the tests above pass before and after.

Two things the tests turned up, both recorded in tests/README.txt: turning on
anything under a superTrack sends <superTrack>=show and undoes an earlier
hide: all for its other members, and hideKids on a view has to enumerate
leaves, so one such step sends 188 variables in a 6,986-character request.

diff --git src/hg/utils/docent/README.md src/hg/utils/docent/README.md
index b8a475ba67b..7149367b00a 100644
--- src/hg/utils/docent/README.md
+++ src/hg/utils/docent/README.md
@@ -293,30 +293,43 @@
 
 FAST drops the dwells (`pace`, `shotHold`, mouseover holds), moves the cursor in one jump,
 skips the dropdown open/highlight, and records no video, so there is no mp4 to transcode
 either — **24 s** instead of 64 s for BP1. The stills carry the same content; a couple of
 things about them are incidental rather than identical, so build normally for the figures
 you publish:
 
 - the drawn cursor rests wherever the last real action left it, which is not where the
   skipped animation would have left it;
 - a `pinShot:` crop is the bounding box of the image plus the pinned tooltips, so it can
   come out a few pixels taller or shorter.
 
 `DOCENT_TIME=1` prints where the time actually went, slowest step first — worth a look
 before assuming a script is slow for a reason you can fix.
 
+`DOCENT_DERIVE=1` skips the browser altogether and prints what each `track:` step turns
+into — the rounds, and the cart variables in each. That is where Docent's own decisions
+are made, and it answers "what will this send" in about a second instead of a full run:
+
+    DOCENT_DERIVE=1 node docent.js urllen.docent.yaml
+    step 3 track {"cCREs":"hideKids"}
+      round 1 (3 vars): cCREregistry=hide coreCcres=hide encodeCcreCombined=hide
+
+db comes from the top of the file; a script that changes assembly mid-tour is not
+followed, and it says so. `tests/` keeps baselines of this for a few scripts (`make
+derive`), which is what catches a change to the derivation that a rendered page would
+hide.
+
 Two more things that help:
 
 - `make -j6` builds scenarios in parallel. Each run has its own browser, context and cart,
   so they don't interfere; the trackDb cache is written via a temp file and renamed, so
   concurrent runs can't read a half-written one.
 - The trackDb cache holds the *derived* index (a few MB), not hubApi's reply (~30 MB for
   hg38), so it is quick to re-read on every run. It refreshes daily; delete
   `$TMPDIR/docent-tdb-*` to force it.
 
 ## Gotchas
 
 The renderer lints for one YAML trap before it opens a browser: in a flow map a colon
 needs a trailing space, so `{item:name5568747}` parses as the single key
 `"item:name5568747"` and the intended `item:` argument is silently dropped — the verb
 then quietly falls back to a default. Any argument key containing a `:` gets a warning.