Skip to content

Configure your project

Start with your app’s command and URL. Paths are relative to dyno.config.js.

import { defineConfig } from 'dyno/config';
export default defineConfig({
testDir: 'tests/browser',
webServer: {
command: 'npm run dev',
url: 'http://127.0.0.1:3000',
},
});

Dyno gives each test 10 seconds, including hooks and document startup. Interactor assertions get up to 2 seconds. Change timeout or expectTimeout when the workflow needs it; use timings to find out why.

All options and defaults
Option Default Purpose
testDir tests/browser Test directory
testMatch **/*.test.{js,jsx,ts,tsx} File pattern
timeout 10000 Test deadline, including runtime startup and hooks
cleanupTimeout 5000 Total budget for cleanup after execution ends
expectTimeout min(2000, timeout / 2), rounded down Interactor assertion timeout
runTimeout 60000 Headless browser opening and results deadline, after app readiness
host, port 127.0.0.1, 7357 Gateway address; port 0 chooses a free port
browser.name, path, args chromium, Playwright build, [] Managed target, optional executable, and launch arguments
browser.deviceScaleFactor 1 Playwright pixel ratio from 1 to 3
browser.isMobile, browser.hasTouch false Emulate mobile viewport behavior and touch input
browser.userAgent Browser default Override the managed browser user agent
viewport Browser size; managed: 1280 × 800 Required app viewport dimensions
reportDir .dyno/reports Saved JSON, JUnit, HTML, and copied images per browser run
artifactsDir .dyno/artifacts PNG output directory
webServer.url Required HTTP(S) origin without a path
webServer.command None App startup command
webServer.cwd, env Config directory, inherited env App process settings
webServer.ready Any process output Ready-message string or RegExp
webServer.timeout 30000 App startup deadline
webServer.reuseExistingServer false Reuse a responding server
setup None Node setup module
seed, random None, false Repeatable randomized priority or a generated seed
workers 1 Managed worker count, from 1 to 32; concurrent runs need project worker setup
forbidOnly Whether CI is set Reject focused test/suite definitions

Point setup at a Node module. Its async default export receives { config, session, signal, onCleanup } and returns the resources your tests need:

import { startTestProject } from './support/project.js';
export default async function setup({ session, signal, onCleanup }) {
return startTestProject({ session, signal, onCleanup });
}

startTestProject is your helper. Return webServer overrides, app env, JSON-safe fixtures for tests, and a teardown function. Keep credentials out of browser fixtures. Register owned releases with onCleanup as resources are acquired. They run even if setup throws before returning. Setup messages go to stderr.

Use project factories to create committed records and real sessions. Return the IDs and paths a scenario needs, then exercise the behavior through the app. Share immutable fixture inputs rather than mutable records. For concurrent runs, give each worker its own resources.

Use named app fixtures to call your real factories through app.fixture. Keep that test control outside production entrypoints. Operations receive explicit app dependencies; Dyno handles execution ownership and transport, while your app owns factories, auth, queues and visual comparison.

A fresh page doesn’t stop server writes, background jobs, or service workers. Return drain when your project needs to join that work between tests. Close admission for the old scenario, release any held requests, and leave its resources ready for reuse.

Between tests Dyno retires the old document, then calls drain({ runId, executionId, workerId, test, signal }). It runs once per non-skipped execution, including the last one before results are saved. The final successful document can remain for inspection, so its backend admission still needs to close during drain. Its duration appears in session timings.

Keep draining within cleanupTimeout and honor its signal. A failure ends the session and saves accepted results; remaining tests stay unassigned. Callbacks must honor cancellation. Dyno retains their original promises until settlement before resource destruction; uncooperative Node work can delay shutdown. Make teardown safe after a drain failure.

Setup owns CLI-session resources, worker setup owns private resources, and optional beforeExecution resets or binds each scenario before browser hooks. Preparation uses the selected test timeout, leaving the remaining budget for browser work. Timings distinguish preparation from execution cleanup. For a multi-process app, use one project command to start the real stack and handle shutdown.