In today’s fast-paced digital landscape, the demand for high-quality web applications has never been greater. As developers strive to deliver seamless user experiences, automation testing tools have become essential in ensuring that applications function correctly across various browsers and devices. From setting up your environment to writing your first tests, this beginner’s guide will equip you with the knowledge and skills needed to harness the full potential of Playwright in your development workflow.
Whether you’re a seasoned developer or just starting your journey into software testing, this guide aims to provide a comprehensive introduction to Playwright. We’ll explore its key features, benefits, and how it stands out from other testing frameworks. Let’s dive in and unlock the capabilities of this innovative tool!
What is Playwright?
Playwright is an open-source automation test framework that allows you to interact with web applications just as a user would. Playwright Test was created specifically to accommodate the needs of end-to-end testing. It can handle multiple browsers, including Chromium, Firefox, and WebKit, so you can ensure your app behaves consistently across all platforms. It’s fast, reliable, and capable of handling even complex scenarios with ease.
Why Playwright over other tools?
Following features make Playwright a versatile, efficient, and modern choice for end-to-end testing, catering to the needs of developers and QA engineers looking for fast, reliable, and comprehensive test automation.
1. Cross-Browser Testing
Playwright supports testing across multiple browsers, including Chromium (Chrome, Edge), WebKit (Safari), and Firefox. This ensures that your web application works consistently across different browser environments without the need for separate test scripts.
2. Cross-Platform Compatibility
It can run tests on various platforms such as Windows, MacOS, and Linux, making it versatile for development teams working in different environments.
3. Reliable and Fast Automation Testing
Playwright automates browsers at the protocol level, which means it can interact directly with the browser, leading to faster and more reliable test execution compared to traditional Selenium-based tools like Selenium IDE & WebDriver, WebDriverIO etc.
4. Headless and Headed Modes
Playwright supports running tests in both headless (no UI) and headed (with UI) modes, giving flexibility for running tests locally during development or in continuous integration (CI) pipelines.
5. Support for Modern Web Features
It offers built-in support for testing modern web applications that use JavaScript frameworks (like React, Angular, Vue.js), SPAs (Single Page Applications), and even Progressive Web Apps (PWAs). It handles events like network interceptions, file uploads, and keyboard and mouse actions seamlessly.
6. Parallel Test Execution
Playwright allows running tests in parallel, reducing the overall test execution time. This is particularly beneficial when you have a large suite of tests, speeding up the feedback loop.
7. Automatic Waiting
It comes with smart waiting features that automatically wait for elements to be ready before interacting with them. This helps in reducing flakiness in tests caused by timing issues.
8. Easy Debugging
Playwright provides debugging capabilities, including features like screenshots, video recording, and trace logs. These features make it easier to analyze and debug test failures.
9. API Testing Support
Playwright can be used not only for UI testing, but also for API testing. Thus, it allows developers to test the back-end services and front-end user flows within the same test suite.
10. Built-in Test Runner
It has its own test runner, which is fast and comes with built-in functionalities like assertions, fixtures, retries, and parallel execution, eliminating the need for an external test runner.
11. Open Source
Playwright is an open-source tool, backed by Microsoft, which means it’s constantly being updated and improved by a community of developers. It’s also free to use, making it an attractive option for companies looking to adopt a robust test automation framework without incurring licensing costs.
Setting Up Playwright
Getting started with Playwright is pretty simple. All you need to do is install Node.js on your machine. If you don’t have it, download it from here.
1. Create a New Project
Open the terminal, create a new project directory and switch to that folder path
> mkdir playwright-demo
> cd playwright-demo
2. Install Playwright
npm init playwright@latest
Run the above mentioned command and select the following to get started:
- Choose between TypeScript or JavaScript (default is TypeScript)
- Name of your Tests folder (default is tests or e2e if you already have a tests folder in your project)
- Add a GitHub Actions workflow to easily run tests on CI (default is false)
- Install Playwright browsers (default is true)
Playwright will download the browsers needed as well as create the following files.
The playwright.config.ts
is where you can add all your configuration for Playwright, including modifying which browsers you would like to run Playwright on. All the dependencies required for this project will be added directly to the package.json
.
The tests
folder will be the place where you need to keep all your test files. This contains a basic example test to help you get started with testing. For a more detailed example check out the tests-examples
folder which contains tests written to test a todo app.
3. Setting Up Your First Playwright Test
As part of setting up first automation test, you need to have some basic ideas on Locators & Actions available in Playwright. For in-depth understanding, you can refer the official documentation of Locators & Actions.
3.1. Locators
Playwright Locators allow you to identify and interact with elements on a web page. It is more flexible and reliable way compared to traditional selectors. They provide a more robust mechanism for targeting elements based on various attributes and conditions. Locators are the central piece of Playwright’s auto-waiting and retry-ability.
As of now, there are 7 recommended built-in locators in Playwright. Those are:
a. page.getByRole()
Method in Playwright used to locate elements based on their ARIA roles. This makes it easier to interact with web elements that serve specific functions on a page (like buttons, links, headings, etc.). It is particularly useful for making tests more accessible and reliable, as it leverages roles defined by web standards.
Let’s look at one example as shown below. To locate the element by its role of button
with name “Sign in”.
<button>Sign in</button>
const locator = page.getByRole('button', {name: 'Sign in'});
b. page.getByText()
Find an element by the text it contains. You can match by a substring, exact string, or a regular expression when using this method.
You can locate the element by the text it contains as:
<a class="getStarted_Sjon" href="/docs/intro">Get started</a>
const getStartedLink = page.getByText('Get started');
Set an exact match:
const getStartedLink = page.getByText('Get started', {exact: true});
By default, getByText()
matches elements containing the exact text. However, it can also work with partial matches by using regular expressions:
const getStartedLink = page.getByText(/Get/i); //Case-insensitive search
c. page.getByLabel()
It is a method in Playwright used to locate form elements (such as input fields, text areas, check-boxes, and radio buttons) by their associated label text.
<label>Username <input type="text" /></label>
const usernameInput = page.getByLabel('Username');
d. page.getByPlaceholder()
Inputs may have a placeholder attribute to hint to the user what value should be entered. You can locate such an input using this method.
<input type="email" placeholder="name@example.com" />
const emailInput = page.getByPlaceholder('name@example.com');
e. page.getByAltText()
All images should have an alt
attribute that describes the image. You can locate an image based on the text alternative using this method.
<img alt="playwright logo" src="/img/playwright-logo.svg" width="100" />
const playwrightLogo = page.getByAltText('playwright logo');
f. page.getByTitle()
Playwright method that allows you to locate elements by their title
attribute. The title
attribute provides additional information about an element and is often used for tooltips that appear when a user hovers over the element.
<button class="clean-btn toggleButton_gllP" type="button" title="Switch between dark and light mode (currently dark mode)" />
const toggleButton = page.getByTitle('Switch between dark and light mode (currently dark mode)');
g. page.getByTestId()
Testing by test ids is the most resilient way of testing as even if your text or role of the attribute changes, the test will still pass. QA’s and developers should define explicit test ids and query them with page.getByTestId(
). However testing by test ids is not user facing. If the role or text value is important to you then consider using user facing locators such as role
and text
locators.
<button data-testid="directions">Route</button>
const routeButton = page.getByTestId('directions');
Apart from the built-in locators, you can use CSS or XPath locators if necessary. Use page.locator()
to create a locator that describes how to find an element on the page. Playwright supports both CSS and XPath selectors. It can also auto-detect them if you omit the css=
or xpath=
prefix.
page.locator('css=button');
page.locator('xpath=//button');
OR
page.locator('button');
page.locator('//button');
3.2. Actions
Playwright can interact with HTML Input elements such as text inputs, checkboxes, radio buttons, select options, mouse clicks, type characters, keys and shortcuts as well as upload files and focus elements. In Playwright these interactions are called Actions and it can be achieved using certain methods as follows:
a. locator.fill()
Using locator.fill()
is the easiest way to fill out the form fields. It focuses the element and triggers an input event with the entered text. It works for <input>
, <textarea>
, and [contenteditable]
elements.
await page.getByRole('textbox').fill('Playwright');
b. locator.setChecked()
Using locator.setChecked()
is the easiest way to check and uncheck a checkbox or a radio button. This method can be used with input[type=checkbox]
, input[type=radio]
and [role=checkbox]
elements.
// Check the checkbox
await page.getByLabel('I agree to the terms above').setChecked(true);
OR await page.getByLabel('I agree to the terms above').check();
// Assert the checked state
expect(page.getByLabel('Subscribe to newsletter')).toBeChecked();
// Uncheck the checkbox
await page.getByLabel('I agree to the terms above').setChecked(false);
OR await page.getByLabel('I agree to the terms above').uncheck();
// Assert the unchecked state
expect(page.getByLabel('Subscribe to newsletter')).toBeChecked({checked: false});
// Select the radio button
await page.getByLabel('XL').check();
c. locator.selectOption()
Selects one or multiple options in the element with locator.selectOption()
. You can specify option value, or label to select. Also, you can select multiple options.
// Single selection matching the value or label
await page.getByLabel('Choose a color').selectOption('blue');
// Single selection matching the label
await page.getByLabel('Choose a color').selectOption({ label: 'Blue' });
// Multiple selected items
await page.getByLabel('Choose multiple colors').selectOption(['red', 'green', 'blue']);
d. locator.click()
Simulates a mouse click on an element.
// Generic 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'] });
e. locator.pressSequentially()
Type into the field character by character, as if it was a user with a real keyboard with.
// Press keys one by one
await page.locator('#area').pressSequentially('Hello World!');
f. locator.press()
// Hit Enter
await page.getByText('Submit').press('Enter');
// Dispatch Control+Right
await page.getByRole('textbox').press('Control+ArrowRight');
// Press $ sign on keyboard
await page.getByRole('textbox').press('$');
The locator.press()
method focuses the selected element and produces a single keystroke. It accepts the logical key names that are emitted in the keyboardEvent.key
property.
g. locator.setInputFiles()
You can select input files for upload using the locator.setInputFiles()
method. It expects first argument to point to an input element with the type "file"
. Multiple files can be passed in the array. If some of the file paths are relative, they are resolved relative to the current working directory. Empty array clears the selected files.
// Select one file
await page.getByLabel('Upload file').setInputFiles(path.join(__dirname, 'myfile.pdf'));
// Select multiple files
await page.getByLabel('Upload files').setInputFiles([
path.join(__dirname, 'file1.txt'),
path.join(__dirname, 'file2.txt'),
]);
// Select a directory
await page.getByLabel('Upload directory').setInputFiles(path.join(__dirname, 'mydir'));
// Remove all the selected files
await page.getByLabel('Upload file').setInputFiles([]);
// Upload buffer from memory
await page.getByLabel('Upload file').setInputFiles({
name: 'file.txt',
mimeType: 'text/plain',
buffer: Buffer.from('this is test')
});
h. locator.setInputFiles()
For the dynamic pages that handle focus events, you can focus the given element with locator.focus()
.
await page.getByLabel('Password').focus();
i. locator.dragTo()
You can perform drag&drop operation with locator.dragTo()
.
await page.locator('#item-to-be-dragged').dragTo(page.locator('#item-to-drop-at'));
j. locator.scrollIntoViewIfNeeded()
Most of the time, Playwright will automatically scroll for you before doing any actions. However, in rare cases you might need to manually scroll.
// Scroll the footer into view, forcing an "infinite list" to load more content
await page.getByText('Footer text').scrollIntoViewIfNeeded();
Now, let’s take a look at the following example to see how to write a test.
import { test, expect } from '@playwright/test';
test('Check Playwright Homepage Title', async ({ page }) => {
await page.goto('https://playwright.dev/');
// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
});
test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');
// Click the get started link.
await page.getByRole('link', { name: 'Get started' }).click();
// Expects page to have a heading with the name of Installation.
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});
Here, import { test, expect } from '@playwright/test';
imports two essential functions from the Playwright testing library.
test
: It is to define and run test cases.expect
: Provides assertion methods to validate the results within tests.
This allows you to write and execute tests using Playwright’s syntax and assertion capabilities.
Most of the tests will start with navigating page to the URL. After that, test will be able to interact with the page elements.
await page.goto('https://playwright.dev/');
Playwright will wait for page to reach the load state prior to moving forward
await expect(page).toHaveTitle(/Playwright/);
This line will check whether the page title contains the substring Playwright
. If the page title contains Playwright
, the test will pass
. Otherwise the test will fail
.
Actions in Playwright begin with locating elements using the Locators API, which helps find elements on the page at any moment. Playwright waits for elements to be actionable before performing actions, eliminating the need for manual waits.
await page.getByRole('link', { name: 'Get started' }).click();
This will identify the locator as link with text Get started
and click
on it.
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
Once click on the Get started
link, it asserts for a locator heading
with text Installation
to be visible on the page loaded.
4. Running the Playwright Test
By default tests will be run on all 3 browsers, chromium, firefox and webkit using 3 workers. This can be configured in the playwright.config
file. Tests are run in headless mode meaning no browser will open up when running the tests. Results of the tests and test logs will be shown in the terminal.
npx playwright test
5. Generating HTML Test Reports
After your test completes, an HTML Reporter will be generated, which 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. You can click on each test and explore the test’s errors as well as each step of the test. By default, the HTML report is opened automatically if some of the tests failed.
npx playwright show-report
Conclusion
In conclusion, getting started with Playwright can significantly enhance your web testing capabilities. By now, you should have a solid understanding of how to set up Playwright, locate web elements and interact with them, create your first automation test, Run your test and generate HTML Report. Throughout this guide, we’ve seen how Playwright simplifies cross-browser testing, making it a versatile tool for developers and testers alike.
As you continue to explore Playwright, remember to experiment with its rich set of APIs and integration options. Whether you’re aiming to run tests on local systems, cloud platforms, or CI/CD pipelines, Playwright has you covered. Additionally, by writing efficient test scripts, you can minimize bugs and improve the overall quality of your web applications, ensuring a seamless user experience across all platforms.
Now that you’ve taken your first steps with Playwright, it’s time to dive deeper. You can read a lot more on the same from Playwright official website. Keep practicing, and soon you’ll be crafting more robust, reliable, and efficient automation tests. Happy testing, and may your journey with Playwright lead to flawless and well-tested web applications!
Lead QA Engineer at CeeGees Software Solutions Pvt. Ltd.