# Configuration

> Set up the apps a test opens, the browsers it runs in, its base URL, its screen and its time limits.

Source: https://rehearsal.dev/retest/essentials/configuration

A project's config is `retest.config.ts` in the folder Retest runs from. `--config <path>` names another file. Retest loads the config in its own process, and test files never load it.

```ts filename="retest.config.ts"
import { app, chrome, chromium, defineConfig, env } from '@rehearsal-labs/retest'

const baseUrl = process.env['TASK_APP_URL'] ?? 'http://127.0.0.1:4173'

const config = defineConfig({
  apps: {
    web: chrome({ baseUrl }),
    admin: chrome({ baseUrl }),
    desktop: app({ baseUrl, targets: { chrome: chrome(), chromium: chromium() } }),
    phone: app({ baseUrl, targets: { pixel: chrome({ emulate: 'Pixel 9' }), iphone: chrome({ emulate: 'iPhone 17' }) } }),
  },
  defaultApp: 'web',
  runs: [
    { desktop: 'chrome', phone: 'pixel' },
    { desktop: 'chromium', phone: 'iphone' },
  ],
  secrets: { password: env('TASK_APP_PASSWORD') },
  tags: ['smoke', 'roles', 'browsers', 'phone'],
  states: ['signed-in'],
  locks: ['saves'],
  timeouts: { action: 5000, assertion: 5000, test: 30_000 },
})

export default config

declare module '@rehearsal-labs/retest' {
  interface Register {
    config: typeof config
  }
}
```

## Keys

| Key | What it holds |
| --- | --- |
| `apps` | Each app the tests open, with its targets |
| `defaultApp` | The app `page` is. With one app, that app. |
| `runs` | Which targets run together, for tests that use two apps with several targets each |
| `secrets` | Each secret's source: `env(name)`, or a function |
| `secretOrigins` | More origins where a secret may be typed |
| `testIds` | The test ids `getByTestId` accepts. Only the type check reads it. |
| `tags` | The tags tests may use. `--tag` refuses any other. |
| `states` | The names of the sign-in states `test.setup` may save |
| `locks` | The shared state tests may hold with `locks` |
| `timeouts` | Budgets that replace the defaults |
| `evaluation` | The judges for [AI checks](https://rehearsal.dev/retest/ai-checks.md) |
| `diagnostics` | Console and network capture, and when it fails a test |
| `recording` | Which apps are recorded as video, and whether a recording is required |
| `pixels` | Whether screenshots and recordings may be taken, by app |

Names of apps, targets, secrets, tags, states and locks hold letters, digits, `_` and `-`, and start with a letter. Paths in the config are relative to its folder.

An invalid config stops the run with exit code 2 before anything starts. The message names the file and every key at fault, such as `apps.web.baseUrl: expected an http or https URL`.

## Apps and targets

An app is what a test opens. A target is where it runs. An app is a target on its own, or `app({ baseUrl, start, targets })` with several.

| Target | Runs |
| --- | --- |
| `chrome({ channel })` | Google Chrome. `channel` is `stable`, the default, or `beta`, `dev` or `canary`. |
| `edge({ channel })` | Microsoft Edge, with the same channels. |
| `chromium({ executablePath })` | The Chromium at `executablePath`, or at the path in `RETEST_CHROMIUM`. |
| `{ browser: 'firefox' }` | Firefox, on macOS. See [Browser support](https://rehearsal.dev/retest/platforms/browsers.md). |
| `{ browser: 'webkit' }` | Playwright's WebKit build, on macOS. |
| `electron({ executablePath, appPath })` | An Electron app. See [Desktop apps](https://rehearsal.dev/retest/platforms/desktop.md). |
| `{ platform: 'ios-simulator', ... }` | An app on an iOS simulator. See [Mobile apps](https://rehearsal.dev/retest/platforms/mobile.md). |
| `{ platform: 'macos', ... }` | A macOS app. See [Desktop apps](https://rehearsal.dev/retest/platforms/desktop.md). |

A test that uses an app with several targets runs once on each. With two such apps, `runs` lists the pairs to run, one entry each. Each run is a variant, named like `desktop=chromium`.

## Base URL

`baseUrl` is the address `page.goto('/')` opens a path on. The command line can replace it, which is how CI points the tests at a preview.

```sh
npx retest run --base-url https://preview.example.com
npx retest run --base-url web=https://preview.example.com --base-url admin=https://admin.preview.example.com
```

## Screen size

- `viewport: { width, height }` sizes the page and nothing else, as in `chromium({ viewport: { width: 1280, height: 720 } })`.
- `emulate` makes a desktop browser pretend to be a device, by name or by its screen. [Web apps](https://rehearsal.dev/retest/platforms/web.md) lists the devices.
- A target takes `viewport` or `emulate`, not both.

## Start the app

An app with `start: { command, ready, cwd, timeoutMs }` gets its server started when a test first needs it.

```ts
web: chrome({
  baseUrl: 'http://localhost:3000',
  start: { command: 'npm run dev', ready: 'http://localhost:3000' },
}),
```

- Retest asks `ready` with an HTTP GET. If anything answers, it uses that server and never stops it.
- Otherwise it runs `command` in a shell, with its output in `logs/app-<name>.log`, and waits for `ready` to answer.
- When the run ends, it stops the server it started.
- A server that exits early or never answers fails every test that needs it, and the failure names the log.

## Budgets

Every wait answers to a budget, in milliseconds. `timeouts` in the config replaces some, and `--timeouts action=500,test=3000` replaces them again for one run.

| Budget | Default | What it covers |
| --- | --- | --- |
| `collection` | 10000 | Loading each test file |
| `setup` | 60000 | Launching a browser, opening a test's pages and starting an app server |
| `action` | 10000 | One action |
| `navigation` | 30000 | One `goto`, `reload`, `goBack` or `goForward` |
| `assertion` | 5000 | One check |
| `test` | 60000 | One test |
| `cleanup` | 10000 | Closing pages and browsers, and failure screenshots |

> [!NOTE]
> How many files run at once is a flag, not a config key. Pass `--workers <n>` to `retest run`, as [Run tests in parallel](https://rehearsal.dev/retest/scaling-up/parallel-runs.md) explains.
