v1.39.0

microsoft/playwrightv1.39.0Oct 11, 2023by dgozman

AI Summary

Introduced custom matchers, fixture merging, and 'boxed' test steps to hide implementation details. Added toHaveAttribute matcher.

Key Highlights

  • Custom matchers via expect.extend
  • Merge test fixtures and custom matchers from multiple files
  • Boxed test steps to point errors to the call site

New Features

  • Custom matchers
  • mergeTests() function
  • mergeExpects() function
  • Boxed test steps
  • expect(locator).toHaveAttribute(name)

Full Release Notes

## Add custom matchers to your expect

You can extend Playwright assertions by providing custom matchers. These matchers will be available on the expect object.

```js
import { expect as baseExpect } from '@playwright/test';
export const expect = baseExpect.extend({
  async toHaveAmount(locator: Locator, expected: number, options?: { timeout?: number }) {
    // ... see documentation for how to write matchers.
  },
});

test('pass', async ({ page }) => {
  await expect(page.getByTestId('cart')).toHaveAmount(5);
});
```

See the documentation [for a full example](https://playwright.dev/docs/test-configuration#add-custom-matchers-using-expectextend).

## Merge test fixtures

You can now merge test fixtures from multiple files or modules:

```js
import { mergeTests } from '@playwright/test';
import { test as dbTest } from 'database-test-utils';
import { test as a11yTest } from 'a11y-test-utils';

export const test = mergeTests(dbTest, a11yTest);
```

```js
import { test } from './fixtures';

test('passes', async ({ database, page, a11y }) => {
  // use database and a11y fixtures.
});
```

## Merge custom expect matchers

You can now merge custom expect matchers from multiple files or modules:

```js
import { mergeTests, mergeExpects } from '@playwright/test';
import { test as dbTest, expect as dbExpect } from 'database-test-utils';
import { test as a11yTest, expect as a11yExpect } from 'a11y-test-utils';

export const test = mergeTests(dbTest, a11yTest);
export const expect = mergeExpects(dbExpect, a11yExpect);
```

```js
import { test, expect } from './fixtures';

test('passes', async ({ page, database }) => {
  await expect(database).toHaveDatabaseUser('admin');
  await expect(page).toPassA11yAudit();
});
```

## Hide implementation details: box test steps

You can mark a [`test.step()`](https://playwright.dev/docs/api/class-test#test-step) as "boxed" so that errors inside it point to the step call site.

```js
async function login(page) {
  await test.step('login', async () => {
    // ...
  }, { box: true });  // Note the "box" option here.
}
```

```txt
Error: Timed out 5000ms waiting for expect(locator).toBeVisible()
  ... error details omitted ...

  14 |   await page.goto('https://github.com/login');
> 15 |   await login(page);
     |         ^
  16 | });
```

See [`test.step()`](https://playwright.dev/docs/api/class-test#test-step) documentation for a full example.

## New APIs

- [`expect(locator).toHaveAttribute(name)`](https://playwright.dev/docs/api/class-locatorassertions#locator-assertions-to-have-attribute-2)

## Browser Versions

* Chromium 119.0.6045.9
* Mozilla Firefox 118.0.1
* WebKit 17.4

This version was also tested against the following stable channels:

* Google Chrome 118
* Microsoft Edge 118