Skip to content

docs(guide): Testing headlessly page #160

Description

@blendsdk

Part of #143 — the Guide expansion. Group Going further.

Purpose & audience

Teach testing an app without a terminal. The Introduction claims "assert on what is on screen in an
ordinary test run" and never shows how — this cashes that promise. Cheap page, high credibility.

The gap today

The headless-mount pattern is used all over the repo's own tests but is nowhere in user-facing docs.
A reader who wants to test their TUI in CI has no guidance.

Outline

  1. Why it's possible: the engine is host-agnostic — no real TTY needed; you drive input and read the
    composed frame.
  2. Mounting headlessly: build the app with a headless/viewport host and no native tty.
  3. Reading the screen: app.loop.renderRoot.buffer().rows() gives the composed frame as strings —
    assert on what's actually painted.
  4. Driving input: dispatching keys/commands (app.loop.dispatch(...)) and asserting the result.
  5. Async + modal testing: awaiting an execView dialog headlessly, resolving it, asserting after.
  6. createRenderRoot({ schedule }) for a bare view (no app), and the trap: that counter conflates
    repaint with relayout — assert a reflow via an inline literal on view.host, not the schedule
    counter.

Code examples to write

  • Mount an app, dispatch a key, assert a row of buffer().rows().
  • Drive a dialog: open via execView, dispatch Enter, await, assert the resolved value.
  • A bare-view render-root test with createRenderRoot.

Live examples

  • Reuse: none — a test-authoring page; a live xterm can't show a vitest run.
  • Build new: none. (The runnable artifact here is a copy-pasteable *.test.ts, not a Play example.)

Source pointers

  • packages/ui/src/view/createRenderRoot / RenderRoot (buffer().rows()).
  • Memories ui-relayout-test-seam (no ViewHost double in ui tests; assert reflow on public
    view.host, never the createRenderRoot({schedule}) counter — it conflates repaint with relayout)
    and jsvision-ui-modal-dialog-patterns (the headless async/nested-confirm test harness).
  • The docs-site's own test/paint-smoke.spec.test.ts mounts every example headlessly — a working
    reference for the mount pattern.

Constraints

  • No .layout = (snippet-drift). Test files have their own conventions, but this page is a teaching
    artifact and is held to the guard.

Acceptance criteria

  • Headless mount + buffer().rows() assertion shown; input driving shown.
  • Async/modal headless testing covered; the render-root schedule-counter trap documented.
  • Cross-links Debugging (shared frame-dump trick) and Writing your own widget.
  • Sidebar under Going further; build clean.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: docs-siteVitePress docs & showcase site (@jsvision/docs-site): guide, live examples, API pagesdocumentationImprovements or additions to documentationeffort: SSmall — hourspriority: mediumValuable; schedule after the high tier

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions