test-e2e drove Cypress through act, which fails to start where it cannot
resolve a host address for its artifact server. It now starts Flask and
Cypress in one shell via scripts/run-e2e.sh, so both share a network
namespace; the act path stays available as test-e2e-act.
The script guards the cases that made the old target lie: it aborts when
something already serves the port instead of testing that server, checks
that its own Flask is alive before trusting a response, pins Cypress to
the same origin Flask binds, and drops ELECTRON_RUN_AS_NODE, which VS Code
exports and which makes Cypress' bundled Electron reject its own flags.
30 YAML and 18 JavaScript files had no linter. yamllint runs correctness
rules only, because the repository predates it and its cosmetic findings
would be noise; key-duplicates is the one that earns its keep, since
PyYAML keeps the last of two identical keys without complaining. eslint
runs the recommended set and already found a dead getBoundingClientRect()
call in navigation.js. Both get a CI job so make lint and the workflows
stop diverging.
flask>=3.1 because app.config["TRUSTED_HOSTS"] arrived in 3.1 and an older
Flask accepts the key and ignores it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Move <header> overflow:hidden into body.fullscreen scope and drop the
implicit-vertical-clip overflow-x:auto from .navbar-nav so dropdown
menus can escape the navbar.
- Drive top-level dropdowns through bootstrap.Dropdown (popperConfig
strategy:'fixed'), and add a chooseDirection() helper that toggles
.dropup/.dropdown on the .nav-item based on space above vs below
before each show. Split the navigation.css rules to position the menu
with top:100% or bottom:100% accordingly.
- Mark the dropdown toggle with data-bs-toggle="dropdown" in the
template; cover that with a Jinja-rendered unit test and add Cypress
specs for the header (opens downward) and footer (flips to .dropup)
cases.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>