# Configuration

> Configure your app address, browser targets and timeouts, and let Retest start a local app server.

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

Start with one app address and one browser in your config. This page shows how to add browser targets, separate sessions and a server start command as your tests need them.

## Configure one app

Create `retest.config.ts` in the folder where you run Retest, or use the file written by `retest init`. This config points tests at the task app on port 4173 and runs them in your installed Google Chrome.

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

const config = defineConfig({
  apps: {
    web: chrome({ baseUrl: 'http://127.0.0.1:4173' }),
  },
})

export default config

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

`web` is your app's name, and `chrome` describes its browser target. Because there is one app, a test without an `apps` option receives it as `page`. Relative paths such as `page.goto('/')` resolve against `baseUrl`.

The `Register` block makes the config's names and capabilities available to TypeScript in your tests. Keep it when you change the config; [TypeScript](https://rehearsal.dev/retest/docs/essentials/typescript.md) explains how it catches wrong app names and unsupported methods.

Retest checks the config when it loads it, including for JavaScript callers. An unknown key or an invalid value stops the command with exit code 2 and a message naming the file and setting.

## Choose browser targets

Give an app several named targets to run the same tests in more than one browser. Add `app` and `chromium` to the imports, then use this `defineConfig` call. Keep the export and registration block from the first example.

```ts
const config = defineConfig({
  apps: {
    web: app({
      baseUrl: 'http://127.0.0.1:4173',
      targets: {
        chrome: chrome(),
        chromium: chromium(),
      },
    }),
  },
})
```

A test using this app runs once on each target, and its results name the target it used. `chrome()` finds an installed Google Chrome. `chromium()` needs an executable path, supplied through `executablePath` or `RETEST_CHROMIUM`; see [Browsers](https://rehearsal.dev/retest/docs/platforms/browsers.md) for installation and engine support.

For an app with one target, the target helper directly under `apps` is the shorter form shown in the first example. Use a target's `viewport` to set only its page size, or `emulate` to describe an emulated device. A target cannot take both.

## Give each person an app

Use separate app entries when one test needs two browser sessions, for example a member and an administrator. They can use the same website address while keeping separate cookies and storage.

```ts
const config = defineConfig({
  apps: {
    web: chrome({ baseUrl: 'http://127.0.0.1:4173' }),
    admin: chrome({ baseUrl: 'http://127.0.0.1:4173' }),
  },
  defaultApp: 'web',
})
```

Keep the export and registration block from the first example. `defaultApp` keeps existing tests using `page` on the web app. A test that explicitly declares both apps receives their names instead of `page`.

```ts
test('both sessions start signed out', { apps: ['web', 'admin'] }, async ({ web, admin }) => {
  await web.goto('/account')
  await admin.goto('/account')
  await expect(web.getByTestId('account')).toHaveText('Signed out')
  await expect(admin.getByTestId('account')).toHaveText('Signed out')
})
```

Each app gets a browser context and page of its own. The same approach lets a test use different platforms together; [One test across platforms](https://rehearsal.dev/retest/docs/platforms/across-platforms.md) shows a flow across web and native apps.

## Choose target pairings

When a test uses two or more apps that each have several targets, use `runs` to choose their pairings. With `app`, `chrome` and `chromium` imported, this config runs the two-session test on two browser pairings:

```ts
const config = defineConfig({
  apps: {
    web: app({
      baseUrl: 'http://127.0.0.1:4173',
      targets: { chrome: chrome(), chromium: chromium() },
    }),
    admin: app({
      baseUrl: 'http://127.0.0.1:4173',
      targets: { chrome: chrome(), chromium: chromium() },
    }),
  },
  defaultApp: 'web',
  runs: [
    { web: 'chrome', admin: 'chromium' },
    { web: 'chromium', admin: 'chrome' },
  ],
})
```

The test using both apps runs once per listed pairing. Apps with only one target use it automatically. If no `runs` entry names all of the test's apps that have several targets, the test file fails collection. Retest does not generate every combination.

## Start a local server

Add `start` when Retest should start the app's development server. In your config, use your own start command and set `ready` to an endpoint that answers when the server is available.

```ts
const config = defineConfig({
  apps: {
    web: chrome({
      baseUrl: 'http://127.0.0.1:4173',
      start: {
        command: 'npm run dev',
        ready: 'http://127.0.0.1:4173',
        timeoutMs: 60_000,
      },
    }),
  },
})
```

Retest first sends an HTTP request to `ready`. If a server already answers, it reuses that server and leaves it running. Otherwise it starts the command, waits for an answer and stops the server it started when the run ends.

> [!NOTE]
> **Readiness checks**
>
> Any HTTP response counts as ready, including an error response. The readiness check proves that a server answers, so your tests must still check that the app works.

A server that exits early or never answers causes setup failures for tests that need it. Read the log path named in the failure for its output. If the command needs another working directory, set `start.cwd` relative to the config's folder.

## Set time budgets

Use `timeouts` to change how long Retest allows an operation to take. Add it alongside your app settings when actions, checks or tests need a different budget.

```ts
const config = defineConfig({
  apps: { web: chrome({ baseUrl: 'http://127.0.0.1:4173' }) },
  timeouts: {
    action: 5000,
    assertion: 10_000,
    test: 30_000,
  },
})
```

Values are milliseconds. Here an action gets up to five seconds, a check up to ten seconds, and the whole test up to thirty seconds. An action or assertion cannot use more time than the test has left. A test's own `timeout` option can set its individual test budget.

Without overrides, the action budget is ten seconds, assertions get five seconds and a test gets sixty seconds. `--timeouts` overrides the config for a run. The [Configuration reference](https://rehearsal.dev/retest/docs/reference/config.md) lists navigation, setup and the other budgets.

## Keep environment values in the config

Read a deployment address from the environment when the same tests run locally and in continuous integration. This uses `TASK_APP_URL` when it is set and the local address otherwise.

```ts
const config = defineConfig({
  apps: {
    web: chrome({
      baseUrl: process.env['TASK_APP_URL'] ?? 'http://127.0.0.1:4173',
    }),
  },
})
```

For passwords, declare a secret source such as `env('TASK_APP_PASSWORD')` in `secrets` and use `secret('password')` in the test. [Signing in and secrets](https://rehearsal.dev/retest/docs/guides/signing-in.md) shows the complete config and sign-in flow.

You can also replace addresses with `--base-url`, or load another file with `--config`. Use flags for a run's choices, including `--workers`; the worker count is not a config key.

## Next steps

- [TypeScript](https://rehearsal.dev/retest/docs/essentials/typescript.md): Check your config names and app capabilities.
- [Running tests](https://rehearsal.dev/retest/docs/essentials/running-tests.md): Choose tests, targets and per-run overrides.
- [Configuration options](https://rehearsal.dev/retest/docs/reference/config.md): Look up every setting and its default.
