diff --git a/package-lock.json b/package-lock.json index 1c82a11ca..b72130d42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "commitplease": "3.2.0", "concurrently": "8.2.2", "core-js-bundle": "3.36.0", + "diff": "5.2.0", "eslint": "8.57.0", "eslint-config-jquery": "3.0.2", "exit-hook": "4.0.0", @@ -828,6 +829,15 @@ "node": ">= 14" } }, + "node_modules/@prantlf/jsonlint/node_modules/diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/@sinonjs/commons": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", @@ -1795,9 +1805,9 @@ } }, "node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, "engines": { "node": ">=0.3.1" diff --git a/package.json b/package.json index 5848043e0..7a4b16d54 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "commitplease": "3.2.0", "concurrently": "8.2.2", "core-js-bundle": "3.36.0", + "diff": "5.2.0", "eslint": "8.57.0", "eslint-config-jquery": "3.0.2", "exit-hook": "4.0.0", diff --git a/test/runner/reporter.js b/test/runner/reporter.js index 74417f2fb..519d74709 100644 --- a/test/runner/reporter.js +++ b/test/runner/reporter.js @@ -1,6 +1,7 @@ import chalk from "chalk"; import { getBrowserString } from "./lib/getBrowserString.js"; import { prettyMs } from "./lib/prettyMs.js"; +import * as Diff from "diff"; export function reportTest( test, reportId, { browser, headless } ) { if ( test.status === "passed" ) { @@ -24,12 +25,58 @@ export function reportTest( test, reportId, { browser, headless } ) { message += `\n${ chalk.gray( error.stack ) }`; if ( error.expected && error.actual ) { message += `\nexpected: ${ JSON.stringify( error.expected ) }`; - message += `\nactual: ${ chalk.red( JSON.stringify( error.actual ) ) }`; + message += `\nactual: ${ JSON.stringify( error.actual ) }`; + let diff; + + if ( + Array.isArray( error.expected ) && + Array.isArray( error.actual ) + ) { + + // Diff arrays + diff = Diff.diffArrays( error.expected, error.actual ); + } else if ( + typeof error.expected === "object" && + typeof error.actual === "object" + ) { + + // Diff objects + diff = Diff.diffJson( error.expected, error.actual ); + } else if ( + typeof error.expected === "number" && + typeof error.expected === "number" + ) { + + // Diff numbers directly + const value = error.actual - error.expected; + if ( value > 0 ) { + diff = [ { added: true, value: `+${ value }` } ]; + } else { + diff = [ { removed: true, value: `${ value }` } ]; + } + } else { + + // Diff everything else as characters + diff = Diff.diffChars( `${ error.expected }`, `${ error.actual }` ); + } + + message += "\n"; + message += diff + .map( ( part ) => { + if ( part.added ) { + return chalk.green( part.value ); + } + if ( part.removed ) { + return chalk.red( part.value ); + } + return chalk.gray( part.value ); + } ) + .join( "" ); } } } - console.log( "\n\n" + message ); + console.log( `\n\n${ message }` ); // Only return failed messages if ( test.status === "failed" ) {