Quick start
Install Retest, run your first test and inspect a failure with an agent or by hand.
This guide takes you from installing Retest to running a test against your web app. You can give the setup to a coding agent or follow the steps yourself. The first test needs no AI provider.
Requirements
Use Node.js 24.12 or later on macOS, or on Linux with Chrome or Chromium, where Retest is checked inside Docker. You also need a web app to test and Google Chrome installed; for another browser, follow Browsers. Run every retest command in the project where you installed it: elsewhere, npx retest would fetch an unrelated npm package with the same name.
Set up with your coding agent Link to Set up with your coding agent
Open Claude Code, Codex or Cursor in your app's directory and paste this prompt. It asks the agent to inspect your project before choosing the commands and flow:
Set up Retest end-to-end tests in this project. Read https://rehearsal.dev/retest/docs/quick-start.md first, then follow the linked docs when needed. 1. Read the project instructions, package manager, start scripts and existing tests. Check for Node.js 24.12 or later and an installed supported browser. 2. Install @rehearsal-labs/retest, typescript and @types/node as development dependencies with this project's package manager. 3. Run retest init with explicit --app, --browser and --start flags for this app, or --yes for defaults you have checked. Review the generated config and keep existing files. 4. Run retest doctor and resolve setup problems before running tests. Reuse an app server that already answers. 5. Replace the generated example with one test for an important user flow. Read the app's actual labels and test ids. Await every action and asynchronous check, and verify the outcome with expect. 6. Run the test. On failure, read the report and follow its next inspection command. Fix the cause and rerun until the test passes, without weakening its checks to hide a bug. 7. Add the test and type-check commands to the project instructions. Report what you tested and any setup you could not verify. Do not add an AI judge for the first test. If the flow needs credentials, declare them as config secrets and use secret handles in the test.
Retest prints shorter output when it detects a coding agent, including the command to inspect the run. Coding agents explains that workflow and gives project instructions you can keep for later tests.
Set up by hand Link to Set up by hand
Step 1: Install the package
In your app's directory, install Retest and the packages used to check your test types:
npm install -D @rehearsal-labs/retest typescript @types/nodepnpm add -D @rehearsal-labs/retest typescript @types/nodeyarn add -D @rehearsal-labs/retest typescript @types/nodebun add -d @rehearsal-labs/retest typescript @types/nodeRetest runs your
.tstests with the TypeScript support built into Node, so the TypeScript package is only there to check types. Tests and the config use ES module imports.If Node prints a warning about the module format, TypeScript explains the
"type"field inpackage.jsonand when it is safe to change.Step 2: Create the config and starter test
Run
initand answer its questions about your app's address, start command and browser:npx retest initpnpm exec retest inityarn retest initbunx retest initinitwritesretest.config.ts,tests/example.retest.tsandtests/tsconfig.json. It also adds test and type-check scripts topackage.json, and.retest/to.gitignore, while keeping existing files and scripts.For a command without questions, give explicit flags. Replace the example address with your app's address:
Terminal npx retest init --app web=http://localhost:3000 --browser chrome --yesThe config below uses Chrome at that address. Your generated config may also have a
startcommand, which lets Retest start the app when no server answers.retest.config.ts import { chrome, defineConfig } from '@rehearsal-labs/retest'const config = defineConfig({ apps: { web: chrome({ baseUrl: 'http://localhost:3000' }), },})export default configdeclare module '@rehearsal-labs/retest' { interface Register { config: typeof config }}webnames the app, andbaseUrlis the address relative paths open against. Keep the registration block at the bottom so TypeScript can check app names and other config values used by tests.Step 3: Check that the browser and app are ready
Start your app if the config has no
startcommand, then run the setup check:npx retest doctorpnpm exec retest doctoryarn retest doctorbunx retest doctordoctorlaunches and closes the browser, checks that the app answers and checks configured secret variables. It runs no tests. If it finds a problem, follow the reported fix before continuing.Step 4: Write a test for your app
The generated test opens
/and checks for a main region. Renametests/example.retest.tstotests/task.retest.tsand replace its contents with this example. It expects the task app's test ids, so change the locators and expected title to match your app.tests/task.retest.ts import { expect, test } from '@rehearsal-labs/retest'test('saves a task', async ({ page }) => { await page.goto('/') await page.getByTestId('task-title').fill('Release checklist') await page.getByTestId('save-task').click() await expect(page.getByTestId('saved-task')).toHaveText('Release checklist')})The test fills the title field, clicks Save once and waits for the saved title. Await each action and check so the steps run in order. The final check waits up to five seconds by default, so you need no fixed sleep while the app saves.
Step 5: Run the test
npx retest runpnpm exec retest runyarn retest runbunx retest runRetest discovers
.retest.tsfiles below the current folder and runs them using your config, then prints a summary and the run folder. A successful run exits with code 0. While editing, run only this file by addingtests/task.retest.tsafterrun.
Read a failure Link to Read a failure
A failed check shows what Retest expected and what the page showed instead. For example, if the app drops the last letter of the title, these lines explain the mismatch:
Check failed toHaveTextLocator getByTestId('saved-task')- Expected "Release checklist"+ Received "Release checklis"The full report also names the source line, the wait and any captured screenshot, then prints commands to rerun and inspect the test. Copy its inspection command to read the saved steps. Inspection opens no browser and changes nothing in the app.
npx retest inspect .retest/runs/<time> --test "tests/task.retest.ts > saves a task"Use the folder printed by your run in place of <time>. Compare the expected value with the app's intended behaviour before changing the test. Debugging a failure explains the rest of the report.
Add an AI check Link to Add an AI check
An optional AI check can judge a requirement that is hard to express as an exact matcher, such as whether a save message explains what happened. Keep the title check, then ask a judge to read the page. The built-in adapter supports Anthropic, OpenAI and Azure through API keys.
Choose a provider, install its optional packages and set its key in the shell where you run Retest. The commands below use npm; use your package manager's equivalent if needed. Replace the key, model id and Azure resource values with your own.
The config snippets add a judge to the earlier example. Keep your own apps settings, including any start command, when adding evaluation.
npm install -D ai@^7.0.127 @ai-sdk/anthropic@^4.0.71export RETEST_EVALUATION_ANTHROPIC_KEY='your-api-key'Add env to the config's imports and use this defineConfig call. Keep the export and registration block:
const config = defineConfig({ apps: { web: chrome({ baseUrl: 'http://localhost:3000' }) }, evaluation: { judges: { visual: { adapter: '@rehearsal-labs/retest/evaluation/ai-sdk', credentials: { apiKey: env('RETEST_EVALUATION_ANTHROPIC_KEY') }, options: { provider: 'anthropic', model: 'your-model-id' }, accepts: ['text', 'images'], }, }, },})npm install -D ai@^7.0.127 @ai-sdk/openai@^4.0.83export RETEST_EVALUATION_OPENAI_KEY='your-api-key'Add env to the config's imports and use this defineConfig call. Keep the export and registration block:
const config = defineConfig({ apps: { web: chrome({ baseUrl: 'http://localhost:3000' }) }, evaluation: { judges: { visual: { adapter: '@rehearsal-labs/retest/evaluation/ai-sdk', credentials: { apiKey: env('RETEST_EVALUATION_OPENAI_KEY') }, options: { provider: 'openai', model: 'your-model-id' }, accepts: ['text', 'images'], }, }, },})npm install -D ai@^7.0.127 @ai-sdk/azure@^4.0.90export RETEST_EVALUATION_AZURE_KEY='your-api-key'Add env to the config's imports and use this defineConfig call, keeping the export and registration block. On Azure, model is your deployment name:
const config = defineConfig({ apps: { web: chrome({ baseUrl: 'http://localhost:3000' }) }, evaluation: { judges: { visual: { adapter: '@rehearsal-labs/retest/evaluation/ai-sdk', credentials: { apiKey: env('RETEST_EVALUATION_AZURE_KEY') }, options: { provider: 'azure', resourceName: 'your-resource', model: 'your-deployment', }, accepts: ['text', 'images'], }, }, },})With one judge configured, Retest uses it by default. Choose a model that accepts images and structured output, then add this call after the saved-title check in your test:
await test.evaluate({ requirement: 'The message says the task was saved and names it.', evidence: { capture: 'screenshot' },})Run the test again with the same command. Retest captures a screenshot, sends it to the configured judge and records the verdict. This check is required by default, so a failed or inconclusive verdict cannot become a pass.
Judges use API keys; Retest does not support subscription sign-in. AI checks covers provider setup and evidence limits.