-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
Expand file tree
/
Copy pathtest-assert-deep-prototype-diff.js
More file actions
115 lines (107 loc) Β· 4.29 KB
/
test-assert-deep-prototype-diff.js
File metadata and controls
115 lines (107 loc) Β· 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
'use strict';
require('../common');
const assert = require('assert');
const { test } = require('node:test');
// Disable colored output to prevent color codes from breaking assertion
// message comparisons. This should only be an issue when process.stdout
// is a TTY.
if (process.stdout.isTTY) {
process.env.NODE_DISABLE_COLORS = '1';
}
// Regression tests for https://github.com/nodejs/node/issues/50397.
//
// When `assert.deepStrictEqual` fails solely because the two values have
// different prototypes, the diff used to render as `{} !== {}` (or similar),
// giving the user no clue about why the assertion failed. The assertion
// error formatter now surfaces the prototype mismatch explicitly.
test('deepStrictEqual surfaces anonymous-class prototype mismatch', () => {
const A = (() => class {})();
const B = (() => class {})();
assert.throws(
() => assert.deepStrictEqual(new A(), new B()),
(err) => {
assert.strictEqual(err.code, 'ERR_ASSERTION');
assert.match(err.message, /Object prototypes differ:/);
// The previous "Values have same structure but are not reference-equal"
// message must no longer be used for prototype-only mismatches because
// it is misleading: the values do not even have the same prototype.
assert.doesNotMatch(err.message, /same structure but are not reference-equal/);
return true;
}
);
});
test('deepStrictEqual surfaces named-class prototype mismatch', () => {
class Foo {}
class Bar {}
assert.throws(
() => assert.deepStrictEqual(new Foo(), new Bar()),
(err) => {
assert.strictEqual(err.code, 'ERR_ASSERTION');
// Both class names should appear somewhere in the rendered message:
// either in the existing inspect-based diff (`+ Foo {}` / `- Bar {}`)
// or in the new "Object prototypes differ:" line. The important
// guarantee is that the user can identify both prototypes from the
// error message alone.
assert.match(err.message, /Foo/);
assert.match(err.message, /Bar/);
return true;
}
);
});
test('deepStrictEqual surfaces null-prototype mismatch', () => {
const a = { __proto__: null };
const b = {};
assert.throws(
() => assert.deepStrictEqual(a, b),
(err) => {
assert.strictEqual(err.code, 'ERR_ASSERTION');
assert.match(err.message, /null prototype/);
return true;
}
);
});
test('deepStrictEqual prototype-mismatch message is helpful for empty objects', () => {
// This is the most pathological case: both sides inspect identically as
// `{}`, so without the prototype-mismatch information the diff body alone
// is useless. The fix must produce an explanatory line.
const A = (() => class {})();
const B = (() => class {})();
let captured;
try {
assert.deepStrictEqual(new A(), new B());
} catch (err) {
captured = err;
}
assert.ok(captured, 'deepStrictEqual should have thrown');
assert.match(captured.message, /Object prototypes differ:/);
});
test('strictEqual on structurally-equal arrays still uses notIdentical message', () => {
// Sanity check that the new code path does not regress the existing
// behavior of `strictEqual([], [])`. That comparison continues to use
// the "Values have same structure but are not reference-equal" message
// because the prototypes do match (both are Array.prototype).
assert.throws(
() => assert.strictEqual([], []),
{
code: 'ERR_ASSERTION',
message: 'Values have same structure but are not reference-equal:\n\n[]\n',
}
);
});
test('deepStrictEqual on structurally-equal values with same prototype still fails clearly', () => {
// When the prototypes match but the values are not reference-equal, the
// existing notIdentical fallback should still apply (deepStrictEqual on
// two equal-shape objects with the same prototype should normally pass;
// here we use objects whose enumerable properties differ to exercise the
// ordinary diff path and confirm it is unaffected).
assert.throws(
() => assert.deepStrictEqual({ a: 1 }, { a: 2 }),
(err) => {
assert.strictEqual(err.code, 'ERR_ASSERTION');
// The ordinary diff path must NOT mention prototype differences
// because the prototypes are identical.
assert.doesNotMatch(err.message, /Object prototypes differ:/);
return true;
}
);
});