e128682fd48d974c0eaa74366087d2be47080bf5 braney Fri Sep 4 11:43:52 2026 -0700 docent: add make preflight, which checks the fixtures a test suite does not own A Docent test that loads a saved session or attaches a hub depends on something outside the tree, and the failure when that thing goes away is silent rather than loud. A session that has been renamed or deleted is not an error: hgTracks answers HTTP 200 with a page titled "Very Early Error" whose body reads "Could not find session NAME for user USER", the page carries no track image, and every noText: assertion on it passes. The run goes green having tested nothing. Verified both ways: a bogus session name passes a test whose only check is noText:, and fails once the script also asserts noText: "Could not find session". preflight.js reads the fixtures out of the scripts themselves -- loadSession:, hub:, addHub:, addCustomTrack: url:, and hubUrl= inside a goto: -- so the list cannot drift from what the scripts actually use. It needs no browser, runs in a couple of seconds, and exits non-zero if anything is unreachable, which is what lets a nightly run tell "the fixtures are gone" from "a bug came back". Checking it against the sessions cited by the tickets in #38252 found four that do not exist on genome-test because they were saved on the RR or on beta, and corrected one I had wrongly called missing: session names store a dash as %2D, so a MySQL LIKE with a literal dash misses them. The HTTP check has no such problem, which is a reason to prefer it over a query against namedSessionDb. refs #37892 #38252 diff --git src/hg/utils/docent/tests/docentTest.mk src/hg/utils/docent/tests/docentTest.mk index cd19e8bf5f3..6a7b08adf14 100644 --- src/hg/utils/docent/tests/docentTest.mk +++ src/hg/utils/docent/tests/docentTest.mk @@ -1,39 +1,50 @@ # Shared rules for a directory of Docent tests. Included by tests/makefile and by # tests/regress/makefile, so both directories run the same code rather than a copy of it. # # An including makefile sets, before the include: # DOCENT path to docent.js from THIS directory (required) +# PREFLIGHT path to preflight.js from THIS directory (required) # PARITY which script `make parity` runs (default: the first one found) # # Everything else -- which scripts are tests, which have derive baselines -- comes from # what is on disk here, so a new *.docent.yaml is picked up with no edit. ifndef DOCENT $(error include docentTest.mk only after setting DOCENT, e.g. DOCENT = ../docent.js) endif +ifndef PREFLIGHT +$(error include docentTest.mk only after setting PREFLIGHT, e.g. PREFLIGHT = ./preflight.js) +endif PW_DIR ?= /hive/groups/browser/uiTest/pw PW_ENV ?= PLAYWRIGHT_BROWSERS_PATH=$(PW_DIR)/browsers NODE_PATH=$(PW_DIR)/node_modules T ?= # `make parity` needs one script that is expected to PASS, so an .xfail one is no use as # the default. An including makefile can name a better one. PASSING := $(filter-out %.xfail,$(patsubst %.docent.yaml,%,$(wildcard *.docent.yaml))) PARITY ?= $(firstword $(PASSING)) TESTS := $(if $(T),$(addsuffix .docent.yaml,$(T)),$(wildcard *.docent.yaml)) -.PHONY: test parity clean +.PHONY: test parity clean preflight + +# The fixtures the scripts here name but do not contain: saved sessions, hub URLs, the +# server itself. No browser, so this is seconds, and it is what separates "the fixtures +# went away" from "a bug came back" -- which are the same red without it. Run it before +# the suite, and on its own as often as you like. +preflight: + @$(PW_ENV) node $(PREFLIGHT) . test: @if [ -z "$(strip $(TESTS))" ]; then \ echo "no *.docent.yaml here -- nothing was tested"; exit 1; fi @fail=0; \ for f in $(TESTS); do \ b=$${f%.docent.yaml}; want=0; \ case $$b in *.xfail) want=1;; esac; \ if [ $$want = 1 ]; then printf '=== %s (expected to fail)\n' "$$b"; \ else printf '=== %s\n' "$$b"; fi; \ $(PW_ENV) node $(DOCENT) $$f > $$b.log 2>&1; got=$$?; \ if [ $$got -ne 0 ] && [ $$want -eq 0 ]; then \ echo " FAILED -- run said:"; sed 's/^/ /' $$b.log; fail=1; \ elif [ $$got -eq 0 ] && [ $$want -eq 1 ]; then \ echo " FAILED -- this was supposed to fail, and it passed"; fail=1; \