Skip to main content

Video Recording

Hosanna Tools can record the complete owned run on supported transports. Video helps reconstruct timing and visible behavior around a failure, but semantic assertions and command artifacts remain the source of test status.

Enable Recording

Set video in hosanna-test.config.ts:

export default defineHosannaTestConfig({
// ...
video: true,
});

The object form is enabled unless enabled: false is set. Its options depend on the target:

video: {
enabled: true,
timeoutSeconds: 180,
codec: 'h264',
}

size is browser-only and defaults to 1920×1080. Native/device capture uses options such as source, timeoutSeconds, codec, videoDevice, audioDevice, application, windowTitle, display, or rect.

The sample config maps this project convention:

video: process.env.HS_TEST_VIDEO === '0'
? false
: true

HS_TEST_VIDEO is not read directly by the shared package; the application config must map it to video.

Supported Transports

Test targetRecording transportOutput
Owned browserPlaywright context recordingrun.webm
iOS Simulatorxcrun simctl io ... recordVideorun.mp4
Apple TV Simulatorsimctl external-display recordingrun.mp4
Physical RokuAVFoundation/ffmpeg capture input, or explicit macOS window/screenrun.mp4 or run.mov
Android/Android TV AVDExplicit macOS window/screen capture onlyrun.mov

Other physical-device targets are not implemented by the test launcher. Android simulator capture is intentionally explicit: set a macOS source plus a window, application, display, or rectangle so the recorder knows what pixels it owns.

Example Android Emulator window capture:

video: {
source: 'macos-window',
application: 'Android Emulator',
windowTitle: 'Television_1080p',
timeoutSeconds: 180,
}

Example Roku capture-card configuration:

video: {
source: 'avfoundation',
videoDevice: 'USB Video',
audioDevice: 'USB Digital Audio',
frameRate: 30,
videoBitrate: '12M',
}

The capture host must provide the required Apple tools, ffmpeg, input device, display, or window. If a target/source combination is unsupported, setup fails instead of silently omitting the recording.

Recording Lifecycle

Browser recording begins with the owned browser context. Native and device capture starts after the application handshake. Both then cover the test run across Vitest files, and global teardown stops and finalizes the recording.

Artifacts live under:

test-results/<testRunId>/<platform>-<target>/
run.webm
# or run.mp4 / run.mov

Native/device capture also writes a sidecar capture manifest next to the video. run.json records the relative path and MIME type, and the HTML report embeds or links the result.

The native/device default timeout is 180 seconds. Increase it for a deliberately longer suite; otherwise the recorder finalizes at the timeout even if tests continue.

Limitations

  • Browser WebM has no audio.
  • Apple simulator recording does not make the simulator equivalent to physical hardware.
  • AVFoundation audio is included only when an audio input is configured.
  • A macOS window/screen recording can include pixels outside the app if its target is too broad.
  • Recording covers the run, not one video per test.
  • A process killed before teardown may leave an incomplete or missing file.
  • Video has no trace events or source-level replay.

The failure bundle contains semantic commands, hierarchy, focus, debugger context, logs, and screenshots. It does not produce a Playwright trace archive. Do not describe video or commands.jsonl as a Playwright trace.

Retention and Secrets

Video can be large. Keep it for failures and high-value proof runs, use shorter retention for routine branches, and disable it for rapid local loops.

Never record a flow that leaves a secret visible. envSecret redacts serialized diagnostics and suppresses the automatic failure screenshot after secret text entry, but it cannot edit recorded pixels or capture-card audio. Exclude credential-bearing flows or disable video for them.

Diagnose With Video

Start with the failed assertion and commands.jsonl, then use video to check whether:

  • visible focus lagged behind semantic state;
  • an animation or remote image was still in flight;
  • the wrong screen was already visible before a command;
  • a native/system dialog interrupted the journey;
  • the device, simulator, or capture transport stopped updating.

Correlate video with logs and proof state; do not accept behavior solely because it looked correct in a recording.

Next: Reports and Failure Investigation.

Talk to us