Browser testing with Playwright WebGPU

Browser tests should exercise the same public API users copy: init(), surface(gpu, canvas, opts), explicit targets, and deterministic frame submission. Avoid hidden app globals and avoid relying on a continuous loop in assertions.

TypeScript
1
2
3
4
5
6
7
8
9
import { init } from "vgpu";
 
export async function renderOnce(canvas: HTMLCanvasElement) {
  const gpu = await init();
  const surface = surface(gpu, canvas, { dpr: 1, autoResize: false });
  const effect = effect(gpu, WGSL, { set: { time: 0, texel: surface.texelSize } });
  frame(gpu, (f) => f.pass({ target: surface, clear: [0, 0, 0, 1] }, (p) => p.draw(effect)));
  return gpu;
}

Test checklist

  • Use fixed DPR/size (dpr: 1, autoResize: false, or explicit size) for pixel snapshots.
  • Submit with frame(gpu, ...) for one deterministic frame, not requestAnimationFrame loops.
  • Read from explicit surfaces or offscreen targets with target.read().
  • Keep WGSL imports pure: modules export helpers only; bindings live in the entry shader. If a module declares a binding, fix VGPU-RESOLVE-MODULE-BINDING.
  • For headless tests use vgpu/mock for deterministic unit tests and vgpu/node only when Dawn/WebGPU behavior is under test.