Skip to content

Test gaps after the browser suite landed: picker paths, node-grid surfaces, PIL-stub blind spot #86

Description

@laurigates

Re-scoped 2026-08-16. §1 is closed — the browser suite it asked for landed in #107. What follows is what actually survives, re-verified against HEAD rather than carried over.

Measured at f819981: pytest 296, vitest 147 (9 files), Playwright 17.

§1 — CLOSED by #107 (f2ed146)

tests/e2e/ exists: stdlib-only stub server (server.mjs) serving the built web/dist/index.js at its real extension URL plus /gallery_loader/{base,list,thumb,file,pins} with real PNG bytes, a fixture page (fixture.html) driving the bundle's exported openImagePicker(), and probe.js — the scrollTop-setter spy that separates "clamped at assignment" from "moved afterwards". Chromium at a 390×844 phone viewport, its own CI job.

Both features that were scoped around the absence are back:

  • Scroll restore / per-directory memory is implemented, through the kit's shared installScrollRestore, and pinned by tests/mutations-e2e.json (6 real mutations + a CONTROL).
  • First-open centring works in flat view, which was the thing a single bare scrollTop write could not do.

Still true, and worth keeping on the record: Chromium-only, so iOS momentum scrolling is uncovered by any tier.

The one item from §1 that was not closed is the measurement gap, so it moves down into §2:

tests/js/image-picker.test.js asserts which object the IntersectionObserver is rooted on. comfyui-image-browser additionally measures the consequence — 400/400 off-screen cards intersect with the grid as root vs 20/400 with the real scroller. Ours would still pass if the root were right and the behaviour wrong.

tests/e2e/ can now express that (REGRESSION N already asserts only the restored band's thumbnails are fetched), so it is a browser-tier item now, not a blocked one.

§2 — Picker paths still untested

Re-checked against src/image-picker.ts at HEAD; all still uncovered:

  • Directory mode — the footer "Use this folder" commit (commitFolder, incl. the . sentinel at a root), and that file cards carry is-inert there.
  • VHS path mode — the absolute-path commit via joinAbs, and that state.absPath seeds from /base when the widget is empty.
  • Navigation — navigateInto / navigateUp, breadcrumb clicks (data-sub vs data-abs), and a tab switch resetting subfolder.
  • .__none__ sentinel from the frontend side. The backend has a test named for the trap (test_directory_mode_sentinel_still_lists_nothing); nothing asserts the picker actually sends it in directory mode.
  • Lazy-load consequence, not just the observer root (moved from §1) — the 400/400-vs-20/400 measurement, now a tests/e2e/ item.

§3 — Node grid

  • The commit-contract divergence — done in test(node-grid): pin the commit contract on the surface that had none #111. Also resolved as a question: it is not one contract implemented twice, it is two widgets. The picker writes core LoadImage's native combo, whose options are sorted(files) off the input dir with no annotation (ComfyUI/nodes.py, LoadImage.INPUT_TYPES), so bare matches an existing option and pre-existing workflows do not churn. The node grid writes GalleryLoadImage's own STRING widget, which has no option list, so annotating states the root outright instead of leaning on parseAnnotated's bare-relative fallback. Both resolve identically through get_annotated_filepath. Now documented in CLAUDE.md § Value contract and pinned on both sides with 4 mutations + a CONTROL.
  • Type-chip switching beyond what test(node-grid): pin the commit contract on the surface that had none #111 needed (it drives the output chip, so this is now partial).
  • The .gl-pathinput free-text absolute-path field (Enter and blur commit paths).
  • DOM-widget mounting and the hideOnZoom teardown.

§4 — Backend

  • Unchanged and still correct: conftest.py stubs PIL with MagicMocks, so _scan_file_entry's width/height probe always raises into its own except and dimensions come back None. Nothing asserts dimensions, which is right today but means a regression that broke the probe outright would be invisible. A narrow real-PIL test (or a stub returning a size) closes it.

Adjacent but tracked in #14, not here: the /thumb + /file handler-level coverage, which #112 adds.


Original body preserved below for provenance.

Original issue text (2026-08, pre-#107)

Follow-up to #85. That PR added the pack's first real DOM coverage (38 → 68 vitest specs, plus the first-ever tests for gallery_loader.ts), but it also surfaced gaps it could not close — and in two places I scoped work down because of them. Filing so the reasons don't evaporate.

1. There is no browser suite, and it is load-bearing

tests/js/ is jsdom, which performs no layout. It accepts scrollTop = 500 on a zero-height scroller and reads back 500 — detached or not. So an entire class of bug is structurally invisible here, and the sibling pack has a Playwright suite (comfyui-image-browser/tests/e2e/) specifically because that class was live there twice.

Two decisions in #85 were made around this absence rather than on the merits:

  • scrollToSelected is guarded off in flat view. Its single bare scrollTop write lands against a grid whose thumbnails are all still data-src placeholders, so a real engine clamps it at the instant of assignment and the view settles somewhere arbitrary. The fix is a bounded re-assert loop — but a re-assert loop that no test can falsify is worse than not scrolling, so flat view simply doesn't scroll-to-selected.
  • Scroll restore / per-directory memory was not ported at all, for the same reason.

There is also a measurement gap the structural tests can't cover (see §2 above, where it now lives).

2. Picker paths still untested

(unchanged — carried up)

3. Node grid coverage is a beachhead, not a suite

(carried up; the commit-contract bullet is now done)

4. Backend

(carried up unchanged)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

choreMaintenance, deps, refactoring

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions