> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# Integrate with Playwright Test

With `PlaywrightAiFixture`, you can use Midscene's visual interaction and assertion capabilities directly in an existing Playwright Test project. Playwright Test organizes and runs the tests, while Midscene interacts with the page and generates execution reports.

## Before you begin

- **Runtime**: Install Node.js `^20.19.0 || ^22.12.0 || >=24.0.0` and pnpm. Have an existing Playwright Test project that can run tests with Chromium.
- **Model configuration and verification**: Complete [model configuration](/model-api-setup) and [model verification](/model-config#verify-model-connectivity), then save the configuration in the project's `.env` file or shell environment.
- **Platform environment**: Install Chromium and make sure the browser can access the target page.
- **(Optional) Try Playground first**: Run an action and an assertion against your target interface in the [Chrome extension Playground](/get-started?platform=web&scene=playground) to verify screenshots, interactions, and model behavior.

## 1. Install dependencies and configure the project

```sh [npm]
npm install @midscene/web dotenv --save-dev
```

```sh [yarn]
yarn add @midscene/web dotenv --save-dev
```

```sh [pnpm]
pnpm add @midscene/web dotenv --save-dev
```

```sh [bun]
bun add @midscene/web dotenv --save-dev
```

```sh [deno]
deno add npm:@midscene/web npm:dotenv --save-dev
```

Add the following configuration to `playwright.config.ts` (create the file if your project does not have one yet), while keeping your project's other settings and reporters:

```typescript title="playwright.config.ts"
import 'dotenv/config';
import { defineConfig } from '@playwright/test';

export default defineConfig({
  testDir: './e2e',
  timeout: 90_000,
  use: { browserName: 'chromium' },
  reporter: [
    ['list'],
    ['@midscene/web/playwright-reporter'],
  ],
});
```

`dotenv/config` loads model settings from the project's `.env` file (settings in the Chrome extension Playground are not automatically shared with test runs). Because model calls take longer than standard DOM operations, increase `timeout` as needed for your tests.

## 2. Create a fixture {#step-2-extend-the-test-instance}

Create `e2e/fixture.ts` to extend Playwright's `test` with `PlaywrightAiFixture`:

```typescript title="e2e/fixture.ts"
import { test as base } from '@playwright/test';
import {
  PlaywrightAiFixture,
  type PlayWrightAiFixtureType,
} from '@midscene/web/playwright';

export const test = base.extend<PlayWrightAiFixtureType>(
  PlaywrightAiFixture(),
);
```

In tests that use Midscene, import `test` from `./fixture` while continuing to import `expect` from `@playwright/test`.

## 3. Write a test

```typescript title="e2e/todo.spec.ts"
import { expect } from '@playwright/test';
import { test } from './fixture';

test('add a todo', async ({ page, aiAct, aiAssert }) => {
  await page.goto('https://todomvc.com/examples/react/dist/');
  await expect(page).toHaveTitle(/TodoMVC/);

  await aiAct('Add a todo named Try Midscene');
  await aiAssert('The todo list contains Try Midscene');
});
```

You can combine Playwright's `page` and `expect` with Midscene's AI methods in the same test. In this example, Playwright opens the page and checks its title, while Midscene adds a todo item and asserts the result on the page. Beyond `aiAct` and `aiAssert`, the fixture also provides `aiTap`, `aiInput`, `aiQuery`, `aiWaitFor`, and more; see the [Agent API reference](/reference/index.md#interaction-methods).

## 4. Run the test and view the report

(Optional) Verify your model configuration before running the test:

```bash
pnpm dlx @midscene/test@latest model verify
```

Run the test from the project directory:

```bash
pnpm exec playwright test e2e/todo.spec.ts
```

After the test finishes, the Midscene reporter prints the report path in the terminal (saved under `midscene_run/report/` by default). Open the generated HTML file in a browser to inspect step-by-step screenshots, AI execution details, and assertion results.

## Common methods

| Category           | Representative methods                         | Description                                                                                           |
| ------------------ | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| Auto-planning      | `aiAct`                                        | Describe a goal in natural language and let the Agent plan and execute multiple steps.                |
| Direct interaction | `aiTap`, `aiInput`                             | Locate a UI element by description and perform a single specified action without multi-step planning. |
| Data extraction    | `aiQuery`, `aiString`, `aiNumber`, `aiBoolean` | Extract structured or primitive data from the current UI for further processing in code.              |
| Assertions         | `aiAssert`                                     | Verify that the current UI meets an expectation; throws an error if it does not.                      |
| Waiting            | `aiWaitFor`                                    | Wait until the UI meets a specified condition; throws an error on timeout.                            |

In practice, you typically perform actions with `aiAct` or direct interaction methods and then verify the outcome with `aiAssert`—completing an action does not guarantee that the expected UI state was reached. For full parameter and return value details, see the [Agent API reference](/reference/index.md#interaction-methods).

## Further configuration

### Agent options {#agent-options}

Pass Agent options when creating the fixture:

```typescript title="e2e/fixture.ts"
import { test as base } from '@playwright/test';
import {
  PlaywrightAiFixture,
  type PlayWrightAiFixtureType,
} from '@midscene/web/playwright';

export const test = base.extend<PlayWrightAiFixtureType>(
  PlaywrightAiFixture({
    waitForNetworkIdleTimeout: 2000,
    replanningCycleLimit: 30,
  }),
);
```

You can also pass other Agent options such as `waitAfterAction` and `modelConfig`. Test and report metadata (`testId`, `reportFileName`, `groupName`, and `groupDescription`) are automatically derived from the current test info and do not need to be set manually. See [Playwright SDK configuration](/sdk/playwright.md#web-options) for platform options and [shared Agent options](/reference.md#agent-options) for common settings.

### Work with a specific page

The AI methods injected by the fixture operate on Playwright's default `page` fixture. To interact with another `Page` instance in the same test (such as one created via `context.newPage()`), use `agentForPage` to get the corresponding Agent:

```typescript
import { test } from './fixture';

test('inspect another page', async ({ context, agentForPage }) => {
  const page = await context.newPage();
  await page.goto('https://todomvc.com/examples/react/dist/');

  const agent = await agentForPage(page);
  await agent.aiAssert('The page contains a todo input');
});
```

For details on new tabs and navigation behavior, see [Web / Playwright SDK](/sdk/playwright.md#about-opening-in-a-new-tab).

### Lifecycle

Within a test, the fixture creates one Agent per `Page` and reuses it across AI calls. When a page closes or the test finishes, the fixture automatically calls `agent.destroy()` and collects the report, so you do not need to destroy fixture-managed Agents manually. Browser contexts and pages remain managed by Playwright.

If you bypass the fixture and instantiate an Agent directly with `new PlaywrightAgent(page)`, you must call `agent.destroy()` yourself; see [Lifecycle and resource ownership](/sdk/standalone.md#lifecycle-and-resource-ownership).

### Report options

Pass options to the reporter in `playwright.config.ts`:

```typescript
import { defineConfig } from '@playwright/test';

export default defineConfig({
  reporter: [
    ['list'],
    ['@midscene/web/playwright-reporter', {
      type: 'merged',
      outputFormat: 'single-html',
    }],
  ],
});
```

- `type`: `'merged'` (default) combines all tests into a single report; `'separate'` generates a separate report for each test.
- `outputFormat`: `'single-html'` (default) embeds execution data and screenshots in one HTML file for offline viewing; `'html-and-external-assets'` stores execution data and screenshots as external files.

When using `'html-and-external-assets'`, keep the HTML file and its asset directory in their relative paths, and preview the report through a local HTTP server (opening it directly via `file://` is not supported):

```bash
pnpm dlx serve midscene_run/report
```

Then open the URL printed in the terminal. When sharing or archiving the report, include both the HTML file and its asset directory.

For a complete working project, see the [Playwright Test example](https://github.com/web-infra-dev/midscene-example/tree/main/playwright-testing-demo).
