DEV Community

Cover image for End-to-End Testing React Components with Playwright: (Part 1)
Samuel Kinuthia
Samuel Kinuthia

Posted on

End-to-End Testing React Components with Playwright: (Part 1)

End-to-end (E2E) testing is essential for ensuring that a web application behaves correctly from a user's perspective. While unit tests and integration tests focus on specific parts of an application, E2E tests verify that the entire application flow works as expected. Playwright, developed by Microsoft, is a modern testing framework that excels in automating browser interactions for E2E testing. This guide will delve into how to set up and utilize Playwright for testing React components, covering everything from basic setup to advanced features.


1. Introduction to Playwright

Playwright is an open-source testing framework designed to handle modern web applications' complexities. It offers several advantages for E2E testing:

  • Cross-Browser Testing: Playwright supports multiple browsers (Chromium, Firefox, and WebKit) and allows you to test across different platforms and devices.
  • Automated Interaction: With Playwright, you can simulate user interactions such as clicks, typing, and form submissions.
  • Network Interception: Mock and inspect network requests to simulate different server responses and test various scenarios.
  • Headless Mode: Run tests in headless mode (without a graphical user interface) for faster execution and reduced resource consumption.

2. Setting Up Playwright for a React Project

Step 1: Install Playwright

To begin, you need to install Playwright and the necessary browser binaries. Run the following commands in your project directory:

npm install --save-dev @playwright/test
npx playwright install
Enter fullscreen mode Exit fullscreen mode
  • @playwright/test: The Playwright test runner package.
  • npx playwright install: Installs the required browser binaries for Playwright to work.

Step 2: Configure Playwright

Create a configuration file named playwright.config.ts in the root of your project. This file defines settings and options for your tests:

import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  projects: [
    {
      name: 'Desktop Chrome',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'Desktop Firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'Desktop Safari',
      use: { ...devices['Desktop Safari'] },
    },
  ],
  use: {
    baseURL: 'http://localhost:3000', // Adjust URL to match your development server
  },
});
Enter fullscreen mode Exit fullscreen mode
  • projects: Defines different browser configurations for testing.
  • use.baseURL: Specifies the base URL for the application being tested.

Step 3: Create Your First Test

Create a test file in the tests directory (or any directory of your choice). For example, create app.spec.ts to write your E2E tests:

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

test('should load the homepage and display the correct content', async ({ page }) => {
  await page.goto('/'); // Uses the baseURL defined in the configuration

  // Check if the page title is correct
  await expect(page).toHaveTitle(/React App/);

  // Check if a specific element is visible
  const header = await page.locator('h1');
  await expect(header).toHaveText('Welcome to React');

  // Simulate a user interaction
  await page.click('button#login');
  await expect(page.locator('text="Login successful"')).toBeVisible();
});
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • page.goto('/'): Navigates to the base URL.
  • expect(page).toHaveTitle: Asserts that the page title matches the expected text.
  • page.locator: Finds elements using CSS selectors.
  • page.click: Simulates a click event.
  • expect(...).toBeVisible(): Asserts that an element is visible.

3. Running Your Tests

To execute your Playwright tests, use the following command:

npx playwright test
Enter fullscreen mode Exit fullscreen mode

This command runs all test files in the tests directory. You can also use additional options:

  • Run in Headless Mode: Tests run without a graphical user interface for faster execution.
  npx playwright test --headless
Enter fullscreen mode Exit fullscreen mode
  • Run in Specific Browser: Execute tests in a specific browser configuration.
  npx playwright test --project=Desktop Chrome
Enter fullscreen mode Exit fullscreen mode
  • Run Tests in Watch Mode: Automatically rerun tests when files change.
  npx playwright test --watch
Enter fullscreen mode Exit fullscreen mode

4. Advanced Testing Scenarios

Network Interception and Mocking

Playwright allows you to intercept network requests and mock responses. This is useful for testing how your application handles different server responses:

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

test('should handle network errors', async ({ page }) => {
  await page.route('**/api/data', (route) =>
    route.fulfill({ status: 500, body: 'Internal Server Error' })
  );

  await page.goto('/');

  // Test behavior when the API returns an error
  await expect(page.locator('text="Error loading data"')).toBeVisible();
});
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • page.route: Intercepts network requests matching the specified pattern.
  • route.fulfill: Mocks a response with a status code and body.

Screenshots and Videos

Capturing screenshots and videos helps in debugging and verifying test results visually:

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

test('should take a screenshot of the homepage', async ({ page }) => {
  await page.goto('/');
  await page.screenshot({ path: 'homepage.png' });
});
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • page.screenshot: Captures a screenshot of the page and saves it to the specified path.

Test Fixtures

Fixtures allow you to set up and tear down common test scenarios, improving test organization:

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

test.describe('User login', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/');
  });

  test('should log in and display user profile', async ({ page }) => {
    await page.fill('input[name="username"]', 'user');
    await page.fill('input[name="password"]', 'password');
    await page.click('button[type="submit"]');
    await expect(page.locator('text="Welcome, user"')).toBeVisible();
  });
});
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • test.beforeEach: Runs before each test in the describe block, setting up the initial state.
  • page.fill: Simulates typing into an input field.

5. Integrating Playwright with CI/CD

Integrating Playwright tests into your Continuous Integration/Continuous Deployment (CI/CD) pipeline ensures that your tests run automatically with every build. Here’s an example configuration for GitHub Actions:

Create a .github/workflows/playwright.yml file:

name: Playwright Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'
      - run: npm install
      - run: npx playwright install
      - run: npx playwright test
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • actions/checkout: Checks out the repository.
  • actions/setup-node: Sets up Node.js.
  • npx playwright install: Installs browser binaries.
  • npx playwright test: Runs the Playwright tests.

6. Conclusion

Playwright provides a robust framework for end-to-end testing of React applications, enabling you to verify that your application functions correctly across different browsers and scenarios. Its powerful API, cross-browser support, and advanced features make it an excellent choice for modern web testing.

By integrating Playwright into your workflow, you can ensure that your React application delivers a seamless user experience, catch potential issues early, and maintain high-quality software. For more information and advanced features, visit the Playwright documentation.

Explore how Playwright can enhance your testing strategy by customizing your setup, leveraging advanced testing capabilities, and integrating with your CI/CD pipelines to ensure comprehensive test coverage and application reliability.


Happy Coding 👨‍💻
Enter fullscreen mode Exit fullscreen mode

Top comments (0)