Software Development

Cross-Browser Testing with Playwright and WebdriverIO – How to Do It Right

Home

>

Blog

>

Software Development

>

Cross-Browser Testing with Playwright and WebdriverIO – How to Do It Right

Published: 2025/11/26

11 min read

Imagine a user trying to place an order on your site, only to find a button isn’t working – but just for them, on their specific browser. What once could have been a minor glitch, now can grow to a lost sale, a frustrated user and a dent in your brand’s reputation. Today, ensuring your application’s smooth user experience for everyone, everywhere, is not a luxury – it’s how it should be. And that’s exactly where cross-browser testing steps in.

In this article, we’ll show you how to get it right using two of the most popular tools, Playwright and WebdriverIO. We’ll give you real-world examples, configuration tips and best practices to help you catch those tricky, browser-specific bugs before they ever reach your users.

What is cross-browser testing?

Before diving deeper, let’s explain what cross-browser testing actually is. Cross-browser testing is the practice of checking if a website or web application functions and appears as intended across a variety of web browsers and their different versions. It also extends to different operating systems and mobile devices.

The goal of cross-browser testing is to catch and fix issues with the site’s layout, CSS styles and interactive elements, such as forms and buttons on any popular browser like Google Chrome, Mozilla Firefox, Safari and Microsoft Edge. All this is to ensure a consistent UX for everyone no matter the browser.

Why is cross-browser testing so important?

Browsers differ in their rendering engines and how they implement web standards. This means your application might behave differently – or even break – depending on the browser. The operating system also matters – a browser on Windows might not behave the same way on macOS, iOS or Android. For example, a site that works perfectly on Chrome may have a few layout issues on, say, Safari for macOS. This is actually a common problem since each browser interprets HTML, CSS and JavaScript in its own way.

That’s why you need to check for these differences if you want to ensure a seamless experience for all your users. You can do this either manually – by running tests yourself on various browsers and devices – or you can automate the process. Many teams rely on specialized tools like BrowserStack, Sauce Labs or LambdaTest to run these checks automatically, often integrating them directly into their CI/CD pipeline.

Ultimately, cross-browser testing helps you:

  • ensure a high-quality user experience,
  • minimize the risk of browser-specific bugs,
  • boost customer satisfaction and trust.

A quick overview: Playwright vs WebdriverIO

Now, let’s compare two of the most popular and modern frameworks for End-to-End (E2E) testing: Playwright and WebdriverIO. Why these two specifically?

They’re popular alternatives to each other: both are excellent for cross-browser testing, allowing you to run checks on all major browsers like Chrome, Firefox, Safari, Edge and even the increasingly popular Brave. They’re also actively developed and widely used in commercial projects. While both frameworks share a similar goal, they have a fundamentally different technological approach. Let’s take a closer look at each of them.

Playwright

Playwright, developed by Microsoft, allows you to run tests on Chromium (Chrome, Edge), Firefox and WebKit (Safari). It’s fast, reliable and supports parallel testing out of the box.

Key benefits:

  • Simple configuration for multiple browsers
  • Test recording and auto-generated code
  • Built-in parallel execution and isolated browser contexts
  • Greater speed and control due to working directly with browser engines

WebdriverIO

WebdriverIO is a versatile E2E framework built on the WebDriver and Chrome DevTools Protocol. It offers a rich plugin ecosystem and seamless integration with cloud testing services like BrowserStack and Sauce Labs.

Key benefits:

  • Flexible browser and device configurations
  • Large community and extensive plugin support
  • Easy CI/CD and reporting integration
  • Close real-user simulation via the W3C WebDriver Protocol

Which one should you choose?

Selecting the right framework really comes down to your team’s specific needs and what you’re already working with.

Playwright is an excellent choice if you’re starting a new project and want an all-in-one tool. It’s built with everything you need right out of the box, including robust API testing and reporting. Plus, since it works directly with the browser’s engines, it gives you more speed and control. This makes it ideal for teams that need quick test execution and want to natively test Safari’s WebKit.

As for WebdriverIO, it’s a more versatile tool, especially if you have an existing test setup. It’s a smooth transition if your team is already using a framework like Selenium, as its architecture is very similar. It also has a strong advantage for teams that use BDD/Cucumber and need seamless integration with cloud testing services like BrowserStack and Sauce Labs. Its use of the W3C WebDriver Protocol allows it to run tests that closely mimic a real user’s actions and it provides extensive flexibility with its configurations and integrations, including Docker.

How to do cross-browser testing right

1. Define critical user paths

Focus on essential user flows like login, registration or placing an order. Make sure these work flawlessly across browsers. But don’t stop there – work with product owners, UX designers and QA leads to identify the most valuable and high-risk paths based on business goals, past bugs and user data.

2. Automate and run tests in parallel

Both Playwright and WebdriverIO support parallel test execution, a critical feature that significantly speeds up the entire development and deployment cycle. Running tests in parallel helps reduce overall test execution time and ensures that issues are detected earlier in the pipeline. It also makes scaling easier, since you can run the same test suite across multiple browsers or devices simultaneously without heavily impacting build time.

3. Use retries and timeouts

Prevent flaky tests by configuring retries and appropriate timeouts. This is particularly important for browsers with slower performance, such as Safari or those in cloud-based environments like BrowserStack. Without enough time to load elements, tests can fail even if your application is working correctly. To handle this, a good practice is to set global timeouts for actions and assertions – like with Playwright’s setDefaultTimeout() or WebdriverIO’s waitForTimeout – to avoid unnecessary test hangs. Also, consider using retries selectively, perhaps only for specific test suites or environments known to be unstable, so you don’t mask actual issues.

4. Use visual test reports

Playwright supports screenshots and videos, while WebdriverIO integrates with tools like Allure to generate detailed test reports. These reports are a massive benefit for teams, as they show you exactly where a test failed. This drastically speeds up debugging by removing the need to reproduce the issue locally and it greatly improves communication when reporting bugs to developers. It’s also crucial for CI/CD, giving you visibility into tests running in the cloud where you don’t have a local view.

5. Test on real devices and environments

To ensure real-world accuracy, leverage services like BrowserStack or Sauce Labs to test your app across actual operating systems and devices. While local setups are convenient, they often mask crucial issues like device-specific rendering, genuine performance differences or mobile browser incompatibilities. Testing on real devices guarantees your application works reliably for every end user, regardless of their platform.

Example of Playwright configuration for cross-browser testing

The configuration above shows a great starting point for cross-browser testing with Playwright. Here’s a breakdown of the key settings you see in the image:

  • timeout – The set 30-second timeout gives tests enough time to run on slower browsers or in CI environments.
  • retries – A retry count of 1 allows a flaky test to run a second time. This helps eliminate failures caused by temporary issues like network glitches or slow loading.
  • reporter – This configuration uses a combination of list for a clean console output and html to generate a detailed graphical report after the tests are finished.
  • projects – This instructs Playwright to run the tests separately on Chromium (which covers Chrome and Edge), Firefox and WebKit (Safari), ensuring consistent behavior across all top browsers.

A good thing to keep in mind is that if your tests are configured for a single browser but you have the projects section enabled, they will run three times – once for each browser. After the tests are finished, the reporter combines a clean console list output with an html report. The full report is saved to the playwright-report folder, which should be added to your .gitignore file. For larger projects, you can also extend this configuration to include seperate settings for mobile viewports or set up retries to run only in your CI environment.

Sample Playwright test

The above example shows a basic E2E test that ensures a page loads correctly and has the right title.

The test uses a few key functions:

  • test(…) – This is the main function from Playwright’s Test Runner. executes the test’s logic separately for each browser defined in your configuration (Chromium, Firefox, WebKit).
  • page.goto(…) – This command opens the specified URL (which would be your baseURL in a real project).
  • expect(…).toHaveTitle(…) – This is an assertion that confirms the page title contains a specific phrase. It’s a quick and effective way to verify that the page loaded as expected.

As simple as this test is, it’s incredibly useful. You can think of it as a basic smoke test to confirm your application is functional across browsers. It also serves as a template for building more complex tests, such as those for logging in or filling out forms. Most importantly, if this test passes in all three configured browsers, you can be confident that your cross-browser configuration is working as intended.

Test running

To run the tests, we’re using the command “npx playwright test”. This is the default command for launching Playwright tests and it follows the settings defined in your configuration file.

Example of WebdriverIO configuration for cross-browser testing


In short, the setup you see in the image balances speed and stability: headless mode for faster runs, multiple instances for parallelism, reporting for clear insights and Safari kept “vanilla” because of its limitations.

Here is a breakdown of the key settings:

  • specs – defines the file path (./test/specs/**/*.js). This tells the framework which tests to execute.
  • maxInstances: 5 – limits the number of concurrent browser sessions. This speeds up execution while keeping the environment stable.
  • capabilities – specifies which browsers to run tests on:
    • Chrome: runs in headless mode with –disable-gpu to avoid rendering issues in CI/CD pipelines.
    • Firefox: also runs headless for faster and more stable execution.
    • Safari: no extra flags here. Since Safari doesn’t support headless mode like Chrome or Firefox, it runs as is.
  • framework: mocha – Mocha is chosen as the test framework because of its strong compatibility and integration with WebdriverIO.
  • reporters – we use a combination of spec (for console output) and allure (to give you detailed HTML reports).
  • MochaOpts: { timeout: 30000 } – This gives the Mocha test runner a generous 30-second window to complete each test. It’s a key setting to prevent tests from being flaky, especially when running multiple instances in parallel.

Sample WebdriverIO test


The screenshot features a basic smoke test designed to quickly verify that your application is reachable, loads without errors and displays the correct page identity.

Here is a breakdown of the code blocks:

  • describe block – groups related tests, here called “Page load test”.
  • it block – defines a single test: “should have the correct title”.
  • browser.url(‘https://your-app.com’) – opens the target application in the selected browser.
  • browser.getTitle() – retrieves the page title.
  • expect(title).toMatch(/Your App/) – asserts that the title contains the expected text (“Your App”).

This test is highly valuable as a sanity check to ensure your entire environment and cross-browser configurations are correctly set up and functional before moving on to more complex tests.

Test running

To execute tests in WebdriverIO, we use the command “npx wdio run wdio.conf.js”. It’s composed of three parts:

  • npx – runs the local WebdriverIO CLI without requiring a global installation.
  • wdio run – instruct WebdriverIO to start a test run.
  • wdio.conf.js – specifies the configuration file that contains all test settings (framework, browsers, reporters, etc.).

This command is the standard way of running WDIO tests locally or in CI pipelines. It’s similar to Playwright’s execution, except in WebdriverIO, you must explicitly point to the configuration file to define the test setup.

CI/CD integration (Playwright example)


The screenshot shows an example of a CI/CD workflow using GitHub Actions to integrate Playwright tests. This configuration is set to automatically trigger the end-to-end tests on every push and pull request to your repository – a critical practice for larger projects for catching bugs before they are merged into the main branch. The workflow ensures the application’s stability across all configured browsers and provides a valuable, downloadable visual test report for the team to review.

Summary

Robust, user-friendly web applications that work for everyone – that’s what cross-browser testing helps you deliver. The choice of tool depends on your goal: Playwright is often the go-to for a fast setup and an all-in-one solution that works right out of the box with all the major browser engines. WebdriverIO, in contrast, is built for more complex or existing projects. It provides enterprise-level flexibility, extensive integrations with cloud services and strong support for BDD frameworks.

Wrapping this all up, to make the most of your cross-browser testing efforts, be sure to:

Focus your efforts on the most critical user flows.

Boost efficiency by automating and running tests in parallel.

Validate your application in real-world scenarios using real devices and environments.

Hook your tests up to your CI/CD pipeline to find bugs as soon as they happen.

Want to deliver a flawless user experience and catch bugs before they go live? Our team can help you build a robust cross-browser testing strategy. Contact us.

FAQ

What is the core difference between Playwright and WebdriverIO?

Playwright is generally an all-in-one solution best suited for new projects, offering greater speed and built-in support for testing WebKit (Safari). WebdriverIO is a more versatile tool designed for complex or existing projects, offering robust enterprise features, extensive plugin support and integration with cloud testing services and BDD frameworks.

Why do I need to test on real devices instead of just emulators?

Local setups and emulators often mask crucial real-world issues like device-specific rendering problems, performance bottlenecks or mobile browser incompatibilities. Testing on real devices – using services like BrowserStack or Sauce Labs – is the only way to ensure your application’s reliability for every end user.

How can I make my cross-browser testing efforts most effective?

Maximize your testing efforts by prioritizing critical user flows (e.g., login, checkout), increase speed and efficiency by automating and running tests in parallel, validating the application using real devices and environments and integrating testing directly into your CI/CD pipeline for instant bug detection.

Do Playwright and WebdriverIO support parallel test execution?

Yes, both Playwright and WebdriverIO fully support parallel test execution. This is a critical feature that significantly speeds up the overall test run time and ensures that issues are detected earlier in the development pipeline.

Why do I need to configure retries and timeouts for cross-browser tests?

You need retries and timeouts to prevent flaky tests. This compensates for the slower performance of certain browsers (e.g., Safari) or cloud testing environments, ensuring tests don’t fail due to elements not loading fast enough. Setting proper timeouts and strategic retries ensures you don’t get false negatives.

About the authorKarolina Blok

Test Automation Engineer

A Test Automation Engineer with 7 years’ experience in the IT industry, Karolina has tested web and mobile applications that implement the latest technologies, like the Internet of Things and AI. Having worked with clients from a range of sectors, from financial services through gaming to fleet management, she has diverse expertise in designing and conducting both manual and automated tests to ensure the highest software quality. As Karolina focuses on driving efficiency and prioritizing value-added testing in her projects, her professional interests revolve around further developing her test automation skills, exploring different frameworks and implementing cloud-based solutions.

Subscribe to our newsletter

Sign up for our newsletter

Most popular posts

Newsletter

Privacy policyTerms and Conditions

Copyright © 2025 by Software Mind. All rights reserved.