The difference between toBe() vs toEqual() assertion in Playwright

Feb 24 / Artem Bondar

What documentations says

The difference between toBe() and toEqual() assertion is not very intuitive, so let's quickly glance at what Playwright documentation says:

toBe()
- Compares value with expected by calling Object.is. This method compares objects by reference instead of their contents, similarly to the strict equality operator ===

toEqual() - Compares contents of the value with contents of expected, performing "deep equality" check. For objects, this method recursively checks equality of all fields, rather than comparing objects by reference as performed by expect(value).toBe()For primitive values, this method is equivalent to expect(value).toBe().

Unfortunately, not very clear. Let's dive deeper using examples

Assertion of primitives

Primitive values are the simplest elements available in a programming language. A primitive is the smallest 'unit of processing' available to a programmer of a given machine. In JavaScript, those values are: number, string, bigint, boolean, undefined, symbol, null.

So let's write a simple code using primitives and make an assertion:
In this example, the test will pass. toBe() and toEqual() work the same, because 5 is a primitive value. So when you assert primitives, it does not matter which assertion to use.

Assertion of objects

Now let's look at the second example, and instead of asserting the primitives, we assert two simple objects, which look the same: 
In this example, we have two constants, houseA and houseB, which have assigned values of the objects with the same values.

toEqual()
assertion passes because it performs "deep equality" of the object content. In other words, it looks at the exact values of two objects and compares them. Since the values are the same - the assertion passes.

toBe() assertion fails because it does not look at the content, it looks at the reference to the object! And if a reference is different - the assertion will fail. In our example, we have two independent objects, assigned to individual constants. houseA reffers to one one object, houseB reffers to another object. They reffer to different object, so not the same.

And just to make it even more clear, here is example:
In this example, houseB constant refers to houseA, and houseA refers to the object. So houseA and houseB refer to the same object, so both assertions toBe() and toEqual() will pass as well.

Summary

In most of the cases, the toEqual() is all you need to perform assertions of the data deep equality. But if you need to dig deeper, and validate that not just content, but the reference to the object is the same, then the toBe() assertion has to be used. For the primitive data types, it does not matter what assertion to use, it will work the same.

Playwright best practice is to use a Locator Assertions instead of utilizing toBe() or toEqual() which are related to Generic Assertions. Check more about the difference between the assertions is this blog post.

In my SDET with Playwright course, I have a separate lecture that shows in detail the two types Playwright assertions: Generic assertions and Locator assertions. How and when to use them correctly.