Skip to content

test: browser-level e2e for the wasm visor (Tier C — SharedWorker, SPA, real carriers) #3927

Description

@0pcom

What exists

  • wasm / wasm-tinygo — compile checks. wasm-tinygo additionally runs make test-wasm-policy, a real wazero runtime test, but of the app-mux policy module, not the visor.
  • wasm-headless — the real one: builds the std-Go blob, starts a loopback dmsg server (scripts/wasm-headless/localdmsg), and runs scripts/wasm-headless/harness.mjs under Node ≥22, asserting boot → live dmsg session over the ws:// seed → the in-wasm hypervisor core answers GET /api/about with dmsg_connected: true.

That is a genuine e2e and it needs no browser, because the visor is driven through globalThis.skywireVisor.

What it structurally cannot reach

Node has no SharedWorker, no DOM, and no real browser networking. So none of these are covered anywhere:

  • SharedWorker lifecycle — orphaned workers, the "already running in another tab" path, worker self-termination and the ping/pong heartbeat in pkg/wasmhv/worker.js
  • The js.Func re-entrancy class — the std-Go wasm scheduler only returns to the JS event loop when every goroutine blocks, so blocking inside a js.Func callback deadlocks. This is browser-observable only.
  • The Angular SPA served by the visor, WinBox windows, the xterm-go terminal, the tpviz netview role
  • Carriers other than ws — the seed is a loopback dmsg server; wt/quic/tcp and real discovery are untested
  • Only /api/about is asserted — none of the rest of the in-wasm hypervisor API

Every one of those has cost real debugging time.

Proposal

A browser lane built from tooling already in the repo, rather than a new framework:

  1. skywire cli hv serve — serves the standalone wasm-visor over HTTP
  2. headless Chromium with --remote-debugging-port — already provisioned in the ui job via browser-actions/setup-chrome
  3. skywire cli hv probe --navigate … --eval … --expect … --fail-on-fault — the CI gate (see cli: give hv probe an exit-code contract so it can gate CI #3926, which adds the exit-code contract this needs)

First assertions, roughly the Node harness's but through a real browser and a real SharedWorker: the page loads with no uncaught exception, the visor boots, dmsg_connected becomes true, hvApi answers. Then the lifecycle cases: open a second tab and assert the "already running" path behaves, close the owning tab and assert the worker is reclaimed.

Depends on #3926.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions