Lane sizes and the window margin become tokens; toolbars wrap by default; windows are capped to the viewport; a ratchet test stops element CSS gaining literal pixel sizes. app/e2e runs the real app in Chromium and Firefox at eight screen sizes (npm run test:viewport). docs/ui-design-guidelines.md gains "Responsive by construction".
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
`node --test` has no timeout by default. Two revert-checks left runs wedged on
session.test.js for forty minutes with no output and no way to tell from the
outside whether they were working or stuck.
ComfyUI's own queue and its own socket, not a second one alongside them. A
FunPack queue would be a second thing tracking what is running, and the one the
user believes is whichever spoke last -- so this speaks to /prompt, /interrupt
and /ws as any ComfyUI client does and holds only a view of the server's state.
The graph is asked for, never assembled here, for the same reason.
The client id is remembered: ComfyUI addresses progress to the client that
queued the run, so a reload with a fresh id hears nothing about the generation
already in flight -- the run continues, the GPU time is spent, and the app says
Ready.
Faults found on the way, each in code that already had passing tests:
* `[hidden]` was inert across the whole kit. The UA rule is element-level, so
`.cx-btn { display: inline-flex }` beats it -- Cancel was marked hidden, sat
there, and nothing reported anything. jsdom cannot see it: the attribute was
always correct. One reset rule, and a browser test over four element kinds.
* A panel passed no height to its body and a split pane passed none to its
panes, so the viewer asked for 100% of `auto` and collapsed to a single line
inside a panel that was the right size around it.
* subscribe() delivered the first state outside the guard every later delivery
gets, so one bad listener took down whoever was wiring the UI up -- at
startup, before anything existed to report it.
* A whole tests directory was never run: the test script globbed
composer/tests only. `node --test` discovers them itself now, so there is no
list to forget.
* `empty` was not in the content rule's key list, so three elements were never
asked to prove their empty-state text comes back as text rather than markup.
The dev server now mounts the REAL routes -- register() already took a route
table -- instead of reimplementing them over http.server. It answered POST
/api/pipeline with 501, so the edit-and-queue path could not be looked at, which
is the one thing the dev server exists for.
The plan asked for jsdom AND Playwright from the start and only jsdom was
ever built. jsdom has no layout engine: getBoundingClientRect answers zeros,
container queries never fire, a theme is an attribute rather than a computed
cascade. So every claim about POSITION or SIZE in this kit was unchecked, and
the unit suite could not have noticed either of these.
A popover bounded its height and not its width. `max-height: 60vh` was there
from the start; there was no max-inline-size at all, so a long unbroken
string -- a file path, a model filename -- made the popover wider than the
screen and anchor.js could not save it: it can move a box, not shrink one.
Measured at 1436px inside a 1280px viewport, off the right edge in all four
corners.
A horizontal split could not fit a narrow screen. The first pane carries an
inline size and `flex: 0 0 auto`, so it would not shrink, and the page
scrolled sideways at 360px -- 407px of content in a 360px viewport. It wraps
now, which stacks the panes, rather than a media query: the kit sizes itself
from its container and not from the window.
Nine layout tests: every overlay corner, an overlay taller than the viewport,
both themes resolving every token they use, light actually being lighter than
dark, and no horizontal scrollbar at five widths. `npm run test:all` runs both
suites.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
register/zlayer/anchor/motion/density are pure cores over plain data, so most of
the suite runs with no DOM at all; jsdom covers only what is genuinely DOM.
100 tests, zero elements.
These five are why v4 had 11 hand-built modals and 7 hand-built popovers: there
was nothing shared to reuse. register makes an element exist only because a file
defined it; portal gives every overlay one stacking parent; zlayer owns the only
z-index in the app; dismiss keeps one stack so Escape pops the top and not the
modal underneath; anchor measures, flips and clamps once.
Three bugs the tests found: unmount() called removeChild on null when no portal
existed yet, focusables() checked aria-hidden on the element instead of its
ancestors so a hidden subtree stayed tab-reachable, and the density ratios v4
hand-tuned are now derived from the gap they were meant to allow for.