Skip to content

Commit 9abef3d

Browse files
authored
test: add error equality tests + more warnings in docs (#5253)
1 parent de8cf2d commit 9abef3d

File tree

2 files changed

+122
-2
lines changed

2 files changed

+122
-2
lines changed

docs/api/expect.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ test('stocks are not the same', () => {
388388
```
389389

390390
:::warning
391-
A _deep equality_ will not be performed for `Error` objects. To test if something was thrown, use [`toThrowError`](#tothrowerror) assertion.
391+
A _deep equality_ will not be performed for `Error` objects. Only the `message` property of an Error is considered for equality. To customize equality to check properties other than `message`, use [`expect.addEqualityTesters`](#expect-addequalitytesters). To test if something was thrown, use [`toThrowError`](#tothrowerror) assertion.
392392
:::
393393

394394
## toStrictEqual

test/core/test/expect.test.ts

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import nodeAssert from 'node:assert'
12
import type { Tester } from '@vitest/expect'
23
import { getCurrentTest } from '@vitest/runner'
3-
import { describe, expect, expectTypeOf, test, vi } from 'vitest'
4+
import { assert, describe, expect, expectTypeOf, test, vi } from 'vitest'
45

56
describe('expect.soft', () => {
67
test('types', () => {
@@ -271,3 +272,122 @@ describe('recursive custom equality tester', () => {
271272
expect(mockFn).toHaveNthReturnedWith(1, [person1, person2])
272273
})
273274
})
275+
276+
describe('Error equality', () => {
277+
class MyError extends Error {
278+
constructor(message: string, public custom: string) {
279+
super(message)
280+
}
281+
}
282+
283+
class YourError extends Error {
284+
constructor(message: string, public custom: string) {
285+
super(message)
286+
}
287+
}
288+
289+
test('basic', () => {
290+
//
291+
// default behavior
292+
//
293+
294+
{
295+
// different custom property
296+
const e1 = new MyError('hi', 'a')
297+
const e2 = new MyError('hi', 'b')
298+
expect(e1).toEqual(e2)
299+
expect(e1).toStrictEqual(e2)
300+
assert.deepEqual(e1, e2)
301+
nodeAssert.notDeepStrictEqual(e1, e2)
302+
}
303+
304+
{
305+
// different message
306+
const e1 = new MyError('hi', 'a')
307+
const e2 = new MyError('hello', 'a')
308+
expect(e1).not.toEqual(e2)
309+
expect(e1).not.toStrictEqual(e2)
310+
assert.notDeepEqual(e1, e2)
311+
nodeAssert.notDeepStrictEqual(e1, e2)
312+
}
313+
314+
{
315+
// different class
316+
const e1 = new MyError('hello', 'a')
317+
const e2 = new YourError('hello', 'a')
318+
expect(e1).toEqual(e2)
319+
expect(e1).not.toStrictEqual(e2) // toStrictEqual checks constructor already
320+
assert.deepEqual(e1, e2)
321+
nodeAssert.notDeepStrictEqual(e1, e2)
322+
}
323+
324+
{
325+
// same
326+
const e1 = new MyError('hi', 'a')
327+
const e2 = new MyError('hi', 'a')
328+
expect(e1).toEqual(e2)
329+
expect(e1).toStrictEqual(e2)
330+
assert.deepEqual(e1, e2)
331+
nodeAssert.deepStrictEqual(e1, e2)
332+
}
333+
334+
//
335+
// stricter behavior with custom equality tester
336+
//
337+
338+
expect.addEqualityTesters(
339+
[
340+
function tester(a, b, customTesters) {
341+
const aOk = a instanceof Error
342+
const bOk = b instanceof Error
343+
if (aOk && bOk) {
344+
// cf. assert.deepStrictEqual https://nodejs.org/api/assert.html#comparison-details_1
345+
// > [[Prototype]] of objects are compared using the === operator.
346+
// > Only enumerable "own" properties are considered.
347+
// > Error names and messages are always compared, even if these are not enumerable properties.
348+
return (
349+
Object.getPrototypeOf(a) === Object.getPrototypeOf(b)
350+
&& a.name === b.name
351+
&& a.message === b.message
352+
&& this.equals({ ...a }, { ...b }, customTesters)
353+
)
354+
}
355+
return aOk !== bOk ? false : undefined
356+
},
357+
],
358+
)
359+
360+
{
361+
// different custom property
362+
const e1 = new MyError('hi', 'a')
363+
const e2 = new MyError('hi', 'b')
364+
expect(e1).not.toEqual(e2) // changed
365+
expect(e1).not.toStrictEqual(e2) // changed
366+
assert.deepEqual(e1, e2) // chai assert is still same
367+
}
368+
369+
{
370+
// different message
371+
const e1 = new MyError('hi', 'a')
372+
const e2 = new MyError('hello', 'a')
373+
expect(e1).not.toEqual(e2)
374+
expect(e1).not.toStrictEqual(e2)
375+
}
376+
377+
{
378+
// different class
379+
const e1 = new MyError('hello', 'a')
380+
const e2 = new YourError('hello', 'a')
381+
expect(e1).not.toEqual(e2) // changed
382+
expect(e1).not.toStrictEqual(e2)
383+
}
384+
385+
{
386+
// same
387+
const e1 = new MyError('hi', 'a')
388+
const e2 = new MyError('hi', 'a')
389+
expect(e1).toEqual(e2)
390+
expect(e1).toStrictEqual(e2)
391+
}
392+
})
393+
})

0 commit comments

Comments
 (0)