Skip to content

Commit

Permalink
docs: brush up writing tests section (#18861)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelfeldman committed Nov 17, 2022
1 parent b1acc0d commit f7b269d
Showing 1 changed file with 102 additions and 60 deletions.
162 changes: 102 additions & 60 deletions docs/src/writing-tests-js.md
Expand Up @@ -3,90 +3,149 @@ id: writing-tests
title: "Writing Tests"
---

Playwright assertions are created specifically for the dynamic web. Checks are automatically retried until the necessary conditions are met. Playwright comes with [auto-wait](./actionability.md) built in meaning it waits for elements to be actionable prior to performing actions. Playwright provides a [test](./api/class-test.md) function to declare tests and the [expect](https://jestjs.io/docs/expect) function to write assertions.
Playwright tests are simple, they

- **perform actions**, and
- **assert the state** against expectations.

There is no need to wait for anything prior to performing an action: Playwright
automatically waits for the wide range of [actionability](./actionability.md)
checks to pass prior to performing each action.

There is also no need to deal with the race conditions when performing the checks -
Playwright assertions are designed in a way that they describe the expectations
that need to be eventually met.

That's it! These design choices allow Playwright users to forget about flaky
timeouts and racy checks in their tests altogether.

**You will learn**

- [How the example test works](/writing-tests.md#the-example-test)
- [How to write the first test](/writing-tests.md#first-test)
- [How to perform actions](/writing-tests.md#actions)
- [How to use assertions](/writing-tests.md#assertions)
- [How to use locators](/writing-tests.md#locators)
- [How tests run in isolation](/writing-tests.md#test-isolation)
- [How to use test hooks](/writing-tests.md#using-test-hooks)

## The Example Test
## First test

Take a look at the example test included when installing Playwright to see how to write a test using [locators](/locators.md) and [web first assertions](/test-assertions.md).
Take a look at the following example to see how to write a test.

```js tab=js-js
// @ts-check
const { test, expect } = require('@playwright/test');
```js
import { test, expect } = require('@playwright/test');

test('homepage has Playwright in title and get started link linking to the intro page', async ({ page }) => {
test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');

// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
});

// create a locator
const getStarted = page.getByRole('link', { name: 'Get started' });

// Expect an attribute "to be strictly equal" to the value.
await expect(getStarted).toHaveAttribute('href', '/docs/intro');
test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');

// Click the get started link.
await getStarted.click();
await page.getByRole('link', { name: 'Get started' }).click();

// Expects the URL to contain intro.
await expect(page).toHaveURL(/.*intro/);
});
```

```js tab=js-ts
import { test, expect } from '@playwright/test';
:::note
Add `// @ts-check` at the start of each test file when using JavaScript in
VS Code to get automatic type checking.
:::

test('homepage has Playwright in title and get started link linking to the intro page', async ({ page }) => {
await page.goto('https://playwright.dev/');
## Actions

// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
### Navigation

// create a locator
const getStarted = page.getByRole('link', { name: 'Get started' });
Most of the tests will start with navigating page to the URL. After that, test
will be able to interact with the page elements.

// Expect an attribute "to be strictly equal" to the value.
await expect(getStarted).toHaveAttribute('href', '/docs/intro');
```js
await page.goto('https://playwright.dev/');
```

// Click the get started link.
await getStarted.click();
Playwright will wait for page to reach the load state prior to moving forward.
Learn more about the [`method: Page.goto`] options.

// Expects the URL to contain intro.
await expect(page).toHaveURL(/.*intro/);
});
### Interactions

Performing actions starts with locating the elements. Playwright uses
[Locators API](./locators.md) for that. Locators represent a way to find
element(s) on the page at any moment, learn more about the
[different types](./locators.md) of locators available. Playwright will wait for the element to be [actionable](./actionability.md)
prior to performing the action, so there is no need to need wait for it to become
available.


```js
// Create a locator.
const getStarted = page.getByRole('link', { name: 'Get started' });
// Click it.
await getStarted.click();
```

:::note
Add `// @ts-check` at the start of each test file when using JavaScript in VS Code to get automatic type checking.
:::
In most cases, it'll be written in one line:

### Assertions
```js
await page.getByRole('link', { name: 'Get started' }).click();
```


### Basic actions

This is the list of the most popular Playwright actions. Note that there are
many more, so make sure to check the [Locator API](./api/class-locator.md) section to
learn more about them.

| Action | Description |
| :- | :- |
| [`method: Locator.check`] | Check the input checkbox |
| [`method: Locator.click`] | Click the element |
| [`method: Locator.uncheck`] | Uncheck the input checkbox |
| [`method: Locator.hover`] | Hover mouse over the element |
| [`method: Locator.fill`] | Fill the form field (fast) |
| [`method: Locator.focus`] | Focus the element |
| [`method: Locator.press`] | Press single key |
| [`method: Locator.setInputFiles`] | Pick files to upload |
| [`method: Locator.selectOption`] | Select option in the drop down |
| [`method: Locator.type`] | Type text character by character (slow) |

## Assertions

Playwright Test uses the [expect](https://jestjs.io/docs/expect) library for [test assertions](./test-assertions.md) which provides matchers like `toEqual`, `toContain`, `toMatch`, `toBe` and many more. Playwright also extends this library with convenience async matchers that will wait until the expected condition is met.
Playwright Test uses the [expect](https://jestjs.io/docs/expect) library for
[test assertions](./test-assertions.md) which provides matchers like
`toEqual`, `toContain`, `toMatch`, `toBe` and many more. It also extends
this library with the convenience async matchers that will wait until the expected condition is met.
Using these matchers allows making the tests non-flaky and resilient. For example, this code will wait until
the page gets the title containing "Playwright":

```js
await expect(page).toHaveTitle(/Playwright/);
```


### Locators

[Locators](./locators.md) are the central piece of Playwright's auto-waiting and retry-ability. Locators represent a way to find element(s) on the page at any moment and are used to perform actions on elements such as `.click` `.fill` etc.
Here is the list of the most popular async assertions. Note that there are [many more](./test-assertions.md) to get familiar with:

```js
const getStarted = page.getByRole('link', { name: 'Get started' });
| Assertion | Description |
| :- | :- |
| [`method: LocatorAssertions.toBeChecked`] | Checkbox is checked |
| [`method: LocatorAssertions.toBeChecked`] | Checkbox is checked |
| [`method: LocatorAssertions.toBeEnabled`] | Control is enabled |
| [`method: LocatorAssertions.toBeVisible`] | Element is visible |
| [`method: LocatorAssertions.toContainText`] | Element contains text |
| [`method: LocatorAssertions.toHaveAttribute`] | Element has attribute |
| [`method: LocatorAssertions.toHaveCount`] | List of elements has given length |
| [`method: LocatorAssertions.toHaveText`] | Element matches text |
| [`method: LocatorAssertions.toHaveValue`] | Input element has value |
| [`method: PageAssertions.toHaveTitle`] | Page has title |
| [`method: PageAssertions.toHaveURL`] | Page has URL |
| [`method: PageAssertions.toHaveScreenshot#1`] | Page has screenshot |

await expect(getStarted).toHaveAttribute('href', '/docs/installation');
await getStarted.click();
```

### Test Isolation

Expand All @@ -101,24 +160,7 @@ test('basic test', async ({ page }) => {
You can use various [test hooks](./api/class-test.md) such as `test.describe` to declare a group of tests and `test.beforeEach` and `test.afterEach` which are executed before/after each test. Other hooks include the `test.beforeAll` and `test.afterAll` which are executed once per worker before/after all tests.
```js tab=js-js
// @ts-check
const { test, expect } = require("@playwright/test");

test.describe("navigation", () => {
test.beforeEach(async ({ page }) => {
// Go to the starting url before each test.
await page.goto("https://playwright.dev/");
});

test("main navigation", async ({ page }) => {
// Assertions use the expect API.
await expect(page).toHaveURL("https://playwright.dev/");
});
});
```
```js tab=js-ts
```js
import { test, expect } from "@playwright/test";

test.describe("navigation", () => {
Expand Down

0 comments on commit f7b269d

Please sign in to comment.