> ## Documentation Index
> Fetch the complete documentation index at: https://checklyhq.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Playwright Support in Checkly

Checkly natively supports running complex browser checks that mimic real user actions using Playwright, the best automation framework. Playwright and Checkly together elevate your monitoring and debugging experience by providing:

* Detailed trace files with step-by-step information on your test cases
* Video recordings of browser sessions
* Automatic `awaits` for reliable automation
* Diverse set of assertions like `toContainText()`, `toHaveURL()`
* Easy to use locators like `getByTitle`, `getByRole`
* Visual regression testing

## Features

This is the list of Playwright features that are currently supported. We will update it as more features become supported.

| Feature                  | Supported?                                                                                                                  |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
| Trace files              | Yes                                                                                                                         |
| Video recordings         | Yes                                                                                                                         |
| API testing              | Yes                                                                                                                         |
| Custom fixtures          | Yes                                                                                                                         |
| Reporters                | JSON                                                                                                                        |
| Typescript               | Yes                                                                                                                         |
| Global configuration     | Yes, a subset of playwright config options.                                                                                 |
| Visual comparisons       | Yes                                                                                                                         |
| Test retry               | No, enable Checkly's ["Double-check on failure"](/communicate/alerts/configuration) in the check settings to retry a check. |
| Parallelism and sharding | No                                                                                                                          |

## Supported configuration options

We currently support the following configuration options. We will update this list as more options become supported.

> We do not support the `projects`, `globalSetup`, `globalTeardown` and `storageState` options yet, but will in a future release.

<Tabs>
  <Tab title="Global">
    | Option           | Supported |
    | ---------------- | --------- |
    | `timeout`        | ✅         |
    | `use`            | ✅         |
    | `expect`         | ✅         |
    | `testDir`        | ❌         |
    | `fullyParallel`  | ❌         |
    | `forbidOnly`     | ❌         |
    | `retries`        | ❌         |
    | `workers`        | ❌         |
    | `reporter`       | ❌         |
    | `testMatch`      | ❌         |
    | `testIgnore`     | ❌         |
    | `outputDir`      | ❌         |
    | `globalSetup`    | ❌         |
    | `globalTeardown` | ❌         |
    | `projects`       | ❌         |
    | `webServer`      | ❌         |

    For more information about the `global` options you can check playwright official documentation [Test configuration](https://playwright.dev/docs/test-configuration)
  </Tab>

  <Tab title="Use">
    | Option               | Supported |
    | -------------------- | --------- |
    | `baseURL`            | ✅         |
    | `colorScheme`        | ✅         |
    | `geolocation`        | ✅         |
    | `locale`             | ✅         |
    | `permissions`        | ✅         |
    | `timezoneId`         | ✅         |
    | `viewport`           | ✅         |
    | `deviceScaleFactor`  | ✅         |
    | `hasTouch `          | ✅         |
    | `isMobile `          | ✅         |
    | `javaScriptEnabled ` | ✅         |
    | `extraHTTPHeaders`   | ✅         |
    | `httpCredentials`    | ✅         |
    | `ignoreHTTPSErrors`  | ✅         |
    | `offline`            | ✅         |
    | `actionTimeout`      | ✅         |
    | `navigationTimeout ` | ✅         |
    | `testIdAttribute`    | ✅         |
    | `connectOptions`     | ✅         |
    | `contextOptions`     | ✅         |
    | `bypassCSP`          | ✅         |
    | `proxy`              | ✅         |
    | `launchOptions`      | ❌         |
    | `storageState`       | ❌         |
    | `browserName`        | ❌         |
    | `channel`            | ❌         |
    | `headless`           | ❌         |
    | `screenshot`         | ❌         |
    | `trace`              | ❌         |
    | `video`              | ❌         |

    For more information about the `use` options you can check playwright official documentation [Test use options](https://playwright.dev/docs/test-use-options)
  </Tab>

  <Tab title="Expect">
    | Option              | Supported |
    | ------------------- | --------- |
    | `timeout`           | ✅         |
    | `toHaveScreenshot ` | ✅         |
    | `toMatchSnapshot `  | ✅         |

    For more information about the `expect` options you can check playwright official documentation [Test Expect options](https://playwright.dev/docs/test-configuration#expect-options)
  </Tab>
</Tabs>

<Warning>
  A check using [the Playwright Test Runner (`@playwright/test`)](https://playwright.dev/docs/intro) will currently run around 30-50% longer than [a regular Playwright check (`playwright`)](https://playwright.dev/docs/library). This is caused by the automatic creation of trace and video assets. We are aware of this and are investigating solutions. If this is significantly degrading the performance of your check, we recommend to divide longer tests into multiple checks.
</Warning>

## Hooks

Playwright Test Runner offers hook functions such as `test.afterEach()` and `test.beforeEach()` that run before or after individual test cases or `test.afterAll()` and `test.beforeAll()` that run before or after all tests have started/finished.

You can find more information on available methods in the [official documentation](https://playwright.dev/docs/api/class-test).

## Viewing trace files

When a `@playwright/test` test case fails, Checkly will record and make its trace files available via the UI. You can download the trace files for manual inspection or view them directly with [trace.playwright.dev](https://trace.playwright.dev).

Using the Playwright Trace Viewer you can effortlessly view your test, skip back and forth between actions, view snapshots and metadata, and more. This makes it very easy to inspect individual traces and debug failing tests.

<video controls className="w-full aspect-video rounded-xl" src="https://mintcdn.com/checkly-422f444a/YgQcQD6j5p9gqjr5/images/docs/images/browser-checks/pwt_traces.mp4?fit=max&auto=format&n=YgQcQD6j5p9gqjr5&q=85&s=1d6f06c53baa97023d468029a087abe5" data-path="images/docs/images/browser-checks/pwt_traces.mp4" />

When running tests from the editor page, trace files are always available for download and preview,
regardless of whether the check is passing or failing. For scheduled check runs traces are only preserved when the check failed.

## Video recordings

When a `@playwright/test` test case fails, Checkly will record a video for each page navigation and make it available in the UI. It is a great tool to get a first look of the actions and their outcome to quickly identify what failed, and to visualize regressions.

Here's an example of a Playwright Test script that fails, and provides a video of the test sequence.

<video controls className="w-full aspect-video rounded-xl" src="https://mintcdn.com/checkly-422f444a/YgQcQD6j5p9gqjr5/images/docs/images/browser-checks/pwt_videos.mp4?fit=max&auto=format&n=YgQcQD6j5p9gqjr5&q=85&s=80dd80539de18f78e70f602ae9484583" data-path="images/docs/images/browser-checks/pwt_videos.mp4" />

When running tests from the editor page, video files are always available for download and preview, regardless of whether
the check is passing or failing. For scheduled check runs videos are only preserved when the check failed.

## PageObject Model (POM)

If you are structuring your test codebase following the [PageObject pattern](https://martinfowler.com/bliki/PageObject.html), you can use the [Checkly CLI](/cli) out of the box. Just make sure that:

* the folder you initialize your CLI in when building your project sits above your test spec files and their dependencies
* your `testMatch` is pointing to the path(s) where your test specs live

To see one way this can look like, see our [example repository](https://github.com/checkly/checkly-sample-pom).

## Global configuration

We are gradually rolling out support for global configuration options for the Playwright Test Runner. This allows you to
configure your Playwright tests in a single place, instead of having to repeat the same configuration for each test file.

There are three things you should be aware of:

1. You can only use a subset of the Playwright config options. See the [supported configuration options](#supported-configuration-options) section for more information.
2. You need to add the `playwrightConfig` section to your `checkly.config.ts` file, nested under the `browserChecks` section.
3. We explicitly do not read from the existing `playwright.config.ts` or `playwright.config.js` file in your project. This is to avoid any confusion about which config file is used to run your tests and to prevent any unexpected behaviour.

If you have an existing `playwright.config.ts` or `playwright.config.js` file in your project that you want to import,
you can simply run the [sync-playwright](/cli/checkly-sync-playwright)

```bash theme={null}
npx checkly sync-playwright
```

This command will add currently supported Playwright config option to your `checkly.config.ts` file.

<Tabs>
  <Tab title="TypeScript">
    ```typescript checkly.config.ts theme={null}
    import { defineConfig } from 'checkly'

    export default defineConfig({
    projectName: 'Website Monitoring',
    logicalId: 'website-monitoring-1',
    repoUrl: 'https://github.com/acme/website',
    checks: {
    checkMatch: '**/*.check.js',
    playwrightConfig: {         // note the extra playwrightConfig section
      timeout: 1234,
      use: {
        baseURL: 'https://www.checklyhq.com',
        isMobile: true,
      },
      expect: {
        toHaveScreenshot: {
          maxDiffPixels: 10,
        }
      }
    },
    browserChecks: {
      testMatch: '**/*.spec.js',
    },
    },
    cli: {
    runLocation: 'eu-west-1',
    privateRunLocation: 'private-dc1'
    }
    })
    ```
  </Tab>

  <Tab title="JavaScript">
    ```js checkly.config.js theme={null}
    const { defineConfig } = require('checkly')

    const config = defineConfig({
    projectName: 'Website Monitoring',
    logicalId: 'website-monitoring-1',
    repoUrl: 'https://github.com/acme/website',
    checks: {
    checkMatch: '**/*.check.js',
    playwrightConfig: {           // note the extra playwrightConfig section
      timeout: 1234,
      use: {
        baseURL: 'https://www.checklyhq.com',
        isMobile: true,
      },
      expect: {
        toHaveScreenshot: {
          maxDiffPixels: 10,
        }
      }
    },
    browserChecks: {
      testMatch: '**/*.spec.js',
    },
    },
    cli: {
    runLocation: 'eu-west-1',
    privateRunLocation: 'private-dc1'
    }
    })

    module.exports = config;
    ```
  </Tab>
</Tabs>

## Multi Test Checks

One of the key benefits of using Playwright Test is that you can split your check into multiple independent test cases, and group them using the `test.describe` function. Your Checkly check will fail if **at least one** of the test cases fails.

<Tabs>
  <Tab title="TypeScript">
    ```ts example.spec.ts theme={null}
    import { test } from '@playwright/test';

    test.describe('two tests', () => {
    test('one', async ({ page }) => {
    // ...
    })

    test('two', async ({ page }) => {
    // ...
    })
    })
    ```
  </Tab>

  <Tab title="JavaScript">
    ```js example.spec.js theme={null}
    const { test } = require('@playwright/test')

    test.describe('two tests', () => {
    test('one', async ({ page }) => {
    // ...
    })

    test('two', async ({ page }) => {
    // ...
    })
    })
    ```
  </Tab>
</Tabs>

<Note> An executed browser check that includes multiple Playwright test cases still counts as a single check run towards your pricing plan's defined limits.</Note>

## Interactions & Navigations

### Page Interactions

```typescript theme={null}
// Navigation
await page.goto('https://example.com')
await page.goBack()
await page.reload()

// Element interactions
await page.click('button[type="submit"]')
await page.fill('input[name="email"]', 'test@example.com')
await page.selectOption('select[name="country"]', 'US')
await page.check('input[type="checkbox"]')

// Keyboard and mouse actions
await page.keyboard.press('Enter')
await page.mouse.click(100, 200)
await page.hover('.tooltip-trigger')

// File operations
await page.setInputFiles('input[type="file"]', './document.pdf')
```

### Element Selection Strategies

```typescript theme={null}
// By test ID (recommended)
await page.click('[data-testid="submit-button"]')

// By text content
await page.click('text=Submit Order')

// By CSS selector
await page.click('.btn-primary')

// By XPath
await page.click('//button[@class="submit-btn"]')

// By role and name
await page.click('role=button[name="Submit"]')
```

## Assertions and Validation

### Page Content Assertions

```typescript theme={null}
// Text content validation
await expect(page.locator('.success-message')).toHaveText('Order confirmed')
await expect(page).toHaveTitle('Dashboard - MyApp')

// Element visibility
await expect(page.locator('.loading-spinner')).toBeHidden()
await expect(page.locator('.user-profile')).toBeVisible()

// URL validation
await expect(page).toHaveURL('https://app.example.com/dashboard')
await expect(page).toHaveURL(/.*checkout\/success/)

// Element attributes
await expect(page.locator('input[name="email"]')).toHaveValue('user@example.com')
await expect(page.locator('.status-badge')).toHaveClass('status-active')
```

### Custom Validation Logic

```typescript theme={null}
// Complex assertions with custom logic
const orderTotal = await page.locator('[data-testid="order-total"]').textContent()
const expectedTotal = '$99.99'
expect(orderTotal).toBe(expectedTotal)


// Validate array of elements

const productTitles = await page.locator('.product-title').allTextContents()
expect(productTitles).toContain('Premium Plan')
expect(productTitles).toHaveLength(3)

```

## Advanced Features

### Screenshots and Visual Testing

Browser checks can take screenshots of the page and compare them to a baseline. This is useful for visual regression testing.

```typescript theme={null}
// Full page screenshot
await page.screenshot({ path: 'dashboard.png', fullPage: true })

// Element screenshot
await page.locator('.product-card').screenshot({ path: 'product.png' })

// Visual comparison (with setup)
await expect(page).toHaveScreenshot('homepage.png')
```

### Mobile Device Simulation

```typescript theme={null}
// Test responsive design
test('Mobile checkout workflow', async ({ page }) => {
  // Simulate iPhone 12
  await page.setViewportSize({ width: 390, height: 844 })

  // Test mobile-specific interactions
  await page.goto('https://shop.example.com')
  await page.click('[data-testid="mobile-menu-toggle"]')
  await expect(page.locator('.mobile-nav')).toBeVisible()
})
```

### Multi-Tab and Context Handling

```typescript theme={null}
// Handle multiple tabs
const [newPage] = await Promise.all([
  context.waitForEvent('page'),
  page.click('a[target="_blank"]')
])

await newPage.waitForLoadState()
await expect(newPage).toHaveTitle('External Service')
```

### Authentication and Session Management

```typescript theme={null}
// Login once and reuse session
test('Setup authentication', async ({ page }) => {
  await page.goto('https://app.example.com/login')
  await page.fill('[name="email"]', process.env.TEST_EMAIL)
  await page.fill('[name="password"]', process.env.TEST_PASSWORD)
  await page.click('[type="submit"]')

  // Save authentication state
  await page.context().storageState({ path: 'auth-state.json' })
})

// Use saved authentication
test.use({ storageState: 'auth-state.json' })
test('Authenticated user workflow', async ({ page }) => {
  // User is already logged in
  await page.goto('https://app.example.com/dashboard')
  await expect(page.locator('.welcome-message')).toBeVisible()
})
```
