Expect more with playwright-expect

Yevhen Laichenkov
6 min readJun 23, 2021

--

Folks! I’m thrilled to announce you my brand new assertion library playwright-expect. It intended for use with test runners such as Jest and Playwright Test.

Don’t confuse with the expect-playwright library, it’s not the same and it’s not a fork of it.

Before we start, I’d highly recommend to subscribe to Test Automation Weekly digest to keep up with latest news in test automation world.

Motivation

First of all, the main reason why I built it was because I started working with Playwright a lot and faced a problem when I had to write tons of additional functions such as trimming string, converting it to the lowercase, waiting for the element, and others before asserting. I tried expect-playwright, but it seems, that doesn’t have all important methods and additional features, which most of you and I really need. So, I’ve decided to deep dive into assertions libraries for different frameworks in different languages to learn more about them. All over, I’ve come up with the idea that I’d like to have something similar that we have for the WebdriverIO, but for the new Playwright Test runner. Eventually, I’ve created playwright-expect and this is not another assertion library, it’s something more, because it includes not just assertion methods. It has extra powerful features for end-to-end testing needs.

Key features

Here I’d like to describe main and significant features, that you can find and enjoy of using them.

First and foremost, I want to notice that all methods, which are expecting an element can accept it in three different ways:

  1. [page, selector] (recommended)
await expect([page, 'button']).toBeEnabled();

2. ElementHandle

await expect(await page.$('button')).toBeDisabled();

3. Promise<ElementHandle>

await expect(page.$('button')).toBeDisabled(false);

I believe it’s quit simple and clear. Let’s continue with the most valuable features.

Rich

I’ve designed and developed all major assertion methods for end-to-end testing. Furthermore, I have implemented additional features to work with strings and to wait before asserting. Even if I missed something here, you would always find all information in the rich API documentation.

Easy to use

It’s really intuitive and user friendly. You just need to do three steps to start using it:

  1. Install:
npm i -D playwright-expect

2. Import or require our custom matchers and Playwright’sexpect function to extend default assertions in the playwright.config.ts or in the playwright.config.js files.

3. Invoke the expect ’s extend function with our custom matchers as an argument:

// playwright.config.ts
import { expect } from '@playwright/test';
import { matchers } from 'playwright-expect';

// add custom matchers
expect.extend(matchers);

or

// playwright.config.js
const { expect } = require('@playwright/test');
const { matchers } = require('playwright-expect');

// add custom matchers
expect.extend(matchers);

Here we are, everything is ready to start testing and asserting.

Exhaustive messages and diff highlights

It provides comprehensive error messages and highlights the difference and that’s really awesome. Let me show you how it looks like.

For instance, we have an ordinary test, where we’re expecting that the current url equals to the expected one, but we’re going to break and put the wrong url to see the diff highlights:

Then let’s run it wit the following command:

npx playwright test ./current-url.test.ts

Now, we can see the following error message in the terminal:

error message with diff highlights

As you can see, it contains three signification sections:

  1. Error — shows exact line of code where it fails
  2. Expected — shows the expected value and diff highlights
  3. Received — shows the received value and diff highlights too

Also, we can see a pretty norm stack trace for the error. All over, I think it’s really neat and it could reduce time on finding the problem. Even more, we have just used our first toHaveUrl custom matcher method that could save time on end-to-end tests development.

If you want to run this test and see the same error message with diff highlights, then I assume that you have installed all dependencies and extended expect. Hence, you’ve done that I’ve mentioned above in previous sections

Additional features

In fact, the comparison is case-sensitive by default, and it’s good, we should compare exact value. However, sometimes we don’t care about it and we would like to check that the given element’s text equals to the provided text ignoring case-sensitive. Agree? Great. Let’s dive in.

Let’s consider the following test, where we’re expecting that the title of the page equals to the expected on:

As you can see I’ve provided ignoreCase property to the toHaveTitle function as a second argument. If I didn’t add it, test would fail, because in the word Playwright the first letter is capitalised. It’s pretty useful feature.

Another case, we have some label that has a whitespace such as space, tab, no-break space, etc. But we don’t want to do additional work before checking such as getting label’s text and then trimming it, and only after that verifying the trimmed value. We’d like just check it, and that’s it. So, I have a good news for you, because we have something for it in the playwright-expect library, we just need to provide it as we’ve already done with ignoreCase but now we have to provide trim property.

You can run the test above without providing the trim property and take a look at the error message, it’ll be like this:

error message with diff highlights #2

As demonstrated, the diff highlights feature works pretty good, and help us easily and quickly find root cause of the issue.

Another thing I want to discuss is timeout errors. None of us likes when our tests fail due to timeout errors, so your knee-jerk reaction might be to add wait methods to avoid the timeout errors. However, with playwright-expect you can just pass additional parameter timeout and it will wait for the element before asserting. Imagine the case when we need to verify that success notification message appears, after some action, but not instantly and we know only that it should take not more than 5 seconds.

Our test will look like this one:

NOTE:
Please, keep in mind wait for the element works only with the [page, selector] approach. In fact, it’s the recommended approach.

Moreover, autocompletion works just out of the box for TypeScript and JavaScript as well, as showed on the gif below:

autocompletion

You can also test for the opposite of a matcher:

await expect([page, '#checkbox']).not.toBeChecked();

Conclusion

Playwright Test is well built test runner, but it doesn’t contain helpful matchers for asserting values. Also, Playwright API is low level and to accomplish everything that I showed in this article will require additional actions and time. Although, expect-playwright has some methods for asserting, it’s not enough for end-to-end testing and it doesn’t provide diff highlights, ignoreCase, trim, waitForUrl, and other features. That is why, I highly recommend you install and start using the playwright-expect library and I know that, you see the difference and you’ll enjoy it.

Thank you for reading. Hope you liked the article. Also, you can follow me on Twitter and connect with me on LinkedIn where I discuss new technologies from time to time.

--

--

Yevhen Laichenkov

Software Development Engineer In Test / Open source creator