@@ -19,6 +19,13 @@ let green = '';
19
19
let red = '' ;
20
20
let white = '' ;
21
21
22
+ const READABLE_OPERATOR = {
23
+ deepStrictEqual : 'Input A expected to strictly deep-equal input B' ,
24
+ notDeepStrictEqual : 'Input A expected to strictly not deep-equal input B' ,
25
+ strictEqual : 'Input A expected to strictly equal input B' ,
26
+ notStrictEqual : 'Input A expected to strictly not equal input B'
27
+ } ;
28
+
22
29
const {
23
30
errmap,
24
31
UV_EAI_MEMORY ,
@@ -40,10 +47,34 @@ function lazyInternalUtil() {
40
47
return internalUtil ;
41
48
}
42
49
50
+ function copyError ( source ) {
51
+ const keys = Object . keys ( source ) ;
52
+ const target = Object . create ( Object . getPrototypeOf ( source ) ) ;
53
+ for ( const key of keys ) {
54
+ target [ key ] = source [ key ] ;
55
+ }
56
+ Object . defineProperty ( target , 'message' , { value : source . message } ) ;
57
+ return target ;
58
+ }
59
+
43
60
function inspectValue ( val ) {
61
+ // The util.inspect default values could be changed. This makes sure the
62
+ // error messages contain the necessary information nevertheless.
44
63
return util . inspect (
45
64
val ,
46
- { compact : false , customInspect : false }
65
+ {
66
+ compact : false ,
67
+ customInspect : false ,
68
+ depth : 1000 ,
69
+ maxArrayLength : Infinity ,
70
+ // Assert compares only enumerable properties (with a few exceptions).
71
+ showHidden : false ,
72
+ // Having a long line as error is better than wrapping the line for
73
+ // comparison.
74
+ breakLength : Infinity ,
75
+ // Assert does not detect proxies currently.
76
+ showProxy : false
77
+ }
47
78
) . split ( '\n' ) ;
48
79
}
49
80
@@ -226,8 +257,8 @@ function createErrDiff(actual, expected, operator) {
226
257
if ( util === undefined ) util = require ( 'util' ) ;
227
258
const actualLines = inspectValue ( actual ) ;
228
259
const expectedLines = inspectValue ( expected ) ;
229
- const msg = `Input A expected to ${ operator } input B:\n` +
230
- `${ green } + expected${ white } ${ red } - actual${ white } ` ;
260
+ const msg = READABLE_OPERATOR [ operator ] +
261
+ `:\n ${ green } + expected${ white } ${ red } - actual${ white } ` ;
231
262
const skippedMsg = ' ... Lines skipped' ;
232
263
233
264
// Remove all ending lines that match (this optimizes the output for
@@ -259,6 +290,7 @@ function createErrDiff(actual, expected, operator) {
259
290
260
291
const maxLines = Math . max ( actualLines . length , expectedLines . length ) ;
261
292
var printedLines = 0 ;
293
+ var identical = 0 ;
262
294
for ( i = 0 ; i < maxLines ; i ++ ) {
263
295
// Only extra expected lines exist
264
296
const cur = i - lastPos ;
@@ -318,12 +350,38 @@ function createErrDiff(actual, expected, operator) {
318
350
res += `\n ${ actualLines [ i ] } ` ;
319
351
printedLines ++ ;
320
352
}
353
+ identical ++ ;
321
354
}
322
355
// Inspected object to big (Show ~20 rows max)
323
356
if ( printedLines > 20 && i < maxLines - 2 ) {
324
357
return `${ msg } ${ skippedMsg } \n${ res } \n...${ other } \n...` ;
325
358
}
326
359
}
360
+
361
+ // Strict equal with identical objects that are not identical by reference.
362
+ if ( identical === maxLines ) {
363
+ let base = 'Input object identical but not reference equal:' ;
364
+
365
+ if ( operator !== 'strictEqual' ) {
366
+ // This code path should not be possible to reach.
367
+ // The output is identical but it is not clear why.
368
+ base = 'Input objects not identical:' ;
369
+ }
370
+
371
+ // We have to get the result again. The lines were all removed before.
372
+ const actualLines = inspectValue ( actual ) ;
373
+
374
+ // Only remove lines in case it makes sense to collapse those.
375
+ // TODO: Accept env to always show the full error.
376
+ if ( actualLines . length > 30 ) {
377
+ actualLines [ 26 ] = '...' ;
378
+ while ( actualLines . length > 27 ) {
379
+ actualLines . pop ( ) ;
380
+ }
381
+ }
382
+
383
+ return `${ base } \n\n ${ actualLines . join ( '\n ' ) } \n` ;
384
+ }
327
385
return `${ msg } ${ skipped ? skippedMsg : '' } \n${ res } ${ other } ${ end } ` ;
328
386
}
329
387
@@ -358,13 +416,15 @@ class AssertionError extends Error {
358
416
}
359
417
}
360
418
if ( util === undefined ) util = require ( 'util' ) ;
419
+ // Prevent the error stack from being visible by duplicating the error
420
+ // in a very close way to the original in case both sides are actually
421
+ // instances of Error.
361
422
if ( typeof actual === 'object' && actual !== null &&
362
- 'stack' in actual && actual instanceof Error ) {
363
- actual = `${ actual . name } : ${ actual . message } ` ;
364
- }
365
- if ( typeof expected === 'object' && expected !== null &&
366
- 'stack' in expected && expected instanceof Error ) {
367
- expected = `${ expected . name } : ${ expected . message } ` ;
423
+ typeof expected === 'object' && expected !== null &&
424
+ 'stack' in actual && actual instanceof Error &&
425
+ 'stack' in expected && expected instanceof Error ) {
426
+ actual = copyError ( actual ) ;
427
+ expected = copyError ( expected ) ;
368
428
}
369
429
370
430
if ( errorDiff === 0 ) {
@@ -379,15 +439,23 @@ class AssertionError extends Error {
379
439
// In case the objects are equal but the operator requires unequal, show
380
440
// the first object and say A equals B
381
441
const res = inspectValue ( actual ) ;
442
+ const base = `Identical input passed to ${ operator } :` ;
382
443
383
- if ( res . length > 20 ) {
384
- res [ 19 ] = '...' ;
385
- while ( res . length > 20 ) {
444
+ // Only remove lines in case it makes sense to collapse those.
445
+ // TODO: Accept env to always show the full error.
446
+ if ( res . length > 30 ) {
447
+ res [ 26 ] = '...' ;
448
+ while ( res . length > 27 ) {
386
449
res . pop ( ) ;
387
450
}
388
451
}
389
- // Only print a single object.
390
- super ( `Identical input passed to ${ operator } :\n${ res . join ( '\n' ) } ` ) ;
452
+
453
+ // Only print a single input.
454
+ if ( res . length === 1 ) {
455
+ super ( `${ base } ${ res [ 0 ] } ` ) ;
456
+ } else {
457
+ super ( `${ base } \n\n ${ res . join ( '\n ' ) } \n` ) ;
458
+ }
391
459
} else {
392
460
super ( createErrDiff ( actual , expected , operator ) ) ;
393
461
}
0 commit comments