Top 20 Playwright Features for QA Engineers

admin-img
TestoMeter

November 03, 2026

Browse by category

Select a category to see more related content

Testing has changed a lot in the last few years. Releases are faster, apps are more complex, and nobody has the patience (or the budget) for endless manual regression cycles. That's why so many teams have turned to automation and why Playwright keeps coming up in QA conversations.

Playwright is an open-source browser automation framework from Microsoft. It lets you write reliable end-to-end tests that run on Chromium, Firefox, and WebKit. So what makes it different from the older tools? A handful of things: auto-waiting, isolated browser contexts, built-in parallel execution, reusable fixtures, API testing, network interception, and some really good debugging tools.

Maybe you're a manual tester thinking about moving into automation. Maybe you've spent years with Selenium and want to see what the fuss is about. Or maybe you're already building frameworks and want to sharpen your skills. Either way, this guide walks through the 20 Playwright features worth knowing, with JavaScript examples and the kind of scenarios you'll run into on real projects.
 

TL;DR:

  • Playwright is Microsoft’s open-source tool for reliable end-to-end web testing across Chromium, Firefox, and WebKit.
  • This guide covers the 20 features worth learning first: auto-waiting, flexible locators, web-first assertions, browser contexts, parallel runs, fixtures, Page Object Model, Codegen, Inspector, Trace Viewer, API testing, network mocking, and CI/CD.
  • Each one comes with a JavaScript example. You’ll also find a Playwright vs Selenium comparison and a 10-stage roadmap for manual testers moving into automation.


So, What is Playwright?

Playwright is an end-to-end testing and browser automation framework built by Microsoft. You can write tests in JavaScript, TypeScript, Python, Java, or .NET, and run them against Chromium, Firefox, and WebKit.

With it, you can automate the journeys your users actually take: logging in, registering, searching for products, filling a cart, checking out, submitting forms, and so on.

Here's a simple login test to give you a feel for it:

const { test, expect } = require('@playwright/test');

test('Verify successful login', async ({ page }) => {

    await page.goto('https://www.saucedemo.com/');

    await page.locator('#user-name').fill('standard_user');

    await page.locator('#password').fill('secret_sauce');

    await page.locator('#login-button').click();

    await expect(page).toHaveURL(/inventory.html/);

});

The script opens the app, types in the credentials, clicks Login, and checks that you landed on the inventory page. Now let's look at the features that make this so smooth.

 

1. Cross-Browser Testing

A page that looks perfect in Chrome can behave strangely in Firefox or Safari. Playwright lets you run the same tests across three engines:

  • Chromium: Chrome and other Chromium-based browsers
  • Firefox: Mozilla Firefox
  • WebKit: the engine behind Safari
const { test, expect } = require('@playwright/test');

test('Verify application title', async ({ page }) => {

    await page.goto('https://www.saucedemo.com/');

    await expect(page).toHaveTitle(/Swag Labs/);

});

Imagine an e-commerce site that has to work for Chrome, Firefox, and Safari users. Instead of writing three separate suites, you run one suite on all three engines and catch browser-specific bugs before your customers do.

 

2. Auto-Waiting

If you've worked with Selenium, you know the pain of sprinkling explicit waits everywhere just to get a click to land. The playwright handles most of that for you. Before it performs an action, it checks that the element is visible, stable, enabled, and able to receive events.

await page.getByRole('button', { name: 'Login' }).click();

That's it. No extra wait code. If the Login button only becomes enabled after valid credentials are entered, Playwright simply waits until it's ready.

Compare that with the habit you should avoid:

// Avoid fixed waits like this
await page.waitForTimeout(5000);

await page.getByRole('button', { name: 'Login' }).click();

Fixed sleeps slow your suite down and still fail when the app is slower than expected. Auto-waiting means fewer flaky tests and faster runs.



 

3. Flexible Locator Strategies

Locators are how you point. Playwright at elements: textboxes, buttons, links, checkboxes, dropdowns. You get plenty of options:

  • CSS
  • XPath
  • Text
  • Role
  • Label
  • Placeholder
  • Test ID
// CSS locator
await page.locator('#user-name').fill('standard_user');

// XPath locator
await page.locator('//input[@id="password"]').fill('secret_sauce');

// Text locator
await page.getByText('Products').isVisible();

// Role locator
await page.getByRole('button', { name: 'Login' }).click();

On a registration form, for example, you might find fields by their labels, the submit button by its role, and error messages by their visible text. Locators that mirror how a user sees the page tend to be easier to read and much less likely to break when the markup changes.

 

4. Web-First Assertions

Playwright's assertions don't just check once and give up. They keep retrying until the condition is met or the timeout runs out, which is exactly what you want in an app where things load dynamically.

const { test, expect } = require('@playwright/test');

test('Verify product page', async ({ page }) => {

    await page.goto('https://www.saucedemo.com/');

    await page.locator('#user-name').fill('standard_user');

    await page.locator('#password').fill('secret_sauce');

    await page.locator('#login-button').click();

    await expect(page.locator('.title')).toHaveText('Products');

});

Here Playwright keeps checking until the title reads "Products". Some assertions you'll use all the time:

await expect(locator).toBeVisible();

await expect(locator).toBeEnabled();

await expect(locator).toHaveText('Welcome');

await expect(page).toHaveURL(/dashboard/);

await expect(locator).toHaveValue('admin');

 

5. Browser Context Isolation

A browser context is like a fresh, independent browser profile, with its own cookies, local storage, and session storage. You can spin up several in a single test, which makes it easy to simulate multiple users without installing anything extra.

const { test, expect } = require('@playwright/test');

test('Multiple user sessions', async ({ browser }) => {

    const user1 = await browser.newContext();
    const user2 = await browser.newContext();

    const page1 = await user1.newPage();
    const page2 = await user2.newPage();

    await page1.goto('https://www.saucedemo.com/');
    await page2.goto('https://www.saucedemo.com/');

    await page1.locator('#user-name').fill('standard_user');
    await page2.locator('#user-name').fill('problem_user');

    await user1.close();
    await user2.close();

});

Think of an app with an admin and a customer. With two contexts, you can test both roles side by side, and nothing leaks from one session into the other.

 

6. Parallel Test Execution

Running tests one after another gets old fast. Playwright Test runs them in parallel using worker processes:

npx playwright test --workers=4

Or set it once in your config:

const { defineConfig } = require('@playwright/test');

module.exports = defineConfig({

    workers: 4,

    fullyParallel: true

});

If you have 100 independent tests, spreading them across several workers can cut total run time dramatically. It's especially handy for big regression suites and for getting quicker feedback during development. Just keep in mind that real-world speed-ups depend on your machine, how your tests are written, and how fast the application is.

 

7. Fixtures

Fixtures take care of reusable setup and teardown. Rather than repeating browser setup, login steps, or page initialization in every test, you define it once and let tests ask for what they need.

Playwright ships with built-in fixtures like page, browser, context, browserName, and request.

const { test, expect } = require('@playwright/test');

test.beforeEach(async ({ page }) => {

    await page.goto('https://www.saucedemo.com/');

});

test('Verify login page', async ({ page }) => {

    await expect(page.locator('#login-button')).toBeVisible();

});

test('Verify username field', async ({ page }) => {

    await expect(page.locator('#user-name')).toBeVisible();

});

When you need something more specific, you can extend Playwright's base test object and write your own custom fixtures. The payoff is less duplicate code and a framework that's easier to maintain.

 

8. Hooks: beforeEach, afterEach, beforeAll, afterAll

Hooks run common setup and cleanup at specific points in a test run.

Hook

When it runs

beforeEach

Before every test

afterEach

After every test

beforeAll

Once, before the tests in a scope

afterAll

Once, after the tests in a scope

const { test, expect } = require('@playwright/test');

test.beforeEach(async ({ page }) => {

    await page.goto('https://www.saucedemo.com/');

});

test('Verify login button', async ({ page }) => {

    await expect(page.locator('#login-button')).toBeVisible();

});

test.afterEach(async ({ page }) => {

    console.log('Test execution completed');

});

If every test needs to start on the login page, one beforeEach handles the navigation and keeps your tests short and tidy.

 

9. Page Object Model (POM)

POM is a design pattern that keeps your code organized. Instead of stuffing locators and actions into every test file, you put them in separate page classes and reuse them.

A simple folder structure looks like this:

PlaywrightProject/
│
├── pages/
│   └── LoginPage.js
│
├── tests/
│   └── login.spec.js
│
└── playwright.config.js

LoginPage.js

class LoginPage {

    constructor(page) {

        this.page = page;

        this.username = page.locator('#user-name');

        this.password = page.locator('#password');

        this.loginButton = page.locator('#login-button');

    }

    async open() {

        await this.page.goto('https://www.saucedemo.com/');

    }

    async login(username, password) {

        await this.username.fill(username);

        await this.password.fill(password);

        await this.loginButton.click();

    }

}

module.exports = LoginPage;

login.spec.js

const { test, expect } = require('@playwright/test');

const LoginPage = require('../pages/LoginPage');

test('Login using POM', async ({ page }) => {

    const loginPage = new LoginPage(page);

    await loginPage.open();

    await loginPage.login('standard_user', 'secret_sauce');

    await expect(page).toHaveURL(/inventory.html/);

});

The big win is maintenance. When a locator changes, you fix it in one place instead of hunting through dozens of tests.

 

10. Codegen

Codegen records what you do in the browser and turns it into Playwright code. It's a great way to learn the syntax when you're starting out.

npx playwright codegen https://www.saucedemo.com/

Playwright opens a browser, you click around, and it writes the script as you go. A beginner can open SauceDemo, log in, and immediately see what the generated code looks like.

One word of caution: treat generated code as a starting point. Review it and clean it up before it goes anywhere near your real framework.

 

11. Playwright Inspector

When a test fails and you can't tell why, the Inspector is your friend. It lets you step through a test line by line, pause execution, inspect locators, and look at the live state of the browser.

npx playwright test --debug

It's the fastest way to see which locator is being used, which action is running, and exactly where things go wrong.

12. Trace Viewer

Trace Viewer is like a flight recorder for your tests. It captures an action timeline, DOM snapshots, screenshots, network requests, console output, and errors.

npx playwright test --trace on

Then open the report:

npx playwright show-report

Say a checkout test fails because the Submit Order button wasn't there. Instead of re-running it again and again, you open the trace, scrub through the timeline, and look at the DOM right before the failure. It saves a lot of time.

 

13. HTML Reporting

Playwright generates a built-in HTML report after a run. It shows how many tests passed, failed, or were skipped, how long they took, the error details, and any attachments or traces.

npx playwright test
npx playwright show-report

After a regression run, you can share that report with developers, managers, and stakeholders so everyone sees the same picture.

 

14. API Testing

Playwright isn't only for UI automation. You can send HTTP requests (GET, POST, PUT, PATCH, DELETE) and validate the responses, all in the same framework.

const { test, expect } = require('@playwright/test');

test('Verify API response', async ({ request }) => {

    const response = await request.get(
        'https://jsonplaceholder.typicode.com/posts/1'
    );

    expect(response.status()).toBe(200);

    const responseBody = await response.json();

    expect(responseBody.id).toBe(1);

});

For instance, before testing a product listing page, you can quickly confirm the product API returns what you expect. For basic workflows, it can reduce the need for a separate API testing tool, and it makes combined API plus UI tests straightforward.

 

 

15. Network Interception and Mocking

Playwright can watch, intercept, modify, and mock network requests. That's useful when your app depends on external services you don't control.

const { test, expect } = require('@playwright/test');

test('Mock product API response', async ({ page }) => {

    await page.route('**/api/products', async route => {

        await route.fulfill({

            status: 200,

            contentType: 'application/json',

            body: JSON.stringify([

                { id: 1, name: 'Laptop', price: 50000 }

            ])

        });

    });

    await page.goto('https://example.com');

});

If a product API is down or flaky, you can mock the response and still test how the front end behaves. It's also a great way to simulate errors and edge cases, and it keeps your test data predictable.

 

16. File Upload and Download Handling

If your app lets people upload resumes, images, or documents, or download reports, Playwright has you covered.

Upload:

await page.locator('input[type="file"]')
    .setInputFiles('tests/sample.pdf');

Download:

const downloadPromise = page.waitForEvent('download');

await page.getByRole('button', { name: 'Download' }).click();

const download = await downloadPromise;

console.log(await download.suggestedFilename());

In a recruitment app, for example, you could automate uploading a resume and then check that the downloaded application document has the right filename.

 

17. Authentication and Storage State

Logging in before every single test is a waste of time. Playwright lets you log in once, save the session, and reuse it.

Save the session:

const { test } = require('@playwright/test');

test('Save login session', async ({ page }) => {

    await page.goto('https://www.saucedemo.com/');

    await page.locator('#user-name').fill('standard_user');

    await page.locator('#password').fill('secret_sauce');

    await page.locator('#login-button').click();

    await page.context().storageState({
        path: 'auth.json'
    });

});

Reuse it:

const context = await browser.newContext({

    storageState: 'auth.json'

});

Think of a banking app where dozens of tests need an authenticated customer. Reusing a saved session skips the repeated logins and speeds up your regression runs.

One important note: those state files can contain sensitive cookies or tokens. Keep them out of source control and protect them like any other secret.

 

18. Mobile and Device Emulation

Playwright can imitate real devices by setting the viewport, user agent, device scale factor, touch support, and other mobile browser traits.

const { test, devices } = require('@playwright/test');

test.use({

    ...devices['iPhone 13']

});

test('Verify mobile application', async ({ page }) => {

    await page.goto('https://www.saucedemo.com/');

    await page.screenshot({

        path: 'mobile-view.png'

    });

});

If your e-commerce site has to look right on desktop, tablet, and phone, this is a quick way to check the responsive layout without a drawer full of devices.

 

19. Screenshots and Video Recording

Sometimes the easiest way to explain a failure is to show it. Playwright can capture screenshots and record video during a run.

Screenshot:

await page.screenshot({

    path: 'homepage.png',

    fullPage: true

});

Video and screenshot settings in the config:

const { defineConfig } = require('@playwright/test');

module.exports = defineConfig({

    use: {

        video: 'retain-on-failure',

        screenshot: 'only-on-failure'

    }

});

When a checkout test fails, a screenshot or recording shows testers and developers exactly what the screen looked like at that moment. It makes bug reports clearer and cuts down the back-and-forth.

 

20. CI/CD Integration

Automation really pays off when it runs on its own. Playwright works with GitHub Actions, Jenkins, Azure DevOps, GitLab CI, and more, so your tests can run on every code push or deployment.

Here's a basic GitHub Actions workflow. Save it as .github/workflows/playwright.yml:

name: Playwright Tests

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install --with-deps

      - name: Run Playwright tests
        run: npx playwright test

      - name: Upload report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: playwright-report/

Now every push to main kicks off your regression tests and publishes the report as an artifact. Bugs get caught earlier, manual regression shrinks, and releases move faster.

 

Playwright vs Selenium: why are people switching?

Selenium has been the standard for years, and it's still a solid choice. But modern web apps put a lot of pressure on synchronization, debugging, parallel runs, and cross-browser coverage, and Playwright bundles many of those things in one package.

Feature

Playwright

Selenium

Browser support

Chromium, Firefox, WebKit

Multiple browsers through drivers

Waiting

Built-in actionability checks

Explicit waits commonly used

Locators

CSS, XPath, role, text, label, and more

CSS, XPath, ID, name, and more

Isolation

Browser contexts

Separate browser sessions

Parallel execution

Built into Playwright Test

Usually via Grid or test frameworks

API testing

Built in

Usually needs extra libraries

Debugging

Inspector and Trace Viewer

Browser and framework tools

Code generation

Built-in Codegen

Tooling and external options

Languages

JavaScript, TypeScript, Python, Java, .NET

Multiple languages

So which should you learn? Honestly, it depends on your project, your team, and the framework you already have. Selenium is still very valuable for organizations with established suites. Playwright is a great pick if you're building something new.

 

How can manual testers get started?

A lot of manual testers assume automation means being a programming expert from day one. It doesn't. With a clear path and some patience, you can build these skills step by step. Here's a roadmap that works well:

Stage

What to learn

1

Software testing fundamentals

2

JavaScript basics

3

Installing and setting up Playwright

4

Locators and XPath

5

Browser actions and assertions

6

Hooks and fixtures

7

Page Object Model

8

API testing

9

Building a framework

10

Reporting and CI/CD

My advice: pick a practice site like SauceDemo and work through real scenarios.

  1. Verify a successful login.
  2. Verify an invalid login.
  3. Search for and identify products.
  4. Add products to the cart.
  5. Remove products from the cart.
  6. Complete the checkout.
  7. Validate the order confirmation.
  8. Generate an execution report.

Building something end to end is the best way to see how all these features fit together.

 

 

Playwright training in Pune, Mumbai, and across India

If you're searching for Playwright automation training in Pune, Mumbai, or anywhere in India, look for a program that's genuinely hands-on. A good course should cover:

  • JavaScript fundamentals for testing
  • Playwright installation and configuration
  • CSS and XPath locators
  • Browser handling and assertions
  • Hooks and fixtures
  • Page Object Model
  • API testing with Playwright
  • Framework development
  • GitHub and CI/CD
  • Real-time automation projects

At TestoMeter Edutech, we focus on practical, industry-oriented IT training that helps students and working professionals build skills employers actually look for. Our software testing and automation programs are built around hands-on exercises, real-world scenarios, and framework development.

Whether you're a manual tester, a Selenium professional, or someone just starting out in software testing, building practical Playwright skills can be a great next step. Learn more at testometer.co.in.

 

FAQs

1. What is Playwright used for?

Answer: Automating web application testing: logins, navigation, form submissions, cart workflows, API checks, and full end-to-end business scenarios.

2. What are its most important features?

Answer: Auto-waiting, cross-browser testing, browser context isolation, flexible locators, web-first assertions, parallel execution, fixtures, API testing, Trace Viewer, and CI/CD integration.

3. Is Playwright better than Selenium?

Answer: Playwright offers built-in auto-waiting, browser contexts, API testing, and strong debugging tools. Selenium has wide browser and language support and is still widely used. The right choice depends on your project and your existing stack.

4. Can beginners learn Playwright?

Answer: Yes. Start with JavaScript basics, get comfortable with locators and browser actions, then move on to fixtures, POM, API testing, and framework development.

5. Does Playwright support API testing?

Answer: Yes, through its APIRequestContext, which lets you send HTTP requests and validate responses.

6. Which language is best for Playwright?

Answer: JavaScript and TypeScript are the most popular. Beginners can start with JavaScript and pick up TypeScript as their projects grow.

7. Can Playwright run tests on Chrome, Firefox, and Safari?

Answer: Yes. It supports Chromium, Firefox, and WebKit. WebKit is the engine associated with Safari, so it helps you validate Safari-like behavior.

8. What is the Page Object Model?

Answer: A design pattern that keeps page locators and reusable actions separate from test cases, which makes code easier to organize, reuse, and maintain.

9. What's the difference between fixtures and hooks?

Answer: Hooks run setup and cleanup at specific points in a test run. Fixtures provide reusable setup and resources that tests request when they need them.

10. Where can I learn Playwright in Pune or Mumbai?

Answer: Look for a practical program that covers JavaScript, locators, hooks, fixtures, POM, API testing, framework development, and real projects. TestoMeter Edutech offers IT training and software testing courses for students and working professionals.

 

Final thoughts

Playwright is more than a browser automation tool. From locators and auto-waiting to API testing, network mocking, tracing, and CI/CD, it gives QA engineers what they need to build reliable, scalable, maintainable test frameworks.

If you're a manual tester, it's a real opening into automation. If you're a Selenium veteran, it's another strong tool for your toolkit. The best time to start is now, and the best way to learn is by building something.

Ready to get going? Start building your Playwright skills with TestoMeter Edutech at testometer.co.in, and follow us for more practical tutorials, testing tips, and certification updates.

12 Views
Social Share

Recent post

Recommended courses here

Recommended Certificates here

×