Skip to content

Commit f22cb2d

Browse files
authored
docs: add expect API (#370)
1 parent 6014250 commit f22cb2d

File tree

6 files changed

+647
-2
lines changed

6 files changed

+647
-2
lines changed

website/docs/en/api/rstest/mockFunctions.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,8 @@ Clears all mocks properties and reset each mock's implementation to its original
8080
- **Type:** `() => Rstest`
8181

8282
Reset all mocks and restore original descriptors of spied-on objects.
83+
84+
## More
85+
86+
- [Mock Matchers](../test-api/expect#mock-matchers)
87+
- [MockInstance API](./mockInstance)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
["test", "describe", "hooks"]
1+
["expect", "test", "describe", "hooks"]
Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
---
2+
title: Expect
3+
overviewHeaders: [2, 3]
4+
---
5+
6+
# Expect
7+
8+
`expect` is used to assert values in tests. It provides a rich set of matchers, supports chainable modifiers, soft assertions, polling, and snapshot testing.
9+
10+
## expect
11+
12+
- **Type:** `<T>(actual: T, message?: string) => Assertion<T>`
13+
14+
Creates an assertion object for the given value.
15+
16+
```ts
17+
import { expect } from '@rstest/core';
18+
19+
expect(1 + 1).toBe(2);
20+
expect('hello').toBeDefined();
21+
expect([1, 2, 3]).toContain(2);
22+
```
23+
24+
## expect.not
25+
26+
Negates the assertion.
27+
28+
```ts
29+
expect(1 + 1).not.toBe(3);
30+
expect('foo').not.toBeUndefined();
31+
```
32+
33+
## expect.soft
34+
35+
- **Type:** `<T>(actual: T, message?: string) => Assertion<T>`
36+
37+
Performs a soft assertion. The test will continue even if the assertion fails, and all failures will be reported at the end.
38+
39+
```ts
40+
expect.soft(1 + 1).toBe(3); // will not stop the test
41+
expect.soft(1 + 2).toBe(4);
42+
```
43+
44+
## expect.poll
45+
46+
- **Type:** `<T>(actual: () => T, options?: { interval?: number, timeout?: number, message?: string }) => Assertion<T>`
47+
48+
Polls the value returned by the function until the assertion passes or timeout.
49+
50+
```ts
51+
await expect.poll(() => getStatus()).toBe('ready');
52+
```
53+
54+
## expect.unreachable
55+
56+
- **Type:** `(message?: string) => never`
57+
58+
Marks a code path as unreachable. Throws if called.
59+
60+
```ts
61+
if (shouldNotHappen) {
62+
expect.unreachable('This should never happen');
63+
}
64+
```
65+
66+
## expect.assertions
67+
68+
- **Type:** `(expected: number) => void`
69+
70+
Asserts that a certain number of assertions are called during a test.
71+
72+
```ts
73+
expect.assertions(2);
74+
expect(1 + 1).toBe(2);
75+
expect(2 + 2).toBe(4);
76+
```
77+
78+
## expect.hasAssertions
79+
80+
- **Type:** `() => void`
81+
82+
Asserts that at least one assertion is called during a test.
83+
84+
```ts
85+
expect.hasAssertions();
86+
expect(1 + 1).toBe(2);
87+
```
88+
89+
## expect.addEqualityTesters
90+
91+
- **Type:** `(testers: Array<Tester>) => void`
92+
93+
Adds custom equality testers for use in assertions.
94+
95+
```ts
96+
expect.addEqualityTesters([
97+
(a, b) => {
98+
if (typeof a === 'number' && typeof b === 'number') {
99+
return Math.abs(a - b) < 0.01;
100+
}
101+
},
102+
]);
103+
expect(0.1 + 0.2).toEqual(0.3); // true with custom tester
104+
```
105+
106+
## expect.addSnapshotSerializer
107+
108+
- **Type:** `(serializer: SnapshotSerializer) => void`
109+
110+
Adds a custom serializer for snapshot testing.
111+
112+
```ts
113+
expect.addSnapshotSerializer({
114+
test: (val) => typeof val === 'string' && val.startsWith('secret:'),
115+
print: (val) => '***MASKED***',
116+
});
117+
expect('secret:123').toMatchSnapshot(); // snapshot will be masked
118+
```
119+
120+
## expect.getState / expect.setState
121+
122+
- **Type:**
123+
- `getState: () => MatcherState`
124+
- `setState: (state: Partial<MatcherState>) => void`
125+
126+
Gets or sets the internal matcher state.
127+
128+
```ts
129+
const state = expect.getState();
130+
console.log(state.currentTestName);
131+
expect.setState({ currentTestName: 'custom name' });
132+
console.log(expect.getState().currentTestName); // will output 'custom name'
133+
```
134+
135+
## Matchers
136+
137+
### Common matchers
138+
139+
Common matchers are used to assert basic value comparisons, type checks, and structure checks. They cover most day-to-day assertions for numbers, strings, objects, arrays, and more.
140+
141+
- `toBe(value)`. Checks strict equality using `Object.is`.
142+
- `toEqual(value)`. Checks deep equality (recursively checks all fields).
143+
- `toStrictEqual(value)`. Checks deep equality, including undefined properties and array sparseness.
144+
- `toBeTruthy()`. Checks if the value is truthy.
145+
- `toBeFalsy()`. Checks if the value is falsy.
146+
- `toBeNull()`. Checks if the value is `null`.
147+
- `toBeUndefined()`. Checks if the value is `undefined`.
148+
- `toBeDefined()`. Checks if the value is not `undefined`.
149+
- `toBeNaN()`. Checks if the value is `NaN`.
150+
- `toBeGreaterThan(number)`. Checks if the value is greater than the given number.
151+
- `toBeGreaterThanOrEqual(number)`. Checks if the value is greater than or equal to the given number.
152+
- `toBeLessThan(number)`. Checks if the value is less than the given number.
153+
- `toBeLessThanOrEqual(number)`. Checks if the value is less than or equal to the given number.
154+
- `toBeCloseTo(number, numDigits?)`. Checks if a number is close to another number, optionally with a given precision.
155+
- `toContain(item)`. Checks if an array or string contains the given item.
156+
- `toContainEqual(item)`. Checks if an array contains an item (using deep equality).
157+
- `toMatch(stringOrRegExp)`. Checks if a string matches a regex or substring.
158+
- `toMatchObject(object)`. Checks if an object matches a subset of properties.
159+
- `toHaveLength(length)`. Checks if an object has a `.length` property with the given value.
160+
- `toHaveProperty(path, value?)`. Checks if an object has a property at the given path, optionally with a specific value.
161+
- `toBeInstanceOf(class)`. Checks if the value is an instance of the given class.
162+
- `toBeTypeOf(type)`. Checks if the value is of the given type (e.g. 'string').
163+
- `toSatisfy(fn)`. Checks if the value satisfies the provided function.
164+
- `toBeOneOf(array)`. Checks if the value is one of the values in the given array.
165+
- `toThrowError(expected?)`. Checks if a function throws an error, optionally matching the error message or type.
166+
167+
```ts
168+
// Equality
169+
expect(1 + 1).toBe(2);
170+
expect({ a: 1 }).toEqual({ a: 1 });
171+
expect([1, undefined]).toStrictEqual([1, undefined]);
172+
expect(2).toBeOneOf([1, 2, 3]);
173+
174+
// Type & Definition
175+
expect(null).toBeNull();
176+
expect(undefined).toBeUndefined();
177+
expect('foo').toBeDefined();
178+
expect('bar').toBeTypeOf('string');
179+
expect(new Date()).toBeInstanceOf(Date);
180+
expect(NaN).toBeNaN();
181+
expect('hello').toBeTruthy();
182+
expect('').toBeFalsy();
183+
184+
// Number Comparison
185+
expect(5).toBeGreaterThan(3);
186+
expect(5).toBeGreaterThanOrEqual(5);
187+
expect(3).toBeLessThan(5);
188+
expect(3).toBeLessThanOrEqual(3);
189+
expect(0.1 + 0.2).toBeCloseTo(0.3, 5);
190+
191+
// Array / Object / String
192+
expect([1, 2, 3]).toContain(2);
193+
expect([{ a: 1 }]).toContainEqual({ a: 1 });
194+
expect('hello world').toMatch(/world/);
195+
expect({ a: 1, b: 2 }).toMatchObject({ a: 1 });
196+
expect('abc').toHaveLength(3);
197+
expect({ foo: { bar: 1 } }).toHaveProperty('foo.bar', 1);
198+
199+
// Function / Exception
200+
expect(() => {
201+
throw new Error('fail');
202+
}).toThrowError('fail');
203+
expect(3).toSatisfy((x) => x % 3 === 0 || x % 3 === 1);
204+
```
205+
206+
### Mock matchers
207+
208+
Mock matchers are used to assert how mock functions (created by `rstest.fn` or `rstest.spyOn`) are called, what they return, and their call order. They are essential for verifying function interactions in unit tests.
209+
210+
- `toHaveBeenCalled()`. Checks if a mock function was called at least once.
211+
- `toHaveBeenCalledTimes(times)`. Checks if a mock function was called a specific number of times.
212+
- `toHaveBeenCalledWith(...args)`. Checks if a mock function was called with specific arguments.
213+
- `toHaveBeenCalledBefore(mock)`. Checks if a mock was called before another mock.
214+
- `toHaveBeenCalledAfter(mock)`. Checks if a mock was called after another mock.
215+
- `toHaveBeenCalledExactlyOnceWith(...args)`. Checks if a mock was called exactly once with specific arguments.
216+
- `toHaveBeenLastCalledWith(...args)`. Checks if a mock was last called with specific arguments.
217+
- `toHaveBeenNthCalledWith(n, ...args)`. Checks if a mock was called with specific arguments on the nth call.
218+
- `toHaveReturned()`. Checks if a mock function returned at least once.
219+
- `toHaveReturnedTimes(times)`. Checks if a mock function returned a specific number of times.
220+
- `toHaveReturnedWith(value)`. Checks if a mock function returned a specific value.
221+
- `toHaveLastReturnedWith(value)`. Checks if a mock function last returned a specific value.
222+
- `toHaveNthReturnedWith(n, value)`. Checks if a mock function returned a specific value on the nth call.
223+
- `toHaveResolved()`. Checks if a promise resolved at least once.
224+
- `toHaveResolvedTimes(times)`. Checks if a promise resolved a specific number of times.
225+
- `toHaveResolvedWith(value)`. Checks if a promise resolved with a specific value.
226+
- `toHaveLastResolvedWith(value)`. Checks if a promise last resolved with a specific value.
227+
- `toHaveNthResolvedWith(n, value)`. Checks if a promise resolved with a specific value on the nth call.
228+
229+
```ts
230+
const mockFn = rstest.fn((x) => x + 1);
231+
mockFn(1);
232+
233+
expect(mockFn).toHaveBeenCalled();
234+
expect(mockFn).toHaveBeenCalledTimes(1);
235+
expect(mockFn).toHaveBeenCalledWith(1);
236+
```
237+
238+
### Snapshot matchers
239+
240+
Snapshot matchers are used to compare values, errors, or files against previously recorded snapshots, making it easy to track changes in output over time.
241+
242+
- `toMatchSnapshot()`. Compares the value to a saved snapshot.
243+
- `toMatchInlineSnapshot()`. Compares the value to an inline snapshot in the test file.
244+
- `toThrowErrorMatchingSnapshot()`. Checks if a thrown error matches a saved snapshot.
245+
- `toThrowErrorMatchingInlineSnapshot()`. Checks if a thrown error matches an inline snapshot in the test file.
246+
- `toMatchFileSnapshot(filepath)`. Compares the value to a snapshot saved in a specific file.
247+
248+
```ts
249+
expect('hello world').toMatchSnapshot();
250+
251+
expect(() => {
252+
throw new Error('fail');
253+
}).toThrowErrorMatchingSnapshot();
254+
```
255+
256+
### Promise matchers
257+
258+
- `resolves`. Asserts on the resolved value of a Promise.
259+
- `rejects`. Asserts on the rejected value of a Promise.
260+
261+
```ts
262+
await expect(Promise.resolve('ok')).resolves.toBe('ok');
263+
await expect(Promise.reject(new Error('fail'))).rejects.toThrow('fail');
264+
```
265+
266+
### Asymmetric matchers
267+
268+
Asymmetric matchers are helpers that allow for flexible matching of values, such as partial matches, type matches, or pattern matches. They are useful for writing more expressive and less brittle tests.
269+
270+
- `expect.anything()`. Matches any value except null or undefined.
271+
- `expect.any(constructor)`. Matches any value of the given type.
272+
- `expect.closeTo(number, precision?)`. Matches a number close to the expected value.
273+
- `expect.arrayContaining(array)`. Matches an array containing the expected elements.
274+
- `expect.objectContaining(object)`. Matches an object containing the expected properties.
275+
- `expect.stringContaining(string)`. Matches a string containing the expected substring.
276+
- `expect.stringMatching(stringOrRegExp)`. Matches a string matching the expected pattern.
277+
278+
```ts
279+
expect({ a: 1 }).toEqual({ a: expect.anything() });
280+
281+
expect(1).toEqual(expect.any(Number));
282+
283+
expect(0.1 + 0.2).toEqual(expect.closeTo(0.3, 5));
284+
285+
expect([1, 2, 3]).toEqual(expect.arrayContaining([2, 1]));
286+
287+
expect({ a: 1, b: 2 }).toEqual(expect.objectContaining({ a: 1 }));
288+
289+
expect('hello world').toEqual(expect.stringContaining('world'));
290+
291+
expect('hello world').toEqual(expect.stringMatching(/^hello/));
292+
```
293+
294+
### Custom matchers
295+
296+
You can extend expect with custom matchers:
297+
298+
```ts
299+
expect.extend({
300+
toBeDivisibleBy(received, argument) {
301+
const pass = received % argument === 0;
302+
if (pass) {
303+
return {
304+
message: () =>
305+
`expected ${received} not to be divisible by ${argument}`,
306+
pass: true,
307+
};
308+
} else {
309+
return {
310+
message: () => `expected ${received} to be divisible by ${argument}`,
311+
pass: false,
312+
};
313+
}
314+
},
315+
});
316+
317+
expect(10).toBeDivisibleBy(2);
318+
```

website/docs/zh/api/rstest/mockFunctions.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,8 @@ expect(spy).toHaveBeenCalled();
8080
- **类型:** `() => Rstest`
8181

8282
重置所有 mock,并恢复被 mock 的对象的原始描述符。
83+
84+
## 更多
85+
86+
- [Mock 匹配器](../test-api/expect#mock-matchers)
87+
- [MockInstance API](./mockInstance)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
["test", "describe", "hooks"]
1+
["expect", "test", "describe", "hooks"]

0 commit comments

Comments
 (0)