6f3f3596f3dc61a8a738717b9701e69a86b5bb0b
braney
  Mon Sep 21 17:24:33 2026 -0700
docent: wait: {gone:} for a selector to leave, and rm38257 stops racing itself

rm38257 went red in the 2026-09-21 nightly with the #38257 fix still live on
genome-test.  The script was waiting on the wrong half of the click.

hgHubConnect.js switches the tab synchronously inside the click dispatch, while
topLinks.js closes the Account popup from a setTimeout(..., 0).  So the tab is
the half that settles FIRST, and waiting for it returned a tick early: the
expect after it read a page that still had the popup on it.  Measured with a
MutationObserver over the click, the tab goes active at t=43ms and the popup
goes on the next task.

wait: now also takes {gone: <selector>}, which waits for a selector to leave the
DOM, so a script can wait on the vanishing half of an answer.  rm38257 uses it.

Six runs each way on genome-test, same build, only the script differing: 6 of 6
green with the new wait:, 3 of 6 red with the old one, failing at the same step
with the same message the nightly printed.  The whole directory is green, 98 of
98.

refs #37892, refs #38252

diff --git src/hg/utils/docent/tests/regress/rm38257.docent.yaml src/hg/utils/docent/tests/regress/rm38257.docent.yaml
index 2d838d21231..0578d254056 100644
--- src/hg/utils/docent/tests/regress/rm38257.docent.yaml
+++ src/hg/utils/docent/tests/regress/rm38257.docent.yaml
@@ -24,50 +24,59 @@
 # signed-in reader, so there is no way to reach it otherwise.  `login:` takes no credentials
 # and reads ~/.docentLogin, one section per hgcentral database; genome-test reads
 # hgcentraltest, and `make preflight` reports the account it resolved.  Anyone without that
 # file fails this one script at the login step, which is why it is worth saying here rather
 # than leaving the next reader to work it out from a red run.
 # NOT YET WATCHED TO FAIL, and the reason is the login rather than the check.  Run against
 # ticket sandbox 38252 (master with this batch's fixes reverted), the script dies at its
 # first step: `login` fails with "Execution context was destroyed, most likely because of a
 # navigation", reproducibly, twice.  That is the hgLogin redirect race the docent README
 # calls a standing open item -- hgLogin answers a good password with returnToURL(150), a
 # page that navigates itself -- and it does not happen against genome-test.  So this is the
 # one script in the batch whose A/B is blocked by the harness, not by the tree.  The same
 # thing happens against the v503 park (38316), so it is the park and not the build.
 proof:
   - "assertion-only 2026-09-17 -- written from #38257 and 7d0ceafa7c0 after the fix reached genome-test"
+  - "assertion-only 2026-09-21 -- the wait: was on the wrong half and the script raced itself; put the old wait: back and it goes red on genome-test, with the fix in place"
 
 target: genome-test
 db: hg38
 # Wide enough to be outside nice_menu.css's @media (max-width: 1100px) rule, which folds the
 # top-right links into the hamburger and makes #loginLink invisible.  Docent's default
 # viewport is 1000px, which is inside it.
 size: [1400, 900]
 reset: true
 fast: true
 steps:
   - login: true
   - goto: "/cgi-bin/hgHubConnect?db=hg38"
   - expect:
       text: "Connected Hubs"
       has: '#loginLink[data-username]'
       noText: "My Track Hubs"
 
   # Open the Account popup.  #loginLink has href='#' and a handler; the popup is built here.
   - click: '#loginLink'
   - expect:
       text: "Signed in as"
       has: 'a:has-text("My Track Hubs")'
 
   # The link that used to do neither of the two things it should.
   - click: 'a:has-text("My Track Hubs")'
-  # The popup closes on the next tick, after the click has been fully dispatched, so wait
-  # for the half that settles last rather than sleeping.
-  - wait: 'li.ui-tabs-active a[href="#unlistedHubs"]'
+  # Wait for the POPUP to go, not for the tab to arrive.  The two halves do not settle in
+  # the order this script first assumed: hgHubConnect.js switches the tab synchronously
+  # inside the click dispatch, while topLinks.js closes the popup from a
+  # setTimeout(..., 0), so the tab is the half that settles FIRST.  Waiting for it returned
+  # a tick early, the expect below read a page that still had the popup on it, and the
+  # script failed about half the time on a build with the fix in it -- 2026-09-19 and 09-20
+  # green, 09-21 red, then two of three reds on a re-run the same morning.  Measured with a
+  # MutationObserver over the click: tab active at t=43ms, popup gone on the next task.
+  # "My Track Hubs" is the popup's own string, as the header says, so its removal is the
+  # popup's removal.
+  - wait: {gone: 'text=My Track Hubs'}
   - expect:
       # The tab really did switch: hgHubConnect.js saw the click.
       has: 'li.ui-tabs-active a[href="#unlistedHubs"]'
       # ...and the popup is off the page.  Both strings it printed are gone.
       noText: ["Signed in as", "My Track Hubs"]
       # Still on hgHubConnect: the click was answered in place, not by a reload.
       url: hgHubConnect