Use Retest from code
Run test files from your program, receive events and add checks your host controls.
Use runFiles when a script, worker or service needs to run Retest directly. Your program is the host. It supplies the configuration and run folder, then receives events and the final result.
Run a test file Link to Run a test file
The authoring helpers come from the root package; host functions come from @rehearsal-labs/retest/runner. Build a config in memory, validate it and resolve its secrets before calling the runner.
import type { Reporter } from '@rehearsal-labs/retest/runner'import { randomUUID } from 'node:crypto'import { resolve } from 'node:path'import { chrome, defineConfig } from '@rehearsal-labs/retest'import { defaultTimeouts, resolveSecrets, runFiles, validateConfig,} from '@rehearsal-labs/retest/runner'const rootDir = process.cwd()const loaded = validateConfig( defineConfig({ apps: { web: chrome({ baseUrl: 'http://127.0.0.1:4173' }) }, }), resolve(rootDir, 'host.config.ts'),)if (!loaded.ok) throw new Error(loaded.failure.message)const secrets = resolveSecrets(loaded.config, process.env)if (!secrets.ok) throw new Error(secrets.failure.message)const reporter: Reporter = { name: 'host', onEvent(event) { process.stdout.write(`${JSON.stringify(event)}\n`) }, onRunEnd() {},}const stop = new AbortController()process.once('SIGINT', () => stop.abort('SIGINT'))process.once('SIGTERM', () => stop.abort('SIGTERM'))const result = await runFiles({ files: ['tests/task.retest.ts'], rootDir, apps: { kind: 'config', config: loaded.config, secrets: secrets.secrets }, timeouts: defaultTimeouts, outputDir: resolve(rootDir, '.retest/runs', randomUUID()), lastRunFile: false, headless: true, signal: stop.signal, testEnvironment: {},}, [reporter])process.exitCode = result.exitCodeRun this script with node host.ts from a project containing the task test and an app already serving that address. The random id gives each call a new output folder because Retest refuses one that already holds files. Your reporter receives events in sequence while the run proceeds.
The path passed to validateConfig labels the config and anchors relative paths; no config file needs to exist there. lastRunFile: false leaves history management to your host. An empty testEnvironment gives the test process none of your application environment; pass only variables the test actually needs.
Supply secrets Link to Supply secrets
A host can use env sources or functions that read a vault. resolveSecrets reads environment sources once and keeps function sources for later use. To use your vault client, replace the config passed to validateConfig with this fragment:
defineConfig({ apps: { web: chrome({ baseUrl: 'http://127.0.0.1:4173' }) }, secrets: { password: ({ signal }) => vault.read('task-app-password', { signal }), },})Here vault is your own credential service, and the function stays in the host process. Test code uses secret('password') without receiving the value. A config with only function sources can use an empty environment map when resolving secrets.
Add host checks Link to Add host checks
Host checks let your program require facts about the final page independently of assertions in the test body. Add this option to runFiles to check both the address and visible saved title:
hostChecks: { 'tests/task.retest.ts': [ { kind: 'address', origin: 'http://127.0.0.1:4173', path: '/' }, { kind: 'text', text: 'Release checklist' }, ],},A file key applies to every test collected from that file, including setups. To require a check on only one test, use its full test id as the key. After a passing body and its cleanup hooks, Retest runs the checks before closing pages; a failed host check fails the test.
Address checks compare the origin and optional path, leaving queries and fragments out. Text checks read the top-level body's visible text, excluding frames, shadow roots and hidden elements. They prove the final state, not the steps used to reach it. A check targeting no selected test or file is refused before a browser starts.
Stop and read a run Link to Stop and read a run
Abort the signal to stop a run. The example forwards SIGINT and SIGTERM, which produce interrupted results and exit codes 130 and 143. A host can also abort with a structured interruption reason, which Retest records and reports with exit code 130.
stop.abort({ class: 'interrupted', message: 'The host is shutting down, so it stopped the run.',})To inspect evidence later, read the run folder through the runner subpath. This validates the files and returns the result, events and any warnings.
import { readRunFolder } from '@rehearsal-labs/retest/runner'const folder = readRunFolder('/path/to/run')process.stdout.write(`${folder.result.status}\n`)for (const warning of folder.warnings) process.stderr.write(`${warning}\n`)If result.json was never written, the reader reconstructs the run from events and marks it incomplete. For concurrent calls, give every run a separate output folder and share a session budget when you need a common limit.
Host boundaries Link to Host boundaries
Take the authoritative result from runFiles and events from your reporter. The run folder contains copies that the test process can write, so a host evaluating untrusted tests should not treat those copies as independent proof.
Test execution
The test process is not a sandbox. It runs as the same user and can access that user's files and network. A host running code it did not write must isolate the whole Retest run, for example in a container it controls.
For an agent that needs to drive a session interactively instead of running test files, use @rehearsal-labs/retest/agent. Coding agents explains where those sessions fit.