Files
ausboss-ComfyUI-AusBoss/docs/live_testing.md
ausboss 8198e8d530 Tests: run the pack against the newest ComfyUI every night
A ComfyUI update can break a node without a line of the pack changing, and
until now nothing looked: CI installs no ComfyUI. A nightly workflow now
installs ComfyUI's newest release and its development head for the CPU and
runs three checks that need no model:

- tests/test_comfy_core_contract.py reads the pack's source for everything
  it takes from ComfyUI (modules, functions, ComfyUI's own nodes it calls
  and the inputs it passes them) and looks each one up in the real thing.
- scripts/compat_boot.py asks a running ComfyUI which nodes it offers:
  every public node of the pack, and every node and required input the
  example workflows use.
- scripts/dev/face_smoke.mjs puts every node on a graph in headless
  Chrome, in both node views, and fails when a face does not come up or
  something throws.

The full Python suite runs there too. A failure on the release opens an
issue; the development head only after two nights in a row.
2026-10-10 22:06:11 -05:00

96 lines
5.6 KiB
Markdown

# Live frontend testing
Frontend work in this pack is proven on a real canvas: a node is created in a
real ComfyUI tab, real mouse drags are dispatched, and the result is a
screenshot a person looks at. Reading the code, or a test that only checks
which input received a link, has let broken designs through before (three
sockets stacked on one pixel passed every automated check). This is the
recipe.
## The pieces
- **ComfyUI** on `http://127.0.0.1:8188` (set `COMFY_URL` to point the
scripts elsewhere), with this repository installed or linked into
`custom_nodes`. A changed `INPUT_TYPES` is served only after a full
restart. Stop the test instance, then start it from the ComfyUI checkout
using that installation's Python environment:
```bash
python main.py --listen 127.0.0.1
```
From this repository, run `python scripts/run_python_tests.py` with the
same environment to isolate ComfyUI stubs and keep CPU thread counts
bounded. Set `AUSBOSS_COMFY_ROOT` to the ComfyUI checkout to enable the
optional core video integration checks.
- **Headless Chrome or Chromium** on an unused CDP port; these examples use
**9334**. Use a separate test profile and the installed browser executable:
```bash
chromium \
--headless=new --remote-debugging-port=9334 --user-data-dir=/tmp/chrome-ausboss \
--window-size=1800,1100 --no-first-run --no-default-browser-check about:blank &
```
- **`scripts/dev/`** — small Node scripts that talk CDP directly, with no
package dependencies. Use a Node version with built-in `fetch` and `WebSocket`:
| script | does |
|---|---|
| `cdp.mjs <port> <workflow.json\|-> <out.png\|-> [eval.js] [waitMs]` | opens/reuses the Comfy tab, optionally loads a workflow, evaluates a JS file, screenshots (a returned `__clip` rect clips the shot), prints the eval result as JSON |
| `cdp_drag.mjs <port> <setup.js> <mid.png\|-> <after.png\|-> [check.js]` | `setup.js` returns `{from, to, __clip}` in client pixels; presses at `from`, moves to `to`, screenshots mid-drag, releases, evaluates `check.js`, screenshots again |
| `audit_workflows.mjs <port> <output-dir> [workflow.json ...]` | loads every example (or selected files), exports API and loaded graphs, captures screenshots, and fails on overlaps, missing nodes, browser exceptions, or exposed AusBoss number widgets |
| `wheel_sweep.mjs <port> [--vue] [--only=Type,Type] [--workflow=file.json] [--shots=dir]` | turns the mouse wheel at every point of every node of the pack (or of the nodes in one workflow) and fails on any spot where the graph does not zoom, naming the element that took the wheel; `--real` sends real wheel turns, slower and on a coarser grid |
| `face_smoke.mjs <port> [--vue] [--only=Type,Type]` | puts one of each node of the pack on an empty graph and fails when a face does not come up: no node, a panel that is not on the page or has no size, an error thrown, a file of the pack that did not load. Needs no model, so it also runs in the nightly ComfyUI check |
| `cdp_nav_debug.mjs <port>` | navigates the tab in place and logs every CDP event, for when a tab stops answering |
| `cdp_hang.mjs <port>` | pre-arms the debugger on a fresh tab, loads ComfyUI, and pauses to print the stack if the page stops answering |
`CDP_RELOAD=1` closes the Comfy tab and opens a fresh one with the cache
cleared — required after editing any `.mjs`, which the frontend caches
hard.
## Screenshot convention
An eval creates the node at `pos [0, 0]`, sets `app.canvas.ds.scale = 1` and
`ds.offset = [160, 230]`, and returns
`__clip: { x: r.left + 152, y: r.top + 192, width: node.size[0] + 16, height: node.size[1] + 46 }`
(`r` is the canvas element's bounding rect). A drag gives two shots: `_mid`,
taken during the drag, and `_after`, the result.
## Gotchas learned the hard way
- **Clearing the graph reuses node ids**, and the frontend's widget store
hands a new node the previous node's widget values (a toggled `preview`
came back `false`). Bump `app.graph.last_node_id += 50` after
`app.graph.clear()`, or set the value you want explicitly.
- **A real mouse drag marks the workflow modified.** The next in-place
navigation raises ComfyUI's `beforeunload` dialog and the whole tab stops
answering every CDP call, even `1+1`; it looks exactly like a renderer
hang. The scripts auto-accept dialogs, and `CDP_RELOAD=1` makes `cdp.mjs`
reload into a fresh tab rather than navigate the old one.
- **Reset a half-finished link drag** (`app.canvas.linkConnector.reset()`)
before clearing the graph in an eval.
- The mid-drag screenshot shows the socket lit and the tooltip, not the
greyed field: the field greys once the link exists, in the `_after` shot.
- Widget input sockets are drawn only while a link is dragged, hovered, or
connected, so a "no socket visible" screenshot at rest is normal; the
mid-drag shot is the one that shows where a link can land.
- `cdp.mjs` and `cdp_drag.mjs` requests time out after 25 s; the workflow
audit allows 45 s.
Inspect the browser's dialogs and logs when a request stops responding.
- Keep test renders and logs out of the repository; only deliberately
shipped sample media belongs in `example_workflows/inputs/`.
## What to verify for a node face
1. The face at rest (values, alignment, no clipped panel).
2. Every group disclosure open.
3. A real link dropped on every row and socket, `_mid` and `_after`.
4. `app.graphToPrompt()` sends the link for a linked input and the typed
value otherwise.
5. Save, reload (fresh tab), and confirm links, values and hidden state.
6. The preview switch on and off where the node has one.
7. The wheel zooms the graph over every part of the face:
`wheel_sweep.mjs`, once plain and once with `--vue`.