DEV Community

Cover image for Playwright: A Comprehensive Overview of Web UI Automation Testing Framework
Isaac Chen
Isaac Chen

Posted on

Playwright: A Comprehensive Overview of Web UI Automation Testing Framework

PlayWright is a Web UI automation testing framework developed by Microsoft.

It aims to provide a cross-platform, cross-language, cross-browser automation testing framework that also supports mobile browsers.

Image description

As described on its official homepage:

  • Automatic waiting, intelligent assertions for page elements, and execution tracing make it highly effective in handling the instability of web pages.
  • It controls browsers in a process different from the one running the test, eliminating the limitations of in-process test runners and supporting Shadow DOM penetration.
  • PlayWright creates a browser context for each test. A browser context is equivalent to a brand-new browser profile, enabling zero-cost full test isolation. Creating a new browser context takes just a few milliseconds.
  • Provides features like code generation, step-by-step debugging, and trace viewer.

PlayWright vs. Selenium vs. Cypress

What are the best Web UI automation testing frameworks available today? The standout options include the decade-old Selenium, the recently popular Cypress, and the one we’re introducing here—PlayWright. How do they differ? Below is a summarized comparison for your reference

Feature PlayWright Selenium Cypress
Supported Languages JavaScript, Java, C#, Python JavaScript, Java, C#, Python, Ruby JavaScript/TypeScript
Supported Browsers Chrome, Edge, Firefox, Safari Chrome, Edge, Firefox, Safari, IE Chrome, Edge, Firefox, Safari
Testing Framework Frameworks for supported languages Frameworks for supported languages Frameworks for supported languages
Usability Easy to use and configure Complex setup with a learning curve Easy to use and configure
Code Complexity Simple Moderate Simple
DOM Manipulation Simple Moderate Simple
Community Maturity Improving gradually Highly mature Fairly mature
Headless Mode Support Yes Yes Yes
Concurrency Support Supported Supported Depends on CI/CD tools
iframe Support Supported Supported Supported via plugins
Driver Not required Requires a browser-specific driver Not required
Multi-Tab Operations Supported Not supported Supported
Drag and Drop Supported Supported Supported
Built-in Reporting Yes No Yes
Cross-Origin Support Supported Supported Supported
Built-in Debugging Yes No Yes
Automatic Wait Yes No Yes
Built-in Screenshot/Video Yes No video recording Yes

Key Comparisons:

  • Supported Languages: PlayWright and Selenium support Java, C#, and Python, making them more popular among test engineers who may not be familiar with JavaScript/TypeScript.
  • Technical Approach: Both PlayWright and Selenium use Google’s Remote Debugging Protocol to control Chromium-based browsers. For browsers like Firefox, without such protocols, they use JavaScript injection. Selenium encapsulates this in a Driver, while PlayWright directly calls it. Cypress, on the other hand, uses JavaScript to control browsers.
  • Browser Support: Selenium supports Internet Explorer, which is irrelevant as IE is being phased out.
  • Ease of Use: All three frameworks have a learning curve. However, PlayWright and Cypress are more user-friendly for simple scenarios compared to Selenium.

Getting Started

Although PlayWright supports multiple languages, it heavily relies on Node.js. Regardless of whether you use the Python or Java version, PlayWright requires a Node.js environment during initialization, downloading a Node.js driver. Hence, we’ll focus on JavaScript/TypeScript for this guide.

Installation and Demo

  1. Ensure Node.js is installed.
  2. Initialize a PlayWright project using npm or yarn:
   # Using npm
   npm init playwright@latest

   # Using yarn
   yarn create playwright
Enter fullscreen mode Exit fullscreen mode
  1. Follow the prompts:
    • Choose TypeScript or JavaScript (default: TypeScript).
    • Specify the test directory name.
    • Decide whether to install PlayWright-supported browsers (default: True).

If you choose to download browsers, PlayWright will download Chromium, Firefox, and WebKit, which may take some time. This process occurs only during the first setup unless the PlayWright version is updated.

Project Structure

After initialization, you’ll get a project template:

playwright.config.ts    # PlayWright configuration file
package.json            # Node.js configuration file
package-lock.json       # Node.js dependency lock file
tests/                  # Your test directory
  example.spec.ts       # Template test case
tests-examples/         # Example tests directory
  demo-todo-app.spec.ts # Example test case
Enter fullscreen mode Exit fullscreen mode

Run the example test case:

npx playwright test
Enter fullscreen mode Exit fullscreen mode

The tests execute silently (in headless mode), and results are displayed as:

Running 6 tests using 6 workers

  6 passed (10s)

To open the last HTML report run:

  npx playwright show-report
Enter fullscreen mode Exit fullscreen mode

Example Source Code

Here’s the example.spec.ts test case:

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

test('has title', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  await expect(page).toHaveTitle(/Playwright/);
});

test('get started link', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  await page.getByRole('link', { name: 'Get started' }).click();
  await expect(page).toHaveURL(/.*intro/);
});
Enter fullscreen mode Exit fullscreen mode
  • First Test: Verifies the page title contains "Playwright".
  • Second Test: Clicks the "Get started" link and verifies the URL.

Each test method has:

  • A test name (e.g., 'has title').
  • A function to execute the test logic.

Key methods include:

  • page.goto: Navigates to a URL.
  • expect(page).toHaveTitle: Asserts the page title.
  • page.getByRole: Locates an element by its role.
  • await: Waits for asynchronous operations to complete.

Running Tests from the Command Line

Here are common commands:

  • Run all tests:
  npx playwright test
Enter fullscreen mode Exit fullscreen mode
  • Run a specific test file:
  npx playwright test landing-page.spec.ts
Enter fullscreen mode Exit fullscreen mode
  • Debug a test case:
  npx playwright test --debug
Enter fullscreen mode Exit fullscreen mode

Code Recording

Use the codegen feature to record interactions:

npx playwright codegen https://leapcell.io/
Enter fullscreen mode Exit fullscreen mode

Recorded code can be copied into your files. Note: The recorder might not handle complex actions like hovering.


In-Depth Playwright Guide

Actions and Behaviors

This section introduces some typical Playwright actions for interacting with page elements. Note that the locator object introduced earlier does not actually locate the element on the page during its creation. Even if the element doesn't exist on the page, using the element locator methods to get a locator object won't throw any exceptions. The actual element lookup happens only during the interaction. This differs from Selenium's findElement method, which directly searches for the element on the page and throws an exception if the element isn't found.

Text Input

Use the fill method for text input, mainly targeting <input>, <textarea>, or elements with the [contenteditable] attribute:

// Text input
await page.getByRole('textbox').fill('Peter');
Enter fullscreen mode Exit fullscreen mode

Checkbox and Radio

Use locator.setChecked() or locator.check() to interact with input[type=checkbox], input[type=radio], or elements with the [role=checkbox] attribute:

await page.getByLabel('I agree to the terms above').check();

expect(await page.getByLabel('Subscribe to newsletter').isChecked()).toBeTruthy();

// Uncheck
await page.getByLabel('XL').setChecked(false);
Enter fullscreen mode Exit fullscreen mode

Select Control

Use locator.selectOption() to interact with <select> elements:

// Select by value
await page.getByLabel('Choose a color').selectOption('blue');

// Select by label
await page.getByLabel('Choose a color').selectOption({ label: 'Blue' });

// Multi-select
await page.getByLabel('Choose multiple colors').selectOption(['red', 'green', 'blue']);
Enter fullscreen mode Exit fullscreen mode

Mouse Clicks

Basic operations:

// Left click
await page.getByRole('button').click();

// Double click
await page.getByText('Item').dblclick();

// Right click
await page.getByText('Item').click({ button: 'right' });

// Shift+click
await page.getByText('Item').click({ modifiers: ['Shift'] });

// Hover
await page.getByText('Item').hover();

// Click at specific position
await page.getByText('Item').click({ position: { x: 0, y: 0 } });
Enter fullscreen mode Exit fullscreen mode

For elements covered by others, use force click:

await page.getByRole('button').click({ force: true });
Enter fullscreen mode Exit fullscreen mode

Or trigger the click event programmatically:

await page.getByRole('button').dispatchEvent('click');
Enter fullscreen mode Exit fullscreen mode

Typing Characters

The locator.type() method simulates typing character-by-character, triggering keydown, keyup, and keypress events:

await page.locator('#area').type('Hello World!');
Enter fullscreen mode Exit fullscreen mode

Special Keys

Use locator.press() for special keys:

// Enter key
await page.getByText('Submit').press('Enter');

// Ctrl+Right Arrow
await page.getByRole('textbox').press('Control+ArrowRight');

// Dollar key
await page.getByRole('textbox').press('$');
Enter fullscreen mode Exit fullscreen mode

Supported keys include Backquote, Minus, Equal, Backslash, Backspace, Tab, Delete, Escape, ArrowDown, End, Enter, Home, Insert, PageDown, PageUp, ArrowRight, ArrowUp, F1-F12, Digit0-Digit9, and KeyA-KeyZ.

File Upload

Use locator.setInputFiles() to specify files for upload. Multiple files are supported:

// Upload a file
await page.getByLabel('Upload file').setInputFiles('myfile.pdf');

// Upload multiple files
await page.getByLabel('Upload files').setInputFiles(['file1.txt', 'file2.txt']);

// Remove files
await page.getByLabel('Upload file').setInputFiles([]);

// Upload from buffer
await page.getByLabel('Upload file').setInputFiles({
  name: 'file.txt',
  mimeType: 'text/plain',
  buffer: Buffer.from('this is test')
});
Enter fullscreen mode Exit fullscreen mode

Focus Element

Use locator.focus() to focus on an element:

await page.getByLabel('Password').focus();
Enter fullscreen mode Exit fullscreen mode

Drag and Drop

The drag-and-drop process involves four steps:

  1. Hover the mouse over the draggable element.
  2. Press the left mouse button.
  3. Move the mouse to the target position.
  4. Release the left mouse button.

You can use the locator.dragTo() method:

await page.locator('#item-to-be-dragged').dragTo(page.locator('#item-to-drop-at'));
Enter fullscreen mode Exit fullscreen mode

Alternatively, manually implement the process:

await page.locator('#item-to-be-dragged').hover();
await page.mouse.down();
await page.locator('#item-to-drop-at').hover();
await page.mouse.up();
Enter fullscreen mode Exit fullscreen mode

Dialog Handling

By default, Playwright automatically cancels dialogs like alert, confirm, and prompt. You can pre-register a dialog handler to accept dialogs:

page.on('dialog', dialog => dialog.accept());
await page.getByRole('button').click();
Enter fullscreen mode Exit fullscreen mode

Handling New Pages

When a new page pops up, you can use the popup event to handle it:

const newPagePromise = page.waitForEvent('popup');
await page.getByText('Click me').click();
const newPage = await newPagePromise;
await newPage.waitForLoadState();
console.log(await newPage.title());
Enter fullscreen mode Exit fullscreen mode

The Best Platform for Playwright: Leapcell

Image description

Leapcell is a modern cloud computing platform designed for distributed applications. It adopts a pay-as-you-go model with no idle costs, ensuring you only pay for the resources you use.

Unique Benefits of Leapcell for Playwright Applications

  1. Cost Efficiency

    • Pay-as-you-go: Avoid resource waste during low traffic and scale up automatically during peak times.
    • Real-world example: For example, on getdeploying.com’s calculations, renting a 1 vCPU and 2 GB RAM virtual machine in traditional cloud services costs around $25 per month. On Leapcell, $25 can support a service handling 6.94 million requests with an average response time of 60 ms, giving you better value for money.
  2. Developer Experience

    • Ease of use: Intuitive interface with minimal setup requirements.
    • Automation: Simplifies development, testing, and deployment.
    • Seamless integration: Supports Go, Python, Node.js, Rust, and more.
  3. Scalability and Performance

    • Auto-scaling: Dynamically adjusts resources to maintain optimal performance.
    • Asynchronous optimization: Handles high-concurrency tasks with ease.
    • Global reach: Low-latency access supported by distributed data centers.

For more deployment examples, refer to the documentation.

Top comments (0)