From 2324158330e882e6c2fea867522ac0060788e59c Mon Sep 17 00:00:00 2001 From: Brian Mann Date: Sun, 3 Dec 2017 21:44:35 -0500 Subject: [PATCH 1/2] driver: provide additional context when uncaught errors originate either from spec code or app code --- packages/driver/src/cy/errors.coffee | 10 +++++++- packages/driver/src/cypress/cy.coffee | 4 ++-- .../driver/src/cypress/error_messages.coffee | 16 +++++++++++++ .../e2e/uncaught_errors_spec.coffee | 3 +++ .../caught_uncaught_hook_errors_spec.coffee | 24 +++++++++++++++++++ .../uncaught_spec_errors_spec.coffee | 16 +++++++++++++ .../uncaught_support_file_spec.coffee | 4 ++++ 7 files changed, 74 insertions(+), 3 deletions(-) diff --git a/packages/driver/src/cy/errors.coffee b/packages/driver/src/cy/errors.coffee index 701f0358bd0d..beb2d1bcbd21 100644 --- a/packages/driver/src/cy/errors.coffee +++ b/packages/driver/src/cy/errors.coffee @@ -26,7 +26,9 @@ create = (state, config, log) -> obj }) - createUncaughtException = (msg, source, lineno, colno, err) -> + createUncaughtException = (type, args) -> + [msg, source, lineno, colno, err] = args + current = state("current") ## reset the msg on a cross origin script error @@ -43,6 +45,12 @@ create = (state, config, log) -> err.name = "Uncaught " + err.name + suffixMsg = switch type + when "app" then "uncaught.fromApp" + when "spec" then "uncaught.fromSpec" + + err = $utils.appendErrMsg(err, $utils.errMessageByPath(suffixMsg)) + err.onFail = -> if l = current and current.getLastLog() l.error(err) diff --git a/packages/driver/src/cypress/cy.coffee b/packages/driver/src/cypress/cy.coffee index 85bd61acd6be..5acc3f724b28 100644 --- a/packages/driver/src/cypress/cy.coffee +++ b/packages/driver/src/cypress/cy.coffee @@ -871,7 +871,7 @@ create = (specWindow, Cypress, Cookies, state, config, log) -> onSpecWindowUncaughtException: -> ## create the special uncaught exception err - err = errors.createUncaughtException.apply(null, arguments) + err = errors.createUncaughtException("spec", arguments) if runnable = state("runnable") ## we're using an explicit done callback here @@ -891,7 +891,7 @@ create = (specWindow, Cypress, Cookies, state, config, log) -> return if not runnable ## create the special uncaught exception err - err = errors.createUncaughtException.apply(null, arguments) + err = errors.createUncaughtException("app", arguments) results = Cypress.action("app:uncaught:exception", err, runnable) diff --git a/packages/driver/src/cypress/error_messages.coffee b/packages/driver/src/cypress/error_messages.coffee index c71a79fa9e58..8925d052f2a3 100644 --- a/packages/driver/src/cypress/error_messages.coffee +++ b/packages/driver/src/cypress/error_messages.coffee @@ -788,6 +788,22 @@ module.exports = { msg + if source and lineno then " (#{source}:#{lineno})" else "" + fromApp: """ + This error originated from *your* application code, not from Cypress. + + When Cypress detects uncaught errors originating from your application it will automatically fail the current test. + + This behavior is configurable, and you can choose to turn this off by listening to the 'uncaught:exception' event. + + https://on.cypress.io/uncaught-exception-from-application + """ + + fromSpec: """ + This error originated from *your* test code, not from Cypress. + + When Cypress detects uncaught errors originating from your test code it will automatically fail the current test. + """ + viewport: bad_args: "#{cmd('viewport')} can only accept a string preset or a width and height as numbers." dimensions_out_of_range: "#{cmd('viewport')} width and height must be between 200px and 3000px." diff --git a/packages/driver/test/cypress/integration/e2e/uncaught_errors_spec.coffee b/packages/driver/test/cypress/integration/e2e/uncaught_errors_spec.coffee index 421a7abb8fbd..ec7d56a3b9b2 100644 --- a/packages/driver/test/cypress/integration/e2e/uncaught_errors_spec.coffee +++ b/packages/driver/test/cypress/integration/e2e/uncaught_errors_spec.coffee @@ -35,7 +35,10 @@ describe "uncaught errors", -> r = cy.state("runnable") cy.on "uncaught:exception", (err, runnable) -> + expect(err.name).to.eq("Uncaught ReferenceError") expect(err.message).to.include("foo is not defined") + expect(err.message).to.include("This error originated from *your* application code, not from Cypress.") + expect(err.message).to.include("https://on.cypress.io/uncaught-exception-from-application") expect(runnable is r).to.be.true return false diff --git a/packages/server/__snapshots__/caught_uncaught_hook_errors_spec.coffee b/packages/server/__snapshots__/caught_uncaught_hook_errors_spec.coffee index f8a989002c01..baa0382d1185 100644 --- a/packages/server/__snapshots__/caught_uncaught_hook_errors_spec.coffee +++ b/packages/server/__snapshots__/caught_uncaught_hook_errors_spec.coffee @@ -87,6 +87,14 @@ Started video recording: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 1) s1b "before each" hook for "t2b": Uncaught ReferenceError: foo is not defined +This error originated from *your* application code, not from Cypress. + +When Cypress detects uncaught errors originating from your application it will automatically fail the current test. + +This behavior is configurable, and you can choose to turn this off by listening to the 'uncaught:exception' event. + +https://on.cypress.io/uncaught-exception-from-application + Because this error occurred during a 'before each' hook we are skipping the remaining tests in the current suite: 's1b' at stack trace line @@ -134,6 +142,14 @@ Started video recording: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 1) "before each" hook for "t1c": Uncaught ReferenceError: foo is not defined +This error originated from *your* application code, not from Cypress. + +When Cypress detects uncaught errors originating from your application it will automatically fail the current test. + +This behavior is configurable, and you can choose to turn this off by listening to the 'uncaught:exception' event. + +https://on.cypress.io/uncaught-exception-from-application + Because this error occurred during a 'before each' hook we are skipping all of the remaining tests. at stack trace line @@ -187,6 +203,14 @@ Started video recording: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 1) uncaught hook error should continue to fire all mocha events s1 "before each" hook for "does not run": Uncaught ReferenceError: foo is not defined +This error originated from *your* application code, not from Cypress. + +When Cypress detects uncaught errors originating from your application it will automatically fail the current test. + +This behavior is configurable, and you can choose to turn this off by listening to the 'uncaught:exception' event. + +https://on.cypress.io/uncaught-exception-from-application + Because this error occurred during a 'before each' hook we are skipping the remaining tests in the current suite: 's1' at stack trace line diff --git a/packages/server/__snapshots__/uncaught_spec_errors_spec.coffee b/packages/server/__snapshots__/uncaught_spec_errors_spec.coffee index 0bc7b8a8734c..6bed561b69d8 100644 --- a/packages/server/__snapshots__/uncaught_spec_errors_spec.coffee +++ b/packages/server/__snapshots__/uncaught_spec_errors_spec.coffee @@ -12,6 +12,10 @@ Started video recording: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 1) An uncaught error was detected outside of a test: Uncaught ReferenceError: foo is not defined +This error originated from *your* test code, not from Cypress. + +When Cypress detects uncaught errors originating from your test code it will automatically fail the current test. + Cypress could not associate this error to any specific test. We dynamically generated a new test to display this failure. @@ -64,6 +68,10 @@ Started video recording: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 1) An uncaught error was detected outside of a test: Uncaught ReferenceError: foo is not defined +This error originated from *your* test code, not from Cypress. + +When Cypress detects uncaught errors originating from your test code it will automatically fail the current test. + Cypress could not associate this error to any specific test. We dynamically generated a new test to display this failure. @@ -118,6 +126,10 @@ Started video recording: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 1) foo bar: Uncaught ReferenceError: foo is not defined + +This error originated from *your* test code, not from Cypress. + +When Cypress detects uncaught errors originating from your test code it will automatically fail the current test. at stack trace line @@ -169,6 +181,10 @@ Started video recording: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 1) foo "before all" hook for "does not run": Uncaught ReferenceError: foo is not defined +This error originated from *your* test code, not from Cypress. + +When Cypress detects uncaught errors originating from your test code it will automatically fail the current test. + Because this error occurred during a 'before all' hook we are skipping the remaining tests in the current suite: 'foo' at stack trace line diff --git a/packages/server/__snapshots__/uncaught_support_file_spec.coffee b/packages/server/__snapshots__/uncaught_support_file_spec.coffee index 20ef3d26c982..b2724bcd0570 100644 --- a/packages/server/__snapshots__/uncaught_support_file_spec.coffee +++ b/packages/server/__snapshots__/uncaught_support_file_spec.coffee @@ -12,6 +12,10 @@ Started video recording: /foo/bar/.projects/uncaught-support-file/cypress/videos 1) An uncaught error was detected outside of a test: Uncaught Error: bar +This error originated from *your* test code, not from Cypress. + +When Cypress detects uncaught errors originating from your test code it will automatically fail the current test. + Cypress could not associate this error to any specific test. We dynamically generated a new test to display this failure. From d5b4ab862ca9aaff15dbcc1a5c7fb2e150300289 Mon Sep 17 00:00:00 2001 From: Brian Mann Date: Sun, 3 Dec 2017 22:35:37 -0500 Subject: [PATCH 2/2] server: fix failing snapshots for uncaught exceptions in spec + test code --- .../commands_outside_of_test_spec.coffee | 7 ++++-- .../js_error_handling_spec.coffee | 24 +++++++++++++++++++ .../e2e/commands_outside_of_test_spec.coffee | 10 +------- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/packages/server/__snapshots__/commands_outside_of_test_spec.coffee b/packages/server/__snapshots__/commands_outside_of_test_spec.coffee index 2cfd2e4ec26e..f476f8b79e4a 100644 --- a/packages/server/__snapshots__/commands_outside_of_test_spec.coffee +++ b/packages/server/__snapshots__/commands_outside_of_test_spec.coffee @@ -1,4 +1,4 @@ -exports['e2e commands outside of test passes 1'] = ` +exports['e2e commands outside of test fails 1'] = ` Started video recording: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 (Tests Starting) @@ -20,6 +20,10 @@ Check your test file for errors. https://on.cypress.io/cannot-execute-commands-outside-test +This error originated from *your* test code, not from Cypress. + +When Cypress detects uncaught errors originating from your test code it will automatically fail the current test. + Cypress could not associate this error to any specific test. We dynamically generated a new test to display this failure. @@ -60,4 +64,3 @@ We dynamically generated a new test to display this failure. (All Done) ` - diff --git a/packages/server/__snapshots__/js_error_handling_spec.coffee b/packages/server/__snapshots__/js_error_handling_spec.coffee index c08d26cb5efc..2568bc41884d 100644 --- a/packages/server/__snapshots__/js_error_handling_spec.coffee +++ b/packages/server/__snapshots__/js_error_handling_spec.coffee @@ -22,6 +22,14 @@ Started video recording: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 1) s1 without an afterEach hook t1: Uncaught ReferenceError: foo is not defined + +This error originated from *your* application code, not from Cypress. + +When Cypress detects uncaught errors originating from your application it will automatically fail the current test. + +This behavior is configurable, and you can choose to turn this off by listening to the 'uncaught:exception' event. + +https://on.cypress.io/uncaught-exception-from-application at stack trace line at stack trace line at stack trace line @@ -36,6 +44,14 @@ Started video recording: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 3) s1 with an afterEach hook t4: Uncaught ReferenceError: foo is not defined + +This error originated from *your* application code, not from Cypress. + +When Cypress detects uncaught errors originating from your application it will automatically fail the current test. + +This behavior is configurable, and you can choose to turn this off by listening to the 'uncaught:exception' event. + +https://on.cypress.io/uncaught-exception-from-application at stack trace line at stack trace line at stack trace line @@ -56,6 +72,14 @@ Check your Developer Tools Console for the actual error - it should be printed t It's possible to enable debugging these scripts by adding the 'crossorigin' attribute and setting a CORS header. https://on.cypress.io/cross-origin-script-error + +This error originated from *your* application code, not from Cypress. + +When Cypress detects uncaught errors originating from your application it will automatically fail the current test. + +This behavior is configurable, and you can choose to turn this off by listening to the 'uncaught:exception' event. + +https://on.cypress.io/uncaught-exception-from-application at stack trace line at stack trace line at stack trace line diff --git a/packages/server/test/e2e/commands_outside_of_test_spec.coffee b/packages/server/test/e2e/commands_outside_of_test_spec.coffee index bd6f707ed61c..9bf5e176c8d5 100644 --- a/packages/server/test/e2e/commands_outside_of_test_spec.coffee +++ b/packages/server/test/e2e/commands_outside_of_test_spec.coffee @@ -3,15 +3,7 @@ e2e = require("../support/helpers/e2e") describe "e2e commands outside of test", -> e2e.setup() - it "passes", -> - ## TODO: currently this doesn't actually cause mocha - ## to fail and therefore our exit code is 0 - ## because this error is thrown in the console - ## and cannot be properly tied to a test - ## --- - ## perhaps we should dynamically generate a test to - ## associate it for stdout? how else would a user know - ## whats going on? + it "fails", -> e2e.exec(@, { spec: "commands_outside_of_test_spec.coffee" snapshot: true