CodeWithMMAK
Test AutomationIntermediate

WebdriverIO Assertions: The Complete Guide for 2026

Master WebdriverIO's built-in assertion library. Learn how to use browser and element matchers to create robust, self-healing automated tests.

CodeWithMMAK
March 3, 2023
10 min

Introduction

🎯 Quick Answer

WebdriverIO uses the expect-webdriverio library, which provides a set of specialized matchers for browser and element assertions. These assertions are asynchronous and feature built-in retry logic, meaning they will automatically wait for a condition to be met before failing. The basic syntax is await expect(element).toBeDisplayed(). This makes your tests more resilient to network latency and slow-rendering components.

In end-to-end testing, assertions are the heart of your scripts. They are the checkpoints that verify whether your application is behaving as expected. WebdriverIO's assertion library is built on top of Jest's expect but is specifically optimized for the asynchronous nature of web browsers.

📖 Key Definitions

Matcher

A specialized function used in an assertion to verify a specific property or state (e.g., toHaveText, toBeEnabled).

Asynchronous Assertion

An assertion that returns a promise and waits for a condition to be true within a specified timeout period.

Soft Assertion

An assertion that allows the test to continue even if it fails, typically used for non-critical UI checks.

Retry Logic

The mechanism that repeatedly checks a condition until it passes or the timeout is reached, reducing "flaky" test results.

Core Matchers in WebdriverIO

WebdriverIO categorizes its matchers into browser-level and element-level checks.

Browser Matchers

These are used to verify the state of the entire browser window or tab.

  • toHaveUrl: Verifies the exact current page URL.
  • toHaveTitle: Checks the page title for an exact match or substring.
  • toHaveUrlContaining: Checks if the current URL contains a specific string.

Element Matchers

These are used to verify the state or properties of specific DOM elements.

  • toBeDisplayed: Checks if an element is visible to the user.
  • toExist: Checks if an element is present in the DOM (even if hidden).
  • toBeEnabled: Verifies that an input or button is not disabled.
  • toHaveText: Matches the visible text content of an element.
  • toHaveValue: Checks the current value of an input field.
  • toBeSelected: Verifies if a checkbox, radio button, or option is selected.

🚀 Step-by-Step Implementation

1

Identify the Target

Locate the element or browser property you want to verify using a selector (e.g., const btn = await $('#submit')).

2

Choose the Right Matcher

Select a matcher that fits your requirement (e.g., use toBeClickable if you want to ensure the button can be interacted with).

3

Write the Assertion

Use the await expect(...) syntax to perform the check.

4

Configure Custom Timeouts (Optional)

If an element takes longer than usual to appear, pass a custom timeout: await expect(btn).toBeDisplayed({ timeout: 5000 }).

5

Run and Verify

Execute your test and ensure the assertion provides clear feedback in the logs if it fails.

Common Errors & Best Practices

⚠️ Common Errors & Pitfalls

  • Missing 'await' Keyword

    Forgetting to await the assertion. Since WDIO assertions are asynchronous, failing to await them will cause the test to proceed before the check is complete.

  • Using Generic Matchers

    Using expect(await el.isDisplayed()).toBe(true) instead of the specialized await expect(el).toBeDisplayed(). The latter includes built-in retries, while the former does not.

  • Over-Asserting

    Adding too many assertions for every minor UI detail, which makes tests brittle and slow.

Best Practices

  • Always use Specialized Matchers (like toHaveText) over generic boolean checks to benefit from automatic retries.
  • Use Sub-string Matching with containing matchers when exact text matches are too restrictive or dynamic.
  • Implement Custom Error Messages to make debugging easier: await expect(el).toBeDisplayed({ message: 'Login button was not found!' }).
  • Leverage Negative Assertions using .not (e.g., await expect(el).not.toBeDisplayed()) to verify elements disappear after an action.

Frequently Asked Questions

How do I change the default timeout for assertions?

You can set the waitforTimeout in your wdio.conf.js file, or pass a specific timeout object to an individual assertion.

Can I use Jest matchers with WebdriverIO?

Yes, WebdriverIO's expect is compatible with standard Jest matchers, but it's recommended to use the expect-webdriverio versions for browser interactions.

What is the difference between toBeDisplayed and toExist?

toExist only checks if the element is in the HTML source, while toBeDisplayed also checks if it's visible on the screen (not hidden by CSS).

Example Usage

Code Snippet
describe('WebdriverIO Assertions Demo', () => {
    it('should verify page and element states', async () => {
        await browser.url('https://ecommerce-playground.lambdatest.io/');
        
        // Browser level assertion
        await expect(browser).toHaveTitle('Your Store');
        
        // Element level assertions
        const searchInput = await $('#input-search');
        await expect(searchInput).toBeEnabled();
        await expect(searchInput).toHaveAttribute('placeholder', 'Search For Products');
        
        // Negative assertion
        const hiddenElement = await $('.hidden-msg');
        await expect(hiddenElement).not.toBeDisplayed();
    });
});

Conclusion

Mastering WebdriverIO assertions is key to building stable and reliable automation suites. By using asynchronous matchers with built-in retries, you can eliminate many common causes of test flakiness and ensure your tests provide accurate feedback on your application's health.

📝 Summary & Key Takeaways

This guide provided a deep dive into WebdriverIO assertions, highlighting the power of the expect-webdriverio library. We explored both browser and element-level matchers, emphasizing the importance of asynchronous execution and built-in retry logic. The tutorial outlined a structured approach to writing assertions, identified common mistakes like missing await keywords, and detailed best practices for creating resilient tests. By leveraging these specialized matchers, automation engineers can build self-healing tests that gracefully handle the dynamic nature of modern web applications.

Share it with your network and help others learn too!

Follow me on social media for more developer tips, tricks, and tutorials. Let's connect and build something great together!