Add a front-end browser check, so the pages are testable and not just readable
server/smoketest.py proves the API works; nothing proved the PAGES work. That gap
is why users.js, wp-sidenav.js and the extracted console.css shipped unexecuted and
had to be written up as a known issue instead of verified. This closes the gap with
a tool rather than a one-off, so the next front-end change is cheap to check.
tests/cdp.py a minimal DevTools Protocol client — hand-rolled stdlib
WebSocket (handshake, masked frames), browser discovery for
Edge/Chrome across platforms, and process teardown.
tests/browser_check.py the fixture and 71 assertions.
Stdlib only, matching smoketest.py's rule: these have to run on a plain Python
install on whatever machine is to hand. No pip, no Selenium, no node.
Self-contained — it builds a throwaway database, seeds a fixture, starts its own
uvicorn on a free port, drives the browser, and tears everything down. The real
database is never touched. Sessions come from minting a token with the app's own
auth.create_token() rather than scripting the login form.
What it asserts, beyond "no JavaScript errors on boot" (the thing that actually
went unverified): the three role-dependent renderings of the directory, one-line
rows and no sideways scroll, the roles each caller may grant, the project-access
dialog opening and closing, the drawer's open/Escape/scrim/focus/aria behaviour and
its role gating, ?project= carried only onto project-scoped links, and — the reason
this matters most — that admin.html still has its tokens, cards, headings and dense
sticky tables after console.css was lifted out of its inline <style>.
Three things the build had to get right, each learned the hard way:
- Teardown kills the browser's whole process tree AND sweeps anything still
holding the unique temp profile, matched on that path so a browser window the
user has open is never touched. proc.kill() alone left 98 strays.
- Launching retries with a fresh profile and port: a browser can hand off to
another instance and exit rc=0 without ever binding the debugging port.
- Cleanup waits for the server to exit and disposes the harness's own SQLAlchemy
engine before removing the temp directory, or the open SQLite file blocks the
delete and ignore_errors hides it.
The fixture includes an account on a project the super user cannot see, without
which the admin and the super user would see the same number of rows and the
scoping assertion would prove nothing.
Documented in DEPLOYMENT.md next to the smoke test. 71/71 across repeated runs,
leaving no stray processes or temp directories.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -177,6 +177,33 @@ could not start (host unreachable, or credentials missing or rejected). The last
|
||||
kept separate on purpose — "I could not test this" is a different answer from "this is
|
||||
broken", and automation should not treat them alike.
|
||||
|
||||
### Front-end browser check
|
||||
|
||||
`tests/browser_check.py` is the other half: the smoke test proves the API works, this
|
||||
proves the **pages** work. It runs them in headless Edge (or Chrome) over the DevTools
|
||||
Protocol and asserts what only a browser can settle — that each page boots without a
|
||||
JavaScript error, that the role-dependent renderings are right, and that the layout
|
||||
rules the console pages depend on are actually in effect.
|
||||
|
||||
Self-contained: it creates a throwaway SQLite database, seeds a fixture (two projects,
|
||||
an admin, a Project Super User, a plain member, and accounts positioned to exercise
|
||||
in-scope / out-of-scope / invisible), starts its own server on a free port, and tears
|
||||
all of it down. **Your real database is never touched.** Stdlib only.
|
||||
|
||||
```bash
|
||||
python tests/browser_check.py # everything, ~71 checks
|
||||
python tests/browser_check.py --keep-server # leave it up to poke at by hand
|
||||
WP_BROWSER=/path/to/chrome python tests/browser_check.py
|
||||
```
|
||||
|
||||
Same exit codes as the smoke test, including **2** for "no browser found" — a missing
|
||||
browser is not a failing app.
|
||||
|
||||
Run this after any change to `html/users.js`, `html/wp-sidenav.js`, `html/console.css`
|
||||
or `html/admin.js`. It is the check that would have caught a rule lost while
|
||||
`console.css` was being extracted out of `admin.html`, which is a silent, whole-page
|
||||
regression that no server-side test can see.
|
||||
|
||||
Exit code 0 and "ALL PASS" means the API, the Python logic, and SQL are all
|
||||
working. It cleans up after itself (the test project and its SOP/WPs are
|
||||
deleted via cascade); a single tagged test comment remains (there's no comment
|
||||
|
||||
Reference in New Issue
Block a user