From 09226eba90150ba9bae62517988cb1d57eb1b767 Mon Sep 17 00:00:00 2001 From: Aaron Brady Date: Thu, 19 Oct 2017 17:12:22 -0700 Subject: [PATCH] have Base generate the strings for error messages immediately instead of delaying until epilogue, the reason for this is that it is possible to reference objects in errors that could be mutated after the error occurs, causing the printed error message to be misleading --- lib/reporters/base.js | 19 +++++++++++-------- test/reporters/list.spec.js | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/lib/reporters/base.js b/lib/reporters/base.js index 9243ec42e6..d8ee73358e 100644 --- a/lib/reporters/base.js +++ b/lib/reporters/base.js @@ -155,6 +155,10 @@ exports.cursor = { } }; +function showDiff(err) { + return err && err.showDiff !== false && sameType(err.actual, err.expected) && err.expected !== undefined; +} + /** * Output the given `failures` as a list. * @@ -183,8 +187,6 @@ exports.list = function (failures) { } var stack = err.stack || message; var index = message ? stack.indexOf(message) : -1; - var actual = err.actual; - var expected = err.expected; var escape = true; if (index === -1) { @@ -201,13 +203,8 @@ exports.list = function (failures) { msg = 'Uncaught ' + msg; } // explicitly show diff - if (err.showDiff !== false && sameType(actual, expected) && expected !== undefined) { + if (showDiff(err)) { escape = false; - if (!(utils.isString(actual) && utils.isString(expected))) { - err.actual = actual = utils.stringify(actual); - err.expected = expected = utils.stringify(expected); - } - fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n'); var match = message.match(/^([^:]+): expected/); msg = '\n ' + color('error message', match ? match[1] : msg); @@ -292,6 +289,12 @@ function Base (runner) { runner.on('fail', function (test, err) { stats.failures = stats.failures || 0; stats.failures++; + if (showDiff(err)) { + if (!utils.isString(err.actual) || !utils.isString(err.expected)) { + err.actual = utils.stringify(err.actual); + err.expected = utils.stringify(err.expected); + } + } test.err = err; failures.push(test); }); diff --git a/test/reporters/list.spec.js b/test/reporters/list.spec.js index 4b3704204d..d83d4e48cc 100644 --- a/test/reporters/list.spec.js +++ b/test/reporters/list.spec.js @@ -192,6 +192,28 @@ describe('List reporter', function () { Base.cursor = cachedCursor; }); + it('should immediately construct fail strings', function() { + var actual = { a: 'actual' }; + var expected = { a: 'expected' }; + var test = {}; + var checked = false; + var err; + runner.on = function (event, callback) { + if (!checked && event === 'fail') { + err = new Error('fake failure object with actual/expected'); + err.actual = actual; + err.expected = expected; + err.showDiff = true; + callback(test, err); + checked = true; + } + }; + List.call({epilogue: function () {}}, runner); + + process.stdout.write = stdoutWrite; + expect(typeof err.actual).to.equal('string'); + expect(typeof err.expected).to.equal('string'); + }); }); describe('on end', function () {