What's the difference between toBe and toEqual? When do you reach for each, and what other matchers matter?
Understanding reference vs. structural equality in assertions — a classic source of confusing failures.
toBe checks REFERENCE / primitive identity — it's Object.is, essentially ===. Use it for primitives (numbers, strings, booleans) and when you specifically want to assert two variables point to the SAME object instance. toEqual checks STRUCTURAL / deep equality — it recursively compares the contents of objects and arrays, so two different objects with the same shape and values pass. The classic bug: expect({a:1}).toBe({a:1}) FAILS because they're two distinct objects with different references, even though their contents match; you wanted toEqual. Conversely, using toEqual where you meant to assert identity can hide a bug where a function returned a fresh copy instead of the same reference. A few related nuances: toEqual ignores undefined properties and array holes; toStrictEqual is stricter (checks undefined props and that types/classes match), useful when the exact shape matters. Beyond equality, the matchers worth knowing keep tests readable and failures diagnostic: toContain (array/string membership), toMatch (regex on strings), toThrow (a function throws, optionally matching a message), toHaveBeenCalledWith (a mock/spy was called with given args), toBeCloseTo (floating-point comparison, since 0.1+0.2 !== 0.3), and truthiness helpers toBeTruthy/toBeNull/toBeDefined. For DOM there are jest-dom matchers like toBeVisible/toHaveTextContent that produce far better failure messages than poking at properties. Choosing the RIGHT matcher matters beyond correctness: a precise matcher gives a precise failure message ('expected 3 to be 4', not 'expected true to be false'), which is half the value of a test.
Choosing the correct assertion; debugging a 'they look equal but toBe fails' surprise.
expect(2 + 2).toBe(4); // primitives: reference/=== is fine
expect({ a: 1 }).toBe({ a: 1 }); // FAILS: different object references
expect({ a: 1 }).toEqual({ a: 1 });// passes: deep structural equality
expect([1, 2, 3]).toContain(2);
expect(() => parse('')).toThrow(/empty/);
expect(0.1 + 0.2).toBeCloseTo(0.3); // floats: never toBe(0.3)
expect(mockFn).toHaveBeenCalledWith('id-42');