mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-18 04:49:13 +00:00
Both shipped in #538 with no interface at all: the bridge could only be configured by editing integrations/mqtt_bridge/bridge_config.json over SSH, and the Pixlet editor was a script you had to know existed. Neither appeared anywhere in the web UI. They are now two sections in the Tools tab. **MQTT bridge.** Service state (installed / running / stopped), install, start, stop and restart, and a form for every setting: broker host and port, username, TLS, command topic, client id, API base, request timeout, on-demand duration and log level. The password is write-only. GET returns every other field plus a password_set flag, never the value -- this interface has no authentication, so anything it hands back is readable by anyone who can reach the port. Submitting a blank password keeps whatever is stored; there is an explicit Clear for removing one. The file is written through a temp file in the same directory and chmod 0600, so a crash mid-write cannot leave a config the bridge would refuse to load. Values are range-checked server-side (port, timeouts, log level, http(s) API base). **Pixlet editor.** Lists the apps on disk and starts a session per app, with a banner showing which app is open, a link to the editor, a countdown, and Stop. The banner survives a page reload because status is polled while a session runs, and Edit is disabled while one is open. Two changes to the script make that safe to drive from a browser: - It binds 0.0.0.0 by default (PIXLET_EDITOR_HOST overrides). Loopback-only meant the URL shown in a browser was unreachable and needed an SSH tunnel, which is the confusing path. The no-auth argument for loopback does not hold when web_interface already serves 0.0.0.0:5000 unauthenticated and can reconfigure everything. - The session ends by itself after PIXLET_EDITOR_TIMEOUT (default 30 min), enforced by `timeout` inside the script rather than by the caller. The display is stopped while editing, so a forgotten session would otherwise leave the panel dark and read as broken hardware -- the timeout is the whole reason a Start button is defensible. Two bugs found while testing that lifecycle, both of which would have bitten the Stop button: - GNU timeout runs its child in a NEW process group, so signalling the script's group killed only bash and orphaned pixlet with the port still bound. Now --foreground keeps one group, and the EXIT trap kills the recorded child too. - The liveness check treated a zombie as running: the script is a child of the web process and stays unreaped after exiting, and signal 0 succeeds against a zombie, so a finished session would have read as running forever. It now reaps non-blockingly and falls back to /proc state for a process that is not ours. Covered by test/js/dom/test_tools_sections.js (26 assertions, real DOM against the server-rendered partial): form prefill, the blank-means-unchanged password contract, the running-session banner and countdown, and that the editor link uses the host the page was loaded from. Also chmod +x on both scripts, which the docs tell you to run directly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014RRtqXDCnvnY6EQwhT5CV9
67 lines
3.7 KiB
Markdown
67 lines
3.7 KiB
Markdown
# Web-interface JS tests
|
|
|
|
Covers `web_interface/static/v3/js/plugins/list_filter.js` (the shared
|
|
search/filter/sort controller) and the plugin-manager grids that use it:
|
|
Installed Plugins, the Plugin Store, and Starlark Apps.
|
|
|
|
There is no JS toolchain in this repo, so these are plain node scripts with no
|
|
test framework. Each prints `ok`/`FAIL` lines and exits non-zero on failure.
|
|
|
|
## Running
|
|
|
|
```bash
|
|
cd test/js
|
|
npm install # jsdom, for the DOM suites only
|
|
node run_all.js
|
|
```
|
|
|
|
The unit suites need nothing but node. The DOM suites additionally need a
|
|
running web interface, because they test against the **real** server-rendered
|
|
HTML and the **real** API rather than fixtures:
|
|
|
|
```bash
|
|
# in another shell, from the repo root
|
|
EMULATOR=true python3 web_interface/app.py # http://localhost:5000
|
|
|
|
# or point the suites at a device
|
|
BASE=http://10.0.10.169:5000 node run_all.js
|
|
```
|
|
|
|
`run_all.js` skips the DOM suites (rather than failing) when jsdom is missing or
|
|
nothing is listening, so it stays useful in a bare checkout.
|
|
|
|
## The suites
|
|
|
|
| Suite | Needs a server | Covers |
|
|
|---|---|---|
|
|
| `unit/test_list_filter.js` | no | `ListFilter` search/filter/sort/count/sticky, and the installed-plugins config **extracted verbatim** from `plugins_manager.js` so the test can't drift from it |
|
|
| `unit/test_render_cards.js` | no | `renderInstalledCards` markup, both empty states, and HTML-escaping of hostile plugin metadata |
|
|
| `dom/test_installed_dom.js` | yes | The toolbar in a real DOM: pill/search/sort interaction, the HTMX partial re-swap, and a `getComputedStyle` check that `.filter-pill[data-active]` really matches the emitted markup |
|
|
| `dom/test_store_dom.js` | yes | Store pagination, per-page, category, tri-state Installed button, and persistence across a re-boot, against the live registry |
|
|
| `dom/test_no_double_fetch.js` | yes | Loads the **whole** `plugins_manager.js` and counts requests: typing in the store search must filter the cached list, not refetch `/api/v3/plugins/store/list` |
|
|
| `dom/test_tools_sections.js` | yes | The Tools tab's MQTT bridge and Pixlet editor sections: form prefill, the write-only password (blank means unchanged), the running-session banner and countdown, and that the editor link points at the host you loaded the page from |
|
|
|
|
Point the DOM suites at a rig with a full plugin set when it matters — a dev box
|
|
with two plugins installed will pass while exercising very little.
|
|
|
|
## Notes for whoever changes this next
|
|
|
|
- The suites read the shipped files off disk and, for the DOM ones, the partial
|
|
from the running server. They do not keep their own copy of the markup, so
|
|
renaming an element id will fail them loudly rather than silently pass.
|
|
- `unit/test_list_filter.js` `eval`s a slice of `plugins_manager.js` located by
|
|
the text `function installedSortName(plugin)`. If that function is renamed,
|
|
fix the slice markers rather than pasting a copy of the config into the test.
|
|
- A few assertions exist specifically to stop earlier bugs coming back:
|
|
trailing spaces surviving the search debounce; a multi-word query that spans
|
|
two adjacent search fields (field order in the haystack is load-bearing);
|
|
`window.installedPlugins` staying at full length while the grid is filtered.
|
|
- Watch for assertions that can pass vacuously. Several here deliberately guard
|
|
against it — e.g. counting only non-skeleton cards, and asserting a search
|
|
phrase matches something before comparing two results.
|
|
|
|
The old-vs-new differential suites used to verify that the store and Starlark
|
|
migrations were behaviour-preserving are not included: they compared against the
|
|
pre-refactor implementation, which now only exists in git history. See PR #540
|
|
if that comparison ever needs redoing.
|