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

WIP: Update driver error messages to allow objects #3752

Merged
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
3 changes: 2 additions & 1 deletion packages/driver/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"lib"
],
"devDependencies": {
"@babel/code-frame": "^7.0.0",
"@cypress/bower-kendo-ui": "0.0.2",
"@cypress/sinon-chai": "1.1.0",
"@cypress/underscore.inflection": "1.0.1",
Expand Down Expand Up @@ -45,8 +46,8 @@
"jsdom": "13.2.0",
"lodash": "4.17.11",
"lolex": "3.1.0",
"methods": "1.1.2",
"method-override": "2.3.10",
"methods": "1.1.2",
"minimatch": "3.0.4",
"minimist": "1.2.0",
"mocha": "cypress-io/mocha#58f6eac05e664fc6b69aa9fba70f1f6b5531a900",
Expand Down
2 changes: 1 addition & 1 deletion packages/driver/src/cy/errors.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ create = (state, config, log) ->
when "app" then "uncaught.fromApp"
when "spec" then "uncaught.fromSpec"

err = $utils.appendErrMsg(err, $utils.errMessageByPath(suffixMsg))
err = $utils.appendErrMsg(err, $utils.errByPath(suffixMsg))

err.onFail = ->
if l = current and current.getLastLog()
Expand Down
11 changes: 6 additions & 5 deletions packages/driver/src/cypress/error_messages.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ module.exports = {
not_registered_without_available: "#{cmd('{{cmd}}')} could not find a registered alias for: '@{{displayName}}'.\nYou have not aliased anything yet."

as:
empty_string: "#{cmd('as')} cannot be passed an empty string."
empty_string:
message: "#{cmd('as')} cannot be passed an empty string."
invalid_type: "#{cmd('as')} can only accept a string."
invalid_first_token: "'{{alias}}' cannot be named starting with the '@' symbol. Try renaming the alias to '{{suggestedName}}', or something else that does not start with the '@' symbol."
reserved_word: "#{cmd('as')} cannot be aliased as: '{{alias}}'. This word is reserved."
Expand Down Expand Up @@ -821,15 +822,15 @@ module.exports = {

msg + if source and lineno then " (#{source}:#{lineno})" else ""

fromApp: """
fromApp:
message: """
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
"""
""",
docs: "https://on.cypress.io/uncaught-exception-from-application"

fromSpec: """
This error originated from your test code, not from Cypress.
Expand Down
77 changes: 64 additions & 13 deletions packages/driver/src/cypress/utils.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ _ = require("lodash")
methods = require("methods")
moment = require("moment")
Promise = require("bluebird")
codeFrameColumns = require("@babel/code-frame").codeFrameColumns

$jquery = require("../dom/jquery")
$Location = require("./location")
Expand Down Expand Up @@ -62,6 +63,10 @@ module.exports = {
## not be evaluated later
stack = err.stack

if _.isObject(message)
err = @copyProperties(message, err)
message = message.message

## preserve message
## and toString
msg = err.message
Expand All @@ -84,11 +89,14 @@ module.exports = {
err2.name = obj.name
err2.stack = obj.stack

for own prop, val of obj
if not err2[prop]
err2[prop] = val
return @copyProperties(obj, err2)

copyProperties: (originalObj, newObj) ->
for own prop, val of originalObj
if not newObj[prop]
newObj[prop] = val

return err2
return newObj

throwErr: (err, options = {}) ->
if _.isString(err)
Expand All @@ -111,7 +119,7 @@ module.exports = {

throwErrByPath: (errPath, options = {}) ->
err = try
@errMessageByPath errPath, options.args
@errByPath errPath, options.args
catch e
err = @internalErr e

Expand All @@ -123,15 +131,17 @@ module.exports = {
err

cypressErr: (err) ->
err = new Error(err)
err.name = "CypressError"
err
if _.isString(err)
err = new Error(err)
err.name = "CypressError"
err

errMessageByPath: (errPath, args) ->
if not errMessage = @getObjValueByPath($errorMessages, errPath)
throw new Error "Error message path '#{errPath}' does not exist"
newErr = new Error(err.message)
newErr.name = "CypressError"
@copyProperties(err, newErr)

getMsg = ->
formatErrorMessage: (errMessage, args) ->
getMessage = ->
if _.isFunction(errMessage)
errMessage(args)
else
Expand All @@ -142,12 +152,53 @@ module.exports = {
## normalize two or more new lines
## into only exactly two new lines
_
.chain(getMsg())
.chain(getMessage())
.split(twoOrMoreNewLinesRe)
.compact()
.join('\n\n')
.value()

getErrorValue: (errPath) ->
if not err = @getObjValueByPath($errorMessages, errPath)
throw new Error "Error path '#{errPath}' does not exist"

return err

errByPath: (errPath, args) ->
err = @getErrorValue(errPath)

if _.isString(err) or _.isFunction(err)
message = @formatErrorMessage(err, args)
return @cypressErr(message)

if !err.message
throw new Error "Error message path '#{errPath}' does not have a message field"
return @cypressErr(err)

errMessageByPath: (errPath, args) ->
errMessage = @getErrorValue(errPath)

if _.isObject(errMessage) and not _.isFunction(errMessage)
if !errMessage.message?
throw new Error "Error message path '#{errPath}' does not have a message field"
errMessage = errMessage.message

@formatErrorMessage(errMessage, args)

getCodeFrame: (source, path, lineNumber, columnNumber) ->
location = { start: { line: lineNumber, column: columnNumber } }
options = {
highlightCode: true,
forceColor: true
}

return {
frame: codeFrameColumns(source, location, options),
path: path,
lineNumber: lineNumber,
columnNumber: columnNumber
}

normalizeObjWithLength: (obj) ->
## lodash shits the bed if our object has a 'length'
## property so we have to normalize that
Expand Down
61 changes: 61 additions & 0 deletions packages/driver/test/cypress/integration/cypress/utils_spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,64 @@ describe "driver/src/cypress/utils", ->
expect(err2.message).to.eq("\n\nbar")

expect(err2.stack).to.eq("Error: \n\nbar\n" + stack)

it "handles error messages as objects", ->
err = new Error("foo")

obj = {
message: "bar",
docs: "baz"
}

stack = err.stack.split("\n").slice(1).join("\n")

err2 = $utils.appendErrMsg(err, obj)
expect(err2.message).to.eq("foo\n\nbar")
expect(err2.docs).to.eq("baz")

expect(err2.stack).to.eq("Error: foo\n\nbar\n" + stack)

context ".getCodeFrame", ->
it "returns a code frame with syntax highlighting", ->
path = "foo/bar/baz"
line = 5
column = 6
src = """
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
foo.bar()
</script>
</body>
</html>
"""

{ frame, path, lineNumber, columnNumber } = $utils.getCodeFrame(src, path, line, column)

expect(frame).to.contain("foo")
expect(frame).to.contain("bar()")
expect(frame).to.contain("[0m")
expect(path).to.eq("foo/bar/baz")
expect(lineNumber).to.eq(5)
expect(columnNumber).to.eq(6)

## TODO determine if we want more failure cases covered
it "fails gracefully", ->
path = "foo/bar/baz"
line = 100
column = 6
src = """
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
foo.bar()
</script>
</body>
</html>
"""

{ frame } = $utils.getCodeFrame(src, path, line, column)

expect(frame).to.eq("")
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe "uncaught errors", ->
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(err.docs).to.eq("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 @@ -57,6 +57,7 @@ Because this error occurred during a 'before each' hook we are skipping the rema
at stack trace line
at stack trace line
at stack trace line
at stack trace line

2) s3a "before all" hook for "t8a":
Error: s3a before hook failed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ We dynamically generated a new test to display this failure.
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down
1 change: 1 addition & 0 deletions packages/server/__snapshots__/2_config_spec.coffee.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ exports['e2e config fails 1'] = `
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down
1 change: 1 addition & 0 deletions packages/server/__snapshots__/3_issue_173_spec.coffee.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ exports['e2e issue 173 failing 1'] = `
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down
2 changes: 2 additions & 0 deletions packages/server/__snapshots__/4_request_spec.coffee.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ RequestError: Error: connect ECONNREFUSED 127.0.0.1:16795
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down Expand Up @@ -279,6 +280,7 @@ Body: Service Unavailable
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ https://on.cypress.io/returning-value-and-commands-in-custom-command
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ exports['e2e spec_isolation failing 1'] = {
],
"state": "failed",
"body": "function () {\n return cy.wrap(true, {\n timeout: 100\n }).should(\"be.false\");\n }",
"stack": "CypressError: Timed out retrying: expected true to be false\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line",
"stack": "CypressError: Timed out retrying: expected true to be false\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line\n at stack trace line",
"error": "Timed out retrying: expected true to be false",
"timings": {
"lifecycle": 100,
Expand Down
2 changes: 2 additions & 0 deletions packages/server/__snapshots__/5_stdout_spec.coffee.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Because this error occurred during a 'before each' hook we are skipping the rema
at stack trace line
at stack trace line
at stack trace line
at stack trace line

3) stdout_failing_spec passing hook is failing:
CypressError: cy.visit() failed trying to load:
Expand Down Expand Up @@ -91,6 +92,7 @@ The internal Cypress web server responded with:
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ https://on.cypress.io/api/task
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down
2 changes: 2 additions & 0 deletions packages/server/__snapshots__/6_task_spec.coffee.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ https://on.cypress.io/api/task
at stack trace line
at stack trace line
at stack trace line
at stack trace line

2) includes stack trace in error:
CypressError: cy.task('errors') failed with the following error:
Expand Down Expand Up @@ -145,6 +146,7 @@ https://on.cypress.io/api/task
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down
4 changes: 4 additions & 0 deletions packages/server/__snapshots__/6_visit_spec.coffee.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ Error: connect ECONNREFUSED 127.0.0.1:16795
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down Expand Up @@ -238,6 +239,7 @@ If you do not want status codes to cause failures pass the option: 'failOnStatus
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down Expand Up @@ -335,6 +337,7 @@ The internal Cypress web server responded with:
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down Expand Up @@ -434,6 +437,7 @@ cy.request() will automatically get and set cookies and enable you to parse resp
at stack trace line
at stack trace line
at stack trace line
at stack trace line



Expand Down
Loading