new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Vitest · Guide · all subjects

advanced/matchers

81 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

Custom snapshot matchers with Snapshots

To build custom snapshot matchers (wrappers around toMatchSnapshot(), toMatchInlineSnapshot(), or toMatchFileSnapshot()), use the Snapshots type exported from vitest.

TypeScript import requirement for matchers

When extending the Matchers interface in TypeScript, importing 'vitest' is required to make TypeScript recognize the file as an ES module. Type declarations will not work without this import.

this.soft in custom matchers

The soft property indicates whether the assertion was called as a soft one. You do not need to respect it; Vitest will always catch the error.

this.assertion in custom matchers (version 5.0.0+)

The assertion property contains the underlying Chai assertion object. This is the same instance that Chai plugins receive, giving access to Chai's flag system and chainable methods. Useful for custom matchers that need to interact with Chai's internals.

expect.getState() method

Call expect.getState() to get current test context information including currentTestName, testPath, environment, and other state values. This is useful when you cannot access this context directly.

Vitest compatible with Chai and Jest matcher APIs

Vitest is compatible with both Chai and Jest. You can use either the chai.use API or expect.extend for extending matchers.

Include ambient declaration file in tsconfig.json

When using an ambient declaration file (e.g: vitest.d.ts) to extend the Matchers interface, ensure it is included in tsconfig.json.

expect.extend basic usage

Call expect.extend with an object containing your matchers. A matcher function receives the received value as the first argument and returns an object with pass (boolean) and message (function returning string) properties.

expect.extend example: toBeFoo

Example custom matcher that checks if a value equals 'foo'. The matcher function accesses isNot from this context and returns {pass: boolean, message: () => string}. Do not alter pass based on isNot; Vitest handles it automatically.

TypeScript matcher declaration in vitest.d.ts

To extend default Matchers interface in TypeScript, create an ambient declaration file (e.g: vitest.d.ts) with: import 'vitest'; declare module 'vitest' { interface Matchers<R, T> { toBeFoo: () => R } }. R is the assertion return type, T is the type of the received value.

Matcher return type R in TypeScript

R is the assertion return type. For synchronous matchers, R makes the return type void for regular assertions and Promise<void> when used with .resolves, .rejects, expect.poll, or expect.element.

Matcher return type T in TypeScript

T is the type of the received value. Use T when an expected argument should have the same type as the received value, e.g. toEqualTyped: (expected: T) => R.

SyncMatcherResult interface

A matcher should return an object compatible with SyncMatcherResult: {pass: boolean, message: () => string, actual?: unknown, expected?: unknown, meta?: object}. Pass actual and expected to automatically display them in a diff when the matcher fails.

Async custom matcher declaration

If a matcher implementation is asynchronous, declare its return type as Promise<void> instead of R in the Matchers interface, and await it in the test. The matcher function should return {pass: boolean, message: () => string}.

Custom matcher types from vitest

Vitest exposes three types for custom matchers since version 4.1: Matcher (the function type), MatcherResult (the return value), and MatcherState (state available as this).

Matcher function types example

Example showing three ways to type custom matchers: (1) simple matcher using function keyword for this access, (2) matcher with arguments using Matcher<MatcherState, [arg1, arg2]>, (3) matcher with custom annotations using function syntax with explicit MatcherState and MatcherResult types.

this.isNot in custom matchers

The isNot property is true if the matcher was called on not (expect(received).not.toBeFoo()). Do not alter the pass value based on isNot; Vitest automatically reverses it.

this.promise in custom matchers

The promise property contains the name of the modifier if the matcher was called on resolved/rejected (e.g., expect(promise).resolves.toBeFoo()). Otherwise, it is an empty string.

this.equals utility function

The equals utility function compares two values and returns true if equal, false otherwise. It supports objects with asymmetric matchers by default and is used internally for almost every matcher.

this.utils in custom matchers

The utils property contains a set of utility functions for displaying messages in custom matchers.

this.currentTestName in custom matchers

The currentTestName property returns the full name of the current test, including the describe block.

this.task in custom matchers (version 4.1.0+)

The task property contains a reference to the Test runner task when available. It is undefined when using the global expect with concurrent tests. Use context.expect instead to ensure task is available in custom matchers with concurrent tests.

this.testPath in custom matchers

The testPath property contains the file path to the current test.

this.environment in custom matchers

The environment property contains the name of the current environment (for example, 'jsdom').

resolves and rejects matchers for promises

The .resolves and .rejects helpers allow you to assert on a promise directly without awaiting it into a variable first. They unwrap the promise and apply the matcher to the resolved or rejected value. You must await the expect statement before the .resolves or .rejects matcher.

expect.hasAssertions() prevents silent test passes

expect.hasAssertions() verifies that at least one assertion ran during the test, which guards against assertions inside callbacks or .then() chains that might never execute, preventing silent test passes.

expect.assertions(n) for exact assertion count

expect.assertions(n) ensures that exactly n assertions run during a test, providing more precise control than expect.hasAssertions() when you know the exact number of assertions that should execute.

expect.requireAssertions config option

Setting expect.requireAssertions in your Vitest config requires at least one assertion in every test in your project, eliminating the need to add expect.hasAssertions() to each test manually.

Wrapping function required for toThrow

When using toThrow, you must wrap the function call in another function so Vitest can catch the error. If you wrote expect(compileCode('')).toThrow() without wrapping, the error would be thrown before expect gets a chance to catch it, and the test would fail with an unhandled error.

expect.soft for soft assertions

The expect.soft method records assertion failures but lets the test keep running instead of stopping immediately. This is useful for checking several independent things and seeing all the failures at once rather than fixing them one by one.

Soft assertions for validating complex objects

Soft assertions are especially useful for validating the shape of an API response or a complex object where multiple fields might be wrong at the same time. The test report will show all fields that did not match.

Example of toBeCloseTo with floating point numbers

Example: test('adding floating point numbers', () => { const value = 0.1 + 0.2; expect(value).toBeCloseTo(0.3) }). This demonstrates using toBeCloseTo for comparing floating point numbers that may have rounding errors.

Example of asymmetric matchers with toEqual

Example: expect(user).toEqual({ id: expect.any(Number), name: 'Alice', email: expect.stringContaining('@'), roles: expect.arrayContaining(['viewer']), }). This demonstrates using asymmetric matchers inside toEqual to describe the shape of a value without specifying exact content.

Example of soft assertions

Example: test('check multiple fields', () => { const user = { name: 'Alice', age: 30, role: 'admin' }; expect.soft(user.name).toBe('Alice'); expect.soft(user.age).toBe(25); expect.soft(user.role).toBe('admin'); }). This demonstrates using expect.soft to check multiple fields and see all failures at once.

toBeCloseTo matcher for floating point comparison

The toBeCloseTo matcher compares numbers within a small rounding error. Use it for floating point comparisons because in JavaScript, 0.1 + 0.2 does not equal 0.3 exactly (it equals 0.30000000000000004).

toBe matcher for exact equality

The toBe matcher checks that a value is exactly equal using Object.is. It works great for primitive values like numbers, strings, and booleans. For objects, toBe checks identity (whether they are the exact same object in memory), not whether they have the same shape.

toEqual matcher for structural comparison

The toEqual matcher recursively compares every field of an object or element of an array, ignoring object identity. Two objects with the same content are toEqual but not toBe. Use toEqual for comparing structure and shapes.

toStrictEqual matcher stricter than toEqual

The toStrictEqual matcher is stricter than toEqual in three ways: it checks undefined properties, distinguishes sparse arrays from undefined values, and verifies that objects have the same type (not just the same shape).

Matcher selection rule of thumb

Use toBe for primitives (numbers, strings, booleans), toEqual for comparing structure, and toStrictEqual when you also care about types and explicit undefined values.

Negating matchers with .not

Any matcher can be negated by inserting .not before it. This is useful when you want to verify that something is not the case, such as expect(1 + 2).not.toBe(0).

toBeNull matcher

The toBeNull matcher matches only null values.

toBeUndefined matcher

The toBeUndefined matcher matches only undefined values.

toBeDefined matcher

The toBeDefined matcher is the opposite of toBeUndefined. It passes for anything that is not undefined.

toBeTruthy matcher

The toBeTruthy matcher matches anything that an if statement would treat as true.

toBeFalsy matcher

The toBeFalsy matcher matches anything that an if statement would treat as false.

Truthiness matcher precision matters

Using toBeTruthy when you really mean toBeDefined can hide bugs, because 0 and empty string are both defined but falsy. Pick the matcher that most precisely describes what you are checking.

toBeGreaterThanOrEqual matcher

The toBeGreaterThanOrEqual matcher checks if a value is greater than or equal to a specified number.

toBeLessThanOrEqual matcher

The toBeLessThanOrEqual matcher checks if a value is less than or equal to a specified number.

Floating point arithmetic gotcha

In JavaScript, 0.1 + 0.2 does not equal 0.3 exactly; it equals 0.30000000000000004. Therefore, a toBe(0.3) check will fail. Use toBeCloseTo instead.

toMatch matcher for regex testing

The toMatch matcher tests strings against regular expressions. It is especially handy when you care about a pattern rather than an exact value, like checking that an error message contains a certain word or that a URL matches a particular format.

toContain matcher for arrays and iterables

The toContain matcher checks that an array (or any iterable, like a Set) includes a particular item. It uses === for comparison, so it works well for primitives.

toContainEqual matcher for array objects

The toContainEqual matcher checks that an array contains an object with a particular structure. It works like toEqual but for individual items inside an array.

toMatchObject matcher for partial object matching

The toMatchObject matcher verifies that the object contains at least the properties you specify, and ignores any additional ones. Use it when you want to check only a few important fields without specifying every property.

toHaveProperty matcher for checking object properties

The toHaveProperty matcher is used for checking individual properties, especially nested ones. You pass a dot-separated path and optionally an expected value. For example, expect(user).toHaveProperty('address.city', 'Paris').

Asymmetric matchers in deep comparison

Asymmetric matchers describe what a value should look like without pinning down the exact content. They work inside any matcher that does deep comparison, like toEqual or toMatchObject.

expect.any() asymmetric matcher

The expect.any(Constructor) asymmetric matcher matches any value created with the given constructor (e.g., Number, String, Array).

expect.stringContaining() asymmetric matcher

The expect.stringContaining(str) asymmetric matcher matches a string that includes the given substring.

expect.stringMatching() asymmetric matcher

The expect.stringMatching(regex) asymmetric matcher matches a string against a regular expression.

expect.arrayContaining() asymmetric matcher

The expect.arrayContaining(arr) asymmetric matcher matches an array that includes all items in the expected array. Order does not matter, and extra items are allowed.

expect.objectContaining() asymmetric matcher

The expect.objectContaining(obj) asymmetric matcher matches an object that includes at least the specified properties.

Give your agent this brain