Skip to content

Commit

Permalink
fix: log error on reject with string content
Browse files Browse the repository at this point in the history
  • Loading branch information
geritol committed Dec 8, 2022
1 parent 79f743e commit ab033fa
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 5 deletions.
27 changes: 26 additions & 1 deletion packages/driver/cypress/component/spec.cy.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import sinon from 'sinon'

describe('component testing', () => {
/** @type {Cypress.Agent<sinon.SinonSpy>} */
let uncaughtExceptionStub
Expand All @@ -12,17 +14,40 @@ describe('component testing', () => {
})
})

beforeEach(() => {
uncaughtExceptionStub.resetHistory()
document.querySelector('[data-cy-root]').innerHTML = ''
})

it('fails and shows an error', () => {
cy.spy(Cypress, 'log').log(false)
const $el = document.createElement('button')

$el.innerText = `Don't click it!`
$el.addEventListener('click', () => {
throw Error('An error!')
throw new Error('An error!')
})

document.querySelector('[data-cy-root]').appendChild($el)
cy.get('button').click().then(() => {
expect(uncaughtExceptionStub).to.have.been.calledOnceWithExactly(null)
expect(Cypress.log).to.be.calledWithMatch(sinon.match({ 'message': `Error: An error!`, name: 'uncaught exception' }))
})
})

it('fails and shows when a promise rejects with a string', () => {
cy.spy(Cypress, 'log').log(false)
const $el = document.createElement('button')

$el.innerText = `Don't click it!`
$el.addEventListener('click', new Promise((_, reject) => {
reject('Promise rejected with a string!')
}))

document.querySelector('[data-cy-root]').appendChild($el)
cy.get('button').click().then(() => {
expect(uncaughtExceptionStub).to.have.been.calledOnceWithExactly(null)
expect(Cypress.log).to.be.calledWithMatch(sinon.match({ 'message': `Error: "Promise rejected with a string!"`, name: 'uncaught exception' }))
})
})
})
25 changes: 23 additions & 2 deletions packages/driver/cypress/e2e/cypress/error_utils.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ allowTsModuleStubbing()
import $stackUtils from '@packages/driver/src/cypress/stack_utils'
import $errUtils, { CypressError } from '@packages/driver/src/cypress/error_utils'
import $errorMessages from '@packages/driver/src/cypress/error_messages'
import sinon from 'sinon'

describe('driver/src/cypress/error_utils', () => {
context('.modifyErrMsg', () => {
Expand Down Expand Up @@ -90,7 +91,7 @@ describe('driver/src/cypress/error_utils', () => {
})

it('attaches onFail to the error when it is a function', () => {
const onFail = function () {}
const onFail = function () { }
const fn = () => $errUtils.throwErr(new Error('foo'), { onFail })

expect(fn).throw().and.satisfy((err) => {
Expand Down Expand Up @@ -561,7 +562,7 @@ describe('driver/src/cypress/error_utils', () => {

it('does not error if no last log', () => {
state.returns({
getLastLog: () => {},
getLastLog: () => { },
})

const result = $errUtils.createUncaughtException({
Expand Down Expand Up @@ -660,4 +661,24 @@ describe('driver/src/cypress/error_utils', () => {
expect(unsupportedPlugin).to.eq(null)
})
})

context('.logError', () => {
let cypressMock

beforeEach(() => {
cypressMock = {
log: cy.stub(),
}
})

it('calls Cypress.log with error type and message when error is instance of Error', () => {
$errUtils.logError(cypressMock, 'error', new Error('Some error'))
expect(cypressMock.log).to.have.been.calledWithMatch(sinon.match.has('message', `Error: Some error`))
})

it('calls Cypress.log with error type and message when error a string', () => {
$errUtils.logError(cypressMock, 'error', 'Some error')
expect(cypressMock.log).to.have.been.calledWithMatch(sinon.match.has('message', `Error: \"Some error\"`))
})
})
})
25 changes: 23 additions & 2 deletions packages/driver/src/cypress/error_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -549,9 +549,11 @@ const errorFromUncaughtEvent = (handlerType: HandlerType, event) => {
errorFromProjectRejectionEvent(event)
}

const logError = (Cypress, handlerType: HandlerType, err, handled = false) => {
const logError = (Cypress, handlerType: HandlerType, err: unknown, handled = false) => {
const error = toLoggableError(err)

Cypress.log({
message: `${err.name}: ${err.message}`,
message: `${error.name}: ${error.message}`,
name: 'uncaught exception',
type: 'parent',
// specifying the error causes the log to be red/failed
Expand All @@ -572,6 +574,25 @@ const logError = (Cypress, handlerType: HandlerType, err, handled = false) => {
})
}

const isLogabbleError = (error: unknown): error is Error => {
return (
typeof error === 'object' &&
error !== null &&
'message' in error &&
typeof (error as Record<string, unknown>).message === 'string'
)
}

const toLoggableError = (maybeError: unknown): Error => {
if (isLogabbleError(maybeError)) return maybeError

try {
return new Error(JSON.stringify(maybeError))
} catch {
return new Error(String(maybeError))
}
}

const getUnsupportedPlugin = (runnable) => {
if (!(runnable.invocationDetails && runnable.invocationDetails.originalFile && runnable.err && runnable.err.message)) {
return null
Expand Down

0 comments on commit ab033fa

Please sign in to comment.