From 35b064add72f467ebe6ebcd8d371e06cf1829850 Mon Sep 17 00:00:00 2001 From: Ben Kucera <14625260+Bkucera@users.noreply.github.com> Date: Mon, 14 Sep 2020 13:23:42 -0400 Subject: [PATCH] fix(driver): ensure errors dont get serialized w/ actual/expected when no showDiff (#8527) Co-authored-by: Chris Breiding --- packages/driver/src/cypress.js | 16 - packages/driver/src/cypress/error_utils.js | 35 +- .../__snapshots__/retries.mochaEvents.spec.js | 740 ++++++++++++++++-- .../__snapshots__/runner.mochaEvents.spec.js | 140 +++- .../integration/reporter.errors.spec.js | 5 +- .../integration/retries.mochaEvents.spec.js | 16 +- packages/runner/cypress/support/helpers.js | 6 +- .../test/support/helpers/resultsUtils.ts | 85 +- 8 files changed, 875 insertions(+), 168 deletions(-) diff --git a/packages/driver/src/cypress.js b/packages/driver/src/cypress.js index a9661fe8ca..1f653d0270 100644 --- a/packages/driver/src/cypress.js +++ b/packages/driver/src/cypress.js @@ -1,6 +1,5 @@ const _ = require('lodash') const $ = require('jquery') -const chai = require('chai') const blobUtil = require('blob-util') const minimatch = require('minimatch') const moment = require('moment') @@ -347,21 +346,6 @@ class $Cypress { break case 'runner:fail': { - // mocha runner calculated a failure - const err = args[0].err - - if (err.type === 'existence' || $dom.isDom(err.actual) || $dom.isDom(err.expected)) { - err.showDiff = false - } - - if (err.actual) { - err.actual = chai.util.inspect(err.actual) - } - - if (err.expected) { - err.expected = chai.util.inspect(err.expected) - } - if (this.config('isTextTerminal')) { return this.emit('mocha', 'fail', ...args) } diff --git a/packages/driver/src/cypress/error_utils.js b/packages/driver/src/cypress/error_utils.js index 0c5c9414a2..b3f3c5549f 100644 --- a/packages/driver/src/cypress/error_utils.js +++ b/packages/driver/src/cypress/error_utils.js @@ -1,12 +1,15 @@ // See: ./errorScenarios.md for details about error messages and stack traces const _ = require('lodash') +const chai = require('chai') -const $errorMessages = require('./error_messages') +const $dom = require('../dom') const $utils = require('./utils') const $stackUtils = require('./stack_utils') +const $errorMessages = require('./error_messages') const ERROR_PROPS = 'message type name stack sourceMappedStack parsedStack fileName lineNumber columnNumber host uncaught actual expected showDiff isPending docsUrl codeFrame'.split(' ') +const ERR_PREPARED_FOR_SERIALIZATION = Symbol('ERR_PREPARED_FOR_SERIALIZATION') if (!Error.captureStackTrace) { Error.captureStackTrace = (err, fn) => { @@ -16,9 +19,39 @@ if (!Error.captureStackTrace) { } } +const prepareErrorForSerialization = (err) => { + if (err[ERR_PREPARED_FOR_SERIALIZATION]) { + return err + } + + if (err.type === 'existence' || $dom.isDom(err.actual) || $dom.isDom(err.expected)) { + err.showDiff = false + } + + if (err.showDiff === true) { + if (err.actual) { + err.actual = chai.util.inspect(err.actual) + } + + if (err.expected) { + err.expected = chai.util.inspect(err.expected) + } + } else { + delete err.actual + delete err.expected + delete err.showDiff + } + + err[ERR_PREPARED_FOR_SERIALIZATION] = true + + return err +} + const wrapErr = (err) => { if (!err) return + prepareErrorForSerialization(err) + return $utils.reduceProps(err, ERROR_PROPS) } diff --git a/packages/runner/__snapshots__/retries.mochaEvents.spec.js b/packages/runner/__snapshots__/retries.mochaEvents.spec.js index cff75b2f88..2fe10fb461 100644 --- a/packages/runner/__snapshots__/retries.mochaEvents.spec.js +++ b/packages/runner/__snapshots__/retries.mochaEvents.spec.js @@ -68,7 +68,13 @@ exports['src/cypress/runner retries mochaEvents simple retry #1'] = [ "id": "r3", "order": 1, "title": "test 1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", @@ -92,9 +98,7 @@ exports['src/cypress/runner retries mochaEvents simple retry #1'] = [ "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -104,7 +108,13 @@ exports['src/cypress/runner retries mochaEvents simple retry #1'] = [ "id": "r3", "order": 1, "title": "test 1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", @@ -410,7 +420,13 @@ exports['src/cypress/runner retries mochaEvents test retry with hooks #1'] = [ "id": "r3", "order": 1, "title": "test 1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", @@ -455,9 +471,7 @@ exports['src/cypress/runner retries mochaEvents test retry with hooks #1'] = [ "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -500,7 +514,13 @@ exports['src/cypress/runner retries mochaEvents test retry with hooks #1'] = [ "id": "r3", "order": 1, "title": "test 1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", @@ -991,7 +1011,13 @@ exports['src/cypress/runner retries mochaEvents test retry with [only] #1'] = [ "id": "r5", "order": 2, "title": "test 2", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", @@ -1036,9 +1062,7 @@ exports['src/cypress/runner retries mochaEvents test retry with [only] #1'] = [ "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -1081,7 +1105,13 @@ exports['src/cypress/runner retries mochaEvents test retry with [only] #1'] = [ "id": "r5", "order": 2, "title": "test 2", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", @@ -1643,7 +1673,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [beforeEach] #1'] "order": 1, "title": "test 1", "hookName": "before each", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h3", "body": "[body]", @@ -1694,9 +1730,7 @@ exports['src/cypress/runner retries mochaEvents can retry from [beforeEach] #1'] "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -1740,7 +1774,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [beforeEach] #1'] "order": 1, "title": "test 1", "hookName": "before each", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h3", "body": "[body]", @@ -2427,7 +2467,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "order": 1, "title": "test 1", "hookName": "after each", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h1", "body": "[body]", @@ -2483,9 +2529,7 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -2496,7 +2540,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -2514,7 +2564,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "order": 1, "title": "test 1", "hookName": "after each", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h1", "body": "[body]", @@ -2691,7 +2747,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -2709,7 +2771,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3005,7 +3073,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3023,7 +3097,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3325,7 +3405,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3343,7 +3429,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3637,7 +3729,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "order": 4, "title": "test 1", "hookName": "after each", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h7", "body": "[body]", @@ -3674,9 +3772,7 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -3687,7 +3783,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h7", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3705,7 +3807,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3723,7 +3831,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3741,7 +3855,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "order": 4, "title": "test 1", "hookName": "after each", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h7", "body": "[body]", @@ -3797,7 +3917,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h7", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3814,7 +3940,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "id": "r7", "title": "test 1", "hookName": "after each", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h7", "body": "[body]", @@ -3850,9 +3982,7 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -3863,7 +3993,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h7", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3881,7 +4017,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3899,7 +4041,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3916,7 +4064,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "id": "r7", "title": "test 1", "hookName": "after each", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h7", "body": "[body]", @@ -3971,7 +4125,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h7", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -3989,7 +4149,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h7", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -4007,7 +4173,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -4025,7 +4197,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -4207,7 +4385,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -4225,7 +4409,13 @@ exports['src/cypress/runner retries mochaEvents can retry from [afterEach] #1'] "title": "\"after each\" hook", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "body": "[body]", "type": "hook", "duration": "match.number", @@ -4440,7 +4630,13 @@ exports['src/cypress/runner retries mochaEvents cant retry from [before] #1'] = "title": "\"before all\" hook for \"test 1\"", "hookName": "before all", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "hook", @@ -4456,9 +4652,7 @@ exports['src/cypress/runner retries mochaEvents cant retry from [before] #1'] = "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -4514,7 +4708,13 @@ exports['src/cypress/runner retries mochaEvents cant retry from [before] #1'] = "order": 1, "title": "test 1", "hookName": "before all", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h1", "body": "[body]", @@ -4553,7 +4753,13 @@ exports['src/cypress/runner retries mochaEvents cant retry from [before] #1'] = "order": 1, "title": "test 1", "hookName": "before all", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h1", "body": "[body]", @@ -4904,7 +5110,13 @@ exports['src/cypress/runner retries mochaEvents cant retry from [after] #1'] = [ "title": "\"after all\" hook for \"test 1\"", "hookName": "after all", "hookId": "h4", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "hook", @@ -4920,9 +5132,7 @@ exports['src/cypress/runner retries mochaEvents cant retry from [after] #1'] = [ "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -4933,7 +5143,13 @@ exports['src/cypress/runner retries mochaEvents cant retry from [after] #1'] = [ "order": 1, "title": "test 1", "hookName": "after all", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h4", "body": "[body]", @@ -5012,7 +5228,13 @@ exports['src/cypress/runner retries mochaEvents cant retry from [after] #1'] = [ "order": 1, "title": "test 1", "hookName": "after all", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h4", "body": "[body]", @@ -5498,7 +5720,13 @@ exports['src/cypress/runner retries mochaEvents three tests with retry #1'] = [ "id": "r4", "order": 2, "title": "test 2", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", @@ -5536,9 +5764,7 @@ exports['src/cypress/runner retries mochaEvents three tests with retry #1'] = [ "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -5582,7 +5808,13 @@ exports['src/cypress/runner retries mochaEvents three tests with retry #1'] = [ "id": "r4", "order": 2, "title": "test 2", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", @@ -5671,7 +5903,13 @@ exports['src/cypress/runner retries mochaEvents three tests with retry #1'] = [ { "id": "r4", "title": "test 2", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", @@ -5708,9 +5946,7 @@ exports['src/cypress/runner retries mochaEvents three tests with retry #1'] = [ "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -5753,7 +5989,13 @@ exports['src/cypress/runner retries mochaEvents three tests with retry #1'] = [ { "id": "r4", "title": "test 2", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", @@ -6456,3 +6698,347 @@ exports['serialize state - retries'] = { "pending": 0, "numLogs": 0 } + +exports['src/cypress/runner retries mochaEvents cleanses errors before emitting does not try to serialize error with err.actual as DOM node #1'] = [ + [ + "mocha", + "start", + { + "start": "match.date" + } + ], + [ + "mocha", + "suite", + { + "id": "r1", + "title": "", + "root": true, + "type": "suite", + "file": "relative/path/to/spec.js", + "retries": -1 + } + ], + [ + "mocha", + "test", + { + "id": "r2", + "order": 1, + "title": "visits", + "body": "[body]", + "type": "test", + "file": null, + "invocationDetails": "{Object 8}", + "currentRetry": 0, + "retries": -1 + } + ], + [ + "mocha", + "test:before:run", + { + "id": "r2", + "order": 1, + "title": "visits", + "body": "[body]", + "type": "test", + "wallClockStartedAt": "match.date", + "file": null, + "invocationDetails": "{Object 8}", + "currentRetry": 0, + "retries": -1 + } + ], + [ + "mocha", + "retry", + { + "id": "r2", + "order": 1, + "title": "visits", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, + "state": "failed", + "body": "[body]", + "type": "test", + "duration": "match.number", + "wallClockStartedAt": "match.date", + "timings": { + "lifecycle": "match.number", + "test": { + "fnDuration": "match.number", + "afterFnDuration": "match.number" + } + }, + "file": null, + "invocationDetails": "{Object 8}", + "final": false, + "currentRetry": 0, + "retries": 2 + }, + { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + } + ], + [ + "mocha", + "test:after:run", + { + "id": "r2", + "order": 1, + "title": "visits", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, + "state": "failed", + "body": "[body]", + "type": "test", + "duration": "match.number", + "wallClockStartedAt": "match.date", + "wallClockDuration": "match.number", + "timings": { + "lifecycle": "match.number", + "test": { + "fnDuration": "match.number", + "afterFnDuration": "match.number" + } + }, + "file": null, + "invocationDetails": "{Object 8}", + "final": false, + "currentRetry": 0, + "retries": 2 + } + ], + [ + "mocha", + "test:before:run", + { + "id": "r2", + "title": "visits", + "body": "[body]", + "type": "test", + "wallClockStartedAt": "match.date", + "file": null, + "currentRetry": 1, + "retries": 2 + } + ], + [ + "mocha", + "retry", + { + "id": "r2", + "title": "visits", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, + "state": "failed", + "body": "[body]", + "type": "test", + "duration": "match.number", + "wallClockStartedAt": "match.date", + "timings": { + "lifecycle": "match.number", + "test": { + "fnDuration": "match.number", + "afterFnDuration": "match.number" + } + }, + "file": null, + "final": false, + "currentRetry": 1, + "retries": 2 + }, + { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + } + ], + [ + "mocha", + "test:after:run", + { + "id": "r2", + "title": "visits", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, + "state": "failed", + "body": "[body]", + "type": "test", + "duration": "match.number", + "wallClockStartedAt": "match.date", + "wallClockDuration": "match.number", + "timings": { + "lifecycle": "match.number", + "test": { + "fnDuration": "match.number", + "afterFnDuration": "match.number" + } + }, + "file": null, + "final": false, + "currentRetry": 1, + "retries": 2 + } + ], + [ + "mocha", + "test:before:run", + { + "id": "r2", + "title": "visits", + "body": "[body]", + "type": "test", + "wallClockStartedAt": "match.date", + "file": null, + "currentRetry": 2, + "retries": 2 + } + ], + [ + "mocha", + "fail", + { + "id": "r2", + "title": "visits", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, + "state": "failed", + "body": "[body]", + "type": "test", + "duration": "match.number", + "wallClockStartedAt": "match.date", + "timings": { + "lifecycle": "match.number", + "test": { + "fnDuration": "match.number", + "afterFnDuration": "match.number" + } + }, + "file": null, + "currentRetry": 2, + "retries": 2 + }, + { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + } + ], + [ + "mocha", + "test end", + { + "id": "r2", + "title": "visits", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, + "state": "failed", + "body": "[body]", + "type": "test", + "duration": "match.number", + "wallClockStartedAt": "match.date", + "timings": { + "lifecycle": "match.number", + "test": { + "fnDuration": "match.number", + "afterFnDuration": "match.number" + } + }, + "file": null, + "final": true, + "currentRetry": 2, + "retries": 2 + } + ], + [ + "mocha", + "test:after:run", + { + "id": "r2", + "title": "visits", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, + "state": "failed", + "body": "[body]", + "type": "test", + "duration": "match.number", + "wallClockStartedAt": "match.date", + "wallClockDuration": "match.number", + "timings": { + "lifecycle": "match.number", + "test": { + "fnDuration": "match.number", + "afterFnDuration": "match.number" + } + }, + "file": null, + "final": true, + "currentRetry": 2, + "retries": 2 + } + ], + [ + "mocha", + "suite end", + { + "id": "r1", + "title": "", + "root": true, + "type": "suite", + "file": "relative/path/to/spec.js", + "retries": -1 + } + ], + [ + "mocha", + "end", + { + "end": "match.date" + } + ] +] diff --git a/packages/runner/__snapshots__/runner.mochaEvents.spec.js b/packages/runner/__snapshots__/runner.mochaEvents.spec.js index b32f5dd5eb..e6f77c8b61 100644 --- a/packages/runner/__snapshots__/runner.mochaEvents.spec.js +++ b/packages/runner/__snapshots__/runner.mochaEvents.spec.js @@ -70,7 +70,13 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "title": "\"before all\" hook for \"test 1\"", "hookName": "before all", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "hook", @@ -86,9 +92,7 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -111,7 +115,13 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "order": 1, "title": "test 1", "hookName": "before all", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h1", "body": "[body]", @@ -143,7 +153,13 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "order": 1, "title": "test 1", "hookName": "before all", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h1", "body": "[body]", @@ -276,7 +292,13 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "title": "\"before each\" hook for \"test 1\"", "hookName": "before each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "hook", @@ -292,9 +314,7 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -305,7 +325,13 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "order": 1, "title": "test 1", "hookName": "before each", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h1", "body": "[body]", @@ -349,7 +375,13 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "order": 1, "title": "test 1", "hookName": "before each", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h1", "body": "[body]", @@ -482,7 +514,13 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "title": "\"after each\" hook for \"test 1\"", "hookName": "after each", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "hook", @@ -498,9 +536,7 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -511,7 +547,13 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "order": 1, "title": "test 1", "hookName": "after each", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h1", "body": "[body]", @@ -559,7 +601,13 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "order": 1, "title": "test 1", "hookName": "after each", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h1", "body": "[body]", @@ -806,7 +854,13 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "title": "\"after all\" hook for \"test 2\"", "hookName": "after all", "hookId": "h1", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "hook", @@ -822,9 +876,7 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -835,7 +887,13 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "order": 2, "title": "test 2", "hookName": "after all", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h1", "body": "[body]", @@ -883,7 +941,13 @@ exports['src/cypress/runner tests finish with correct state hook failures fail i "order": 2, "title": "test 2", "hookName": "after all", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "failedFromHookId": "h1", "body": "[body]", @@ -1105,7 +1169,13 @@ exports['src/cypress/runner tests finish with correct state mocha grep fail with "id": "r5", "order": 2, "title": "test 2", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", @@ -1156,9 +1226,7 @@ exports['src/cypress/runner tests finish with correct state mocha grep fail with "name": "AssertionError", "stack": "match.string", "sourceMappedStack": "match.string", - "parsedStack": "match.array", - "actual": null, - "showDiff": false + "parsedStack": "match.array" } ], [ @@ -1234,7 +1302,13 @@ exports['src/cypress/runner tests finish with correct state mocha grep fail with "id": "r5", "order": 2, "title": "test 2", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", @@ -1301,7 +1375,13 @@ exports['src/cypress/runner tests finish with correct state mocha grep fail with "id": "r5", "order": 2, "title": "test 2", - "err": "{Object 9}", + "err": { + "message": "[error message]", + "name": "AssertionError", + "stack": "match.string", + "sourceMappedStack": "match.string", + "parsedStack": "match.array" + }, "state": "failed", "body": "[body]", "type": "test", diff --git a/packages/runner/cypress/integration/reporter.errors.spec.js b/packages/runner/cypress/integration/reporter.errors.spec.js index 207c66aa9d..17d6205241 100644 --- a/packages/runner/cypress/integration/reporter.errors.spec.js +++ b/packages/runner/cypress/integration/reporter.errors.spec.js @@ -1,6 +1,9 @@ const helpers = require('../support/helpers') -const { verify } = helpers.createCypress({ config: { isTextTerminal: true, retries: 0 } }) +const { verify } = helpers.createCypress({ + config: { isTextTerminal: true, retries: 0 }, + visitUrl: 'http://localhost:3500/fixtures/isolated-runner-inner.html', +}) const verifyInternalFailure = (props) => { const { method } = props diff --git a/packages/runner/cypress/integration/retries.mochaEvents.spec.js b/packages/runner/cypress/integration/retries.mochaEvents.spec.js index 252185cc32..84f66fe10f 100644 --- a/packages/runner/cypress/integration/retries.mochaEvents.spec.js +++ b/packages/runner/cypress/integration/retries.mochaEvents.spec.js @@ -1,7 +1,7 @@ const helpers = require('../support/helpers') const { shouldHaveTestResults, getRunState, cleanseRunStateMap } = helpers -const { runIsolatedCypress, snapshotMochaEvents, getAutCypress } = helpers.createCypress({ config: { retries: 2, isTextTerminal: true } }) +const { runIsolatedCypress, snapshotMochaEvents, getAutCypress } = helpers.createCypress({ config: { retries: 2, isTextTerminal: true, firefoxGcInterval: null } }) const { sinon } = Cypress const match = Cypress.sinon.match @@ -249,6 +249,20 @@ describe('src/cypress/runner retries mochaEvents', () => { }) }) + // https://github.com/cypress-io/cypress/issues/8363 + describe('cleanses errors before emitting', () => { + it('does not try to serialize error with err.actual as DOM node', () => { + runIsolatedCypress(() => { + it('visits', () => { + cy.visit('/fixtures/dom.html') + cy.get('#button').should('not.be.visible') + }) + }, { config: { defaultCommandTimeout: 200 } }) + // should not have err.actual, expected properties since the subject is a DOM element + .then(snapshotMochaEvents) + }) + }) + describe('save/reload state', () => { const serializeState = () => { return getRunState(getAutCypress()) diff --git a/packages/runner/cypress/support/helpers.js b/packages/runner/cypress/support/helpers.js index 3519a9b195..db96c46b4f 100644 --- a/packages/runner/cypress/support/helpers.js +++ b/packages/runner/cypress/support/helpers.js @@ -16,7 +16,6 @@ const eventCleanseMap = { parent: stringifyShort, tests: stringifyShort, commands: stringifyShort, - err: stringifyShort, invocationDetails: stringifyShort, body: '[body]', wallClockStartedAt: match.date, @@ -102,10 +101,11 @@ function createCypress (defaultOptions = {}) { * @param {{state?: any, config?: any}} opts */ const runIsolatedCypress = (mochaTestsOrFile, opts = {}) => { - _.defaultsDeep(opts, defaultOptions, { + opts = _.defaultsDeep(opts, defaultOptions, { state: {}, config: { video: false }, onBeforeRun () {}, + visitUrl: 'http://localhost:3500/fixtures/dom.html', }) return cy.visit('/fixtures/isolated-runner.html#/tests/cypress/fixtures/empty_spec.js') @@ -256,7 +256,7 @@ function createCypress (defaultOptions = {}) { .yieldsAsync({ response: { isOkStatusCode: true, isHtml: true, - url: 'http://localhost:3500/fixtures/isolated-runner-inner.html', + url: opts.visitUrl, } }) .withArgs('set:runnables') diff --git a/packages/server/test/support/helpers/resultsUtils.ts b/packages/server/test/support/helpers/resultsUtils.ts index 212ecf33fe..a370c7f488 100644 --- a/packages/server/test/support/helpers/resultsUtils.ts +++ b/packages/server/test/support/helpers/resultsUtils.ts @@ -44,7 +44,7 @@ const normalizeTestTimings = function (obj, timings) { return } - return _.set(obj, 'timings', _.mapValues(t, (val, key) => { + _.set(obj, 'timings', _.mapValues(t, (val, key) => { switch (key) { case 'lifecycle': // ensure that lifecycle is under 500ms @@ -112,52 +112,59 @@ export const expectRunsToHaveCorrectTimings = (runs = []) => { } _.each(run.tests, (test) => { - if (test.displayError) { - test.displayError = e2e.normalizeStdout(test.displayError) - } - }) - - // now make sure that each tests wallclock duration - // is around the sum of all of its timings - attempts.forEach((attempt) => { - if (attempt.error) { - attempt.error.stack = e2e.normalizeStdout(attempt.error.stack).trim() - } - - // cannot sum an object, must use array of values - const timings = _.sumBy(_.values(attempt.timings), (val) => { - if (_.isArray(val)) { - // array for hooks - return _.sumBy(val, addFnAndAfterFn) + try { + if (test.displayError) { + test.displayError = e2e.normalizeStdout(test.displayError) } - if (_.isObject(val)) { - // obj for test itself - return addFnAndAfterFn(val) - } + const attempts = test.attempts - return val - }) + // now make sure that each tests wallclock duration + // is around the sum of all of its timings + attempts.forEach((attempt) => { + if (attempt.error) { + attempt.error.stack = e2e.normalizeStdout(attempt.error.stack).trim() + } - expectDurationWithin( - attempt, - 'wallClockDuration', - timings, - timings + 80, // add 80ms to account for padding - 1234, - ) + // cannot sum an object, must use array of values + const timings = _.sumBy(_.values(attempt.timings), (val) => { + if (_.isArray(val)) { + // array for hooks + return _.sumBy(val, addFnAndAfterFn) + } - // now reset all the test timings - normalizeTestTimings(attempt, 'timings') + if (_.isObject(val)) { + // obj for test itself + return addFnAndAfterFn(val) + } - if (attempt.wallClockStartedAt) { - const d = new Date(attempt.wallClockStartedAt) + return val + }) - expect(d.toJSON()).to.eq(attempt.wallClockStartedAt) - attempt.wallClockStartedAt = STATIC_DATE + expectDurationWithin( + attempt, + 'wallClockDuration', + timings, + timings + 80, // add 80ms to account for padding + 1234, + ) - expect(attempt.videoTimestamp).to.be.a('number') - attempt.videoTimestamp = 9999 + // now reset all the test timings + normalizeTestTimings(attempt, 'timings') + + if (attempt.wallClockStartedAt) { + const d = new Date(attempt.wallClockStartedAt) + + expect(d.toJSON()).to.eq(attempt.wallClockStartedAt) + attempt.wallClockStartedAt = STATIC_DATE + + expect(attempt.videoTimestamp).to.be.a('number') + attempt.videoTimestamp = 9999 + } + }) + } catch (e) { + e.message = `Error during validation for test "${test.title.join(' / ')}"\n${e.message}` + throw e } })