Tests: improve diffing for values of different types

Close gh-5454

Co-authored-by: Richard Gibson <richard.gibson@gmail.com>
This commit is contained in:
Timmy Willison 2024-03-27 10:36:35 -04:00 committed by GitHub
parent 063831b637
commit b9d333acef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 58 additions and 26 deletions

View File

@ -53,6 +53,17 @@
return nu; return nu;
} }
} }
// Serialize Symbols as string representations so they are
// sent over the wire after being stringified.
if ( typeof value === "symbol" ) {
// We can *describe* unique symbols, but note that their identity
// (e.g., `Symbol() !== Symbol()`) is lost
var ctor = Symbol.keyFor( value ) !== undefined ? "Symbol.for" : "Symbol";
return ctor + "(" + JSON.stringify( value.description ) + ")";
}
return value; return value;
} }
return derez( object ); return derez( object );

View File

@ -3,6 +3,18 @@ import { getBrowserString } from "./lib/getBrowserString.js";
import { prettyMs } from "./lib/prettyMs.js"; import { prettyMs } from "./lib/prettyMs.js";
import * as Diff from "diff"; import * as Diff from "diff";
function serializeForDiff( value ) {
// Use naive serialization for everything except types with confusable values
if ( typeof value === "string" ) {
return JSON.stringify( value );
}
if ( typeof value === "bigint" ) {
return `${ value }n`;
}
return `${ value }`;
}
export function reportTest( test, reportId, { browser, headless } ) { export function reportTest( test, reportId, { browser, headless } ) {
if ( test.status === "passed" ) { if ( test.status === "passed" ) {
@ -25,15 +37,19 @@ export function reportTest( test, reportId, { browser, headless } ) {
message += `\n${ error.message }`; message += `\n${ error.message }`;
} }
message += `\n${ chalk.gray( error.stack ) }`; message += `\n${ chalk.gray( error.stack ) }`;
if ( "expected" in error && "actual" in error ) {
message += `\nexpected: ${ JSON.stringify( error.expected ) }`; // Show expected and actual values
message += `\nactual: ${ JSON.stringify( error.actual ) }`; // if either is defined and non-null.
// error.actual is set to null for failed
// assert.expect() assertions, so skip those as well.
// This should be fine because error.expected would
// have to also be null for this to be skipped.
if ( error.expected != null || error.actual != null ) {
message += `\nexpected: ${ chalk.red( JSON.stringify( error.expected ) ) }`;
message += `\nactual: ${ chalk.green( JSON.stringify( error.actual ) ) }`;
let diff; let diff;
if ( if ( Array.isArray( error.expected ) && Array.isArray( error.actual ) ) {
Array.isArray( error.expected ) &&
Array.isArray( error.actual )
) {
// Diff arrays // Diff arrays
diff = Diff.diffArrays( error.expected, error.actual ); diff = Diff.diffArrays( error.expected, error.actual );
@ -46,7 +62,7 @@ export function reportTest( test, reportId, { browser, headless } ) {
diff = Diff.diffJson( error.expected, error.actual ); diff = Diff.diffJson( error.expected, error.actual );
} else if ( } else if (
typeof error.expected === "number" && typeof error.expected === "number" &&
typeof error.expected === "number" typeof error.actual === "number"
) { ) {
// Diff numbers directly // Diff numbers directly
@ -57,30 +73,35 @@ export function reportTest( test, reportId, { browser, headless } ) {
diff = [ { removed: true, value: `${ value }` } ]; diff = [ { removed: true, value: `${ value }` } ];
} }
} else if ( } else if (
typeof error.expected === "boolean" && typeof error.expected === "string" &&
typeof error.actual === "boolean" typeof error.actual === "string"
) { ) {
// Show the actual boolean in red // Diff the characters of strings
diff = [ { removed: true, value: `${ error.actual }` } ]; diff = Diff.diffChars( error.expected, error.actual );
} else { } else {
// Diff everything else as characters // Diff everything else as words
diff = Diff.diffChars( `${ error.expected }`, `${ error.actual }` ); diff = Diff.diffWords(
serializeForDiff( error.expected ),
serializeForDiff( error.actual )
);
} }
message += "\n"; if ( diff ) {
message += diff message += "\n";
.map( ( part ) => { message += diff
if ( part.added ) { .map( ( part ) => {
return chalk.green( part.value ); if ( part.added ) {
} return chalk.green( part.value );
if ( part.removed ) { }
return chalk.red( part.value ); if ( part.removed ) {
} return chalk.red( part.value );
return chalk.gray( part.value ); }
} ) return chalk.gray( part.value );
.join( "" ); } )
.join( "" );
}
} }
} }
} }