Skip to content

Commit

Permalink
feat(errors): propogate thrown errors by configuring error handler (#154
Browse files Browse the repository at this point in the history
)

* Propogate thrown errors by configuring error handler and attaching in mount function resolves #147

* set errorHandler to be a default export and set Vue.config.errorHandler = errorHandler in mount

* Add test for create-local-vue error handler being defined and configure that in create local vue
  • Loading branch information
Austio authored and eddyerburgh committed Nov 9, 2017
1 parent e484c7e commit 3f3c64a
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/create-local-vue.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import Vue from 'vue'
import cloneDeep from 'lodash/cloneDeep'
import errorHandler from './lib/error-handler'

function createLocalVue (): Component {
const instance = Vue.extend()
Expand All @@ -19,6 +20,8 @@ function createLocalVue (): Component {
// config is not enumerable
instance.config = cloneDeep(Vue.config)

instance.config.errorHandler = errorHandler

// option merge strategies need to be exposed by reference
// so that merge strats registered by plguins can work properly
instance.config.optionMergeStrategies = Vue.config.optionMergeStrategies
Expand Down
19 changes: 19 additions & 0 deletions src/lib/error-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
function errorMessage (msg, info) {
if (info) {
return `${msg} : additional info ${info}`
}

return msg
}

export default function errorHandler (err, _vm, info) {
if ((typeof err === 'object') && err.message) {
if (info) {
err.message = errorMessage(err.message, info)
}

throw err
}

throw new Error(errorMessage(err, info))
}
2 changes: 2 additions & 0 deletions src/mount.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import createInstance from './lib/create-instance'
import cloneDeep from 'lodash/cloneDeep'
import createElement from './lib/create-element'
import './lib/matches-polyfill'
import errorHandler from './lib/error-handler'

Vue.config.productionTip = false
Vue.config.errorHandler = errorHandler

export default function mount (component: Component, options: Options = {}): VueWrapper {
const componentToMount = options.clone === false ? component : cloneDeep(component.extend ? component.options : component)
Expand Down
6 changes: 6 additions & 0 deletions test/unit/specs/create-local-vue.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,10 @@ describe('createLocalVue', () => {
const localVue = createLocalVue()
localVue.use(Vuetify)
})

it('has an errorHandler', () => {
const localVue = createLocalVue()

expect(localVue.config.errorHandler).to.be.an('function')
})
})
31 changes: 31 additions & 0 deletions test/unit/specs/lib/error-handler.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import errorHandler from '../../../../src/lib/error-handler'

describe('errorHandler', () => {
const errorString = 'errorString'
const info = 'additional info provided by vue'
const errorObject = new Error(errorString)

it('when error object: rethrows error', () => {
expect(() => errorHandler(errorObject)).to.throw().with.property('message', errorString)
})

it('when error object: rethrown error contains vue info when provided', () => {
expect(() => errorHandler(errorObject, {}, info)).to.throw().that.satisfies(function (err) {
const errorMessage = err.message

return errorMessage.includes(errorString) && errorMessage.includes(info)
})
})

it('when error string: throws error with string', () => {
expect(() => errorHandler(errorString)).to.throw().with.property('message', errorString)
})

it('throws error with string and appends info when provided', () => {
expect(() => errorHandler(errorString, {}, info)).to.throw().that.satisfies(function (err) {
const errorMessage = err.message

return errorMessage.includes(errorString) && errorMessage.includes(info)
})
})
})
9 changes: 9 additions & 0 deletions test/unit/specs/mount.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,13 @@ describe('mount', () => {
expect(wrapper.vm).to.be.an('object')
expect(wrapper.html()).to.equal(`<div>foo</div>`)
})

it('throws an error when the component fails to mount', () => {
expect(() => mount({
template: '<div></div>',
mounted: function () {
throw (new Error('Error'))
}
})).to.throw()
})
})
9 changes: 9 additions & 0 deletions test/unit/specs/shallow.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,13 @@ describe('shallow', () => {
shallow(ComponentWithNestedChildren)
expect(info.called).to.equal(false)
})

it('throws an error when the component fails to mount', () => {
expect(() => shallow({
template: '<div></div>',
mounted: function () {
throw (new Error('Error'))
}
})).to.throw()
})
})

0 comments on commit 3f3c64a

Please sign in to comment.