Skip to content

Commit

Permalink
Update the E2E tests documentation page (#48951)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mamaduka committed Mar 9, 2023
1 parent b0e96c4 commit 9a3439e
Showing 1 changed file with 14 additions and 27 deletions.
41 changes: 14 additions & 27 deletions docs/contributors/code/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

This living document serves to prescribe instructions and best practices for writing end-to-end (E2E) tests with Playwright in the Gutenberg project.

> **Note**
> See the dedicated guide if you're working with the previous Jest + Puppeteer framework. See the [migration guide](https://github.com/WordPress/gutenberg/tree/HEAD/docs/contributors/code/e2e/migration.md) if you're migrating tests from Jest + Puppeteer.
<div class="callout callout-info">

See the dedicated guide if you're working with the previous Jest + Puppeteer framework. See the [migration guide](https://github.com/WordPress/gutenberg/tree/HEAD/docs/contributors/code/e2e/migration.md) if you're migrating tests from Jest + Puppeteer.
</div>


## Running tests

Expand Down Expand Up @@ -38,14 +41,11 @@ xvfb-run -- npm run test:e2e:playwright -- --project=webkit

Read the [best practices](https://playwright.dev/docs/best-practices) guide for Playwright.

<details>
<summary><h3>Forbid `$`, use `locator` instead</h3></summary>
### Forbid `$`, use `locator` instead

In fact, any API that returns `ElementHandle` is [discouraged](https://playwright.dev/docs/api/class-page#page-query-selector). This includes `$`, `$$`, `$eval`, `$$eval`, etc. [`Locator`](https://playwright.dev/docs/api/class-locator) is a much better API and can be used with playwright's [assertions](https://playwright.dev/docs/api/class-locatorassertions). This also works great with Page Object Model since that locator is lazy and doesn't return a promise.
</details>

<details>
<summary><h3>Use accessible selectors</h3></summary>
### Use accessible selectors

Use [`getByRole`](https://playwright.dev/docs/locators#locate-by-role) to construct the query wherever possible. It enables us to write accessible queries without having to rely on internal implementations.

Expand All @@ -63,45 +63,32 @@ page.getByRole( 'region', { name: 'Block Library' } )
```

See the [official documentation](https://playwright.dev/docs/locators) for more info on how to use them.
</details>

<details>
<summary><h3>Selectors are strict by default</h3></summary>
### Selectors are strict by default

To encourage better practices for querying elements, selectors are [strict](https://playwright.dev/docs/api/class-browser#browser-new-page-option-strict-selectors) by default, meaning that it will throw an error if the query returns more than one element.
</details>

<details>
<summary><h3>Don't overload test-utils, inline simple utils</h3></summary>
### Don't overload test-utils, inline simple utils

`e2e-test-utils` are too bloated with too many utils. Most of them are simple enough to be inlined directly in tests. With the help of accessible selectors, simple utils are easier to write now. For utils that only take place on a certain page, use Page Object Model instead (with an exception of clearing states with `requestUtils` which are better placed in `e2e-test-utils`). Otherwise, only create an util if the action is complex and repetitive enough.
</details>

<details>
<summary><h3>Favor Page Object Model over utils</h3></summary>
### Favor Page Object Model over utils

As mentioned above, [Page Object Model](https://playwright.dev/docs/test-pom) is the preferred way to create reusable utility functions on a certain page.

The rationale behind using a POM is to group utils under namespaces to be easier to discover and use. In fact, `PageUtils` in the `e2e-test-utils-playwright` package is also a POM, which avoids the need for global variables, and utils can reference each other with `this`.
</details>

<details>
<summary><h3>Restify actions to clear or set states</h3></summary>
### Restify actions to clear or set states

It's slow to set states manually before or after tests, especially when they're repeated multiple times between tests. It's recommended to set them via API calls. Use `requestUtils.rest` and `requestUtils.batchRest` instead to call the [REST API](https://developer.wordpress.org/rest-api/reference/) (and add them to `requestUtils` if needed). We should still add a test for manually setting them, but that should only be tested once.
</details>

<details>
<summary><h3>Avoid global variables</h3></summary>
### Avoid global variables

Previously in our Jest + Puppeteer E2E tests, `page` and `browser` are exposed as global variables. This makes it harder to work with when we have multiple pages/tabs in the same test, or if we want to run multiple tests in parallel. `@playwright/test` has the concept of [fixtures](https://playwright.dev/docs/test-fixtures) which allows us to inject `page`, `browser`, and other parameters into the tests.
</details>

<details>
<summary><h3>Make explicit assertions</h3></summary>
### Make explicit assertions

We can insert as many assertions in one test as needed. It's better to make explicit assertions whenever possible. For instance, if we want to assert that a button exists before clicking on it, we can do `expect( locator ).toBeVisible()` before performing `locator.click()`. This makes the tests flow better and easier to read.
</details>
We can insert as many assertions in one test as needed. It's better to make explicit assertions whenever possible. For instance, if we want to assert that a button exists before clicking on it, we can do `expect( locator ).toBeVisible()` before performing `locator.click()`. This makes the tests flow better and easier to read

## Common pitfalls

Expand Down

0 comments on commit 9a3439e

Please sign in to comment.