---
title: "How to add Playwright tests"
---

> Documentation Index
> Fetch the complete documentation index at: https://contribute.freecodecamp.org/llms.txt
> Use this file to discover all available pages before exploring further.

# How to add Playwright tests

:::tip
You'll need this guide if you're adding or modifying end-to-end tests, or if your contribution changes user-facing behavior that requires test coverage. If you're only fixing a typo or updating documentation, you can skip this guide.
:::

## Installation

Playwright is installed with the repository dependencies, but its browser binaries must be installed separately. Run this command before your first local test run and after Playwright is upgraded. On Linux, it also installs the required system dependencies:

```bash
pnpm run playwright:install-build-tools
```

To learn how to write Playwright tests, or 'specs', please see Playwright's official [documentation](https://playwright.dev/docs/writing-tests).

## Where to Add a Test

- Playwright tests are in the `./e2e` directory.

- Standard Playwright test specs use the `.spec.ts` extension.

## Best Practices for writing E2E tests

This section will explain in detail about best practices for writing and documenting E2E tests based on Playwright documentation and our community code-style.

### Imports

Import `test` and `expect` from `@playwright/test` for tests that do not change user data:

For example:

```ts
import { test, expect } from '@playwright/test';
```

Tests that change user data should use the isolated-user fixture. It creates a separate user for the test and deletes that user afterward. Import `test` and `expect` from the fixture, then select a user preset if the test needs one:

```ts
import { test, expect } from './fixtures/isolated-user';

test.use({ userPreset: 'certified' });
```

### Identifying a DOM element

Playwright comes with [multiple built-in locators](https://playwright.dev/docs/locators#quick-guide), but we recommend prioritizing the following locators:

- `getByRole` for querying semantic elements, whose role is important and allows assistive technology to perceive the page correctly.
- `getByLabel` for querying form controls by their associated label.
- `getByPlaceholder` for querying form controls when no label is available.
- `getByAltText` for querying images and other elements by their alternative text.
- `getByText` for querying non-semantic elements such as `div`, `span`, or `p`.

For example:

```ts
await expect(page.getByRole('heading', { name: 'Sign up' })).toBeVisible();
await expect(page.getByText('Hello World')).toBeVisible();
```

If an element cannot be queried with an appropriate user-facing locator, you can use the `data-playwright-test-label` attribute as a last resort. This attribute should be used only in Playwright tests, and not for styling or any other purposes.

For example:

```html
<div data-playwright-test-label="landing-page-figure">
  <img src="..." alt="..." />
</div>
```

In the test file, you can use the `getByTestId` method to identify the element.

For example:

```ts
await expect(page.getByTestId('landing-page-figure')).toBeVisible();
```

### Constants

Define any constant elements, data sets, or configurations used throughout your tests for easy reference.

For example:

```ts
const landingPageElements = { ... };
const superBlocks = [ ... ];
```

### Descriptive test names

Each test block should have a clear and concise name describing exactly what it's testing.

For example:

```ts
test('The component landing-top renders correctly', async ({ page }) => {
  // ...
});
```

### Human readable assertions

Each assertion should be as human readable as possible. This makes it easier to understand what the test is doing and what it's expecting.

For example:

```ts
await expect(
  page.getByRole('heading', { level: 1, name: 'Learn to code — for free.' })
).toBeVisible();
```

### Keep it DRY

Make sure that the tests are not repeating the same code over and over again. If you find yourself repeating the same code, consider refactoring it as a loop or a function.

For example:

```ts
const expectedLogoCount = 3;
await expect(logos).toHaveCount(expectedLogoCount);

for (const logo of await logos.all()) {
  await expect(logo).toBeVisible();
}
```

### Tests for mobile screens

Use the `isMobile` argument to test logic that is specific to mobile devices.

For example:

```ts
test('The campers landing page figure is visible on desktop and hidden on mobile view', async ({
  page,
  isMobile
}) => {
  const landingPageFigure = page.getByTestId('landing-page-figure');

  if (isMobile) {
    await expect(landingPageFigure).toBeHidden();
  } else {
    await expect(landingPageFigure).toBeVisible();
  }
});
```

### Group related tests

Group related tests together using `test.describe` blocks. This makes it easier to understand what the tests are doing and what they're testing.

For example:

```ts
test.describe('The campers landing page', () => {
  test('The campers landing page figure is visible on desktop and hidden on mobile view', async ({
    isMobile
  }) => {
    // ...
  });

  test('The campers landing page figure has the correct image', async () => {
    // ...
  });
});
```

## How to Run Tests

### Ensure that MongoDB and Client Applications are Running

- [Start MongoDB and seed the database](/how-to-setup-freecodecamp-locally/#start-the-app).

- [Start the freeCodeCamp client application and API server](/how-to-setup-freecodecamp-locally/#start-the-app)

Playwright's setup project creates the shared certified and development users before the tests run. Tests that import the isolated-user fixture create and remove their own users.

### Run the Playwright Tests

To run tests with Playwright, check the following commands:

- To run tests in UI mode:

  ```bash
  pnpm playwright:watch
  ```

- To run a single test:

  ```bash
  pnpm playwright:run <filename>
  ```

  For example:

  ```bash
  pnpm playwright:run landing.spec.ts
  ```

- To run a set of test files:

  ```bash
  pnpm playwright:run <filename1> <filename2>
  ```

  For example:

  ```bash
  pnpm playwright:run action-row.spec.ts landing.spec.ts
  ```

- Run the test with the title:

  ```bash
  pnpm playwright:run -g "<title>"
  ```

  For example:

  ```bash
  pnpm playwright:run -g "add a todo item"
  ```

### Debugging Tests

Since Playwright runs in Node.js, you can debug it with your debugger of choice e.g. using console.log or inside your IDE

- Debugging all tests:

  ```bash
  pnpm playwright:run --debug
  ```

- Debugging one test file:

  ```bash
  pnpm playwright:run example.spec.ts --debug
  ```

### Generate Test Reports

The HTML Reporter shows you a full report of your tests allowing you to filter the report by browsers, passed tests, failed tests, skipped tests and flaky tests.

```bash
pnpm --dir e2e exec playwright show-report playwright/reporter
```

### Troubleshooting

- Playwright reports a connection error when the client is not available at its configured base URL. The default URL is `http://127.0.0.1:8000`.

  ```bash
    Error: page.goto: Could not connect: Connection refused
    =========================== logs ===========================
    navigating to "http://127.0.0.1:8000/", waiting until "load"
    ============================================================
  ```

  Check these items before running the test again:

1. Confirm that the client and API are running.
2. Open `http://127.0.0.1:8000` in your browser.
3. If you changed `HOME_LOCATION`, confirm that it points to the running client.

For other errors, see Playwright's [test debugging guide](https://playwright.dev/docs/debug).

## Set up for Playwright on GitHub Codespaces

### Ensure Development Environment is Running

Follow the [GitHub Codespaces setup instructions](/how-to-setup-freecodecamp-locally/#choose-where-to-run-freecodecamp). The codespace creates `.env`, starts MongoDB and Mailpit, and seeds the database. Playwright creates its test users when the tests run.

Start the client and API if they are not already running:

```bash
pnpm run develop
```

### Install Playwright Build Tools

To install necessary dependencies for running Playwright run the following command:

```bash
pnpm run playwright:install-build-tools
```

### Run the Playwright Tests on GitHub Codespaces

To run all Playwright tests, run the following command:

```bash
pnpm playwright:run
```

Source: https://contribute.freecodecamp.org/how-to-add-playwright-tests/index.mdx
