Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

driver: provide additional context when uncaught errors originate either from spec code or app code #999

Merged
merged 2 commits into from
Dec 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion packages/driver/src/cy/errors.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions packages/driver/src/cypress/cy.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)

Expand Down
16 changes: 16 additions & 0 deletions packages/driver/src/cypress/error_messages.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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.
Expand Down Expand Up @@ -60,4 +64,3 @@ We dynamically generated a new test to display this failure.
(All Done)

`

24 changes: 24 additions & 0 deletions packages/server/__snapshots__/js_error_handling_spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
16 changes: 16 additions & 0 deletions packages/server/__snapshots__/uncaught_spec_errors_spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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


Expand Down Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 1 addition & 9 deletions packages/server/test/e2e/commands_outside_of_test_spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down