diff --git a/docs/integrations/vue.rst b/docs/integrations/vue.rst new file mode 100644 index 000000000000..cd7a5d9d26d9 --- /dev/null +++ b/docs/integrations/vue.rst @@ -0,0 +1,65 @@ +Vue.js (2.0) +============ + +.. sentry:support-warning:: + + This plugin only works with Vue 2.0 or greater. + + +To use Sentry with your Vue application, you will need to use both Raven.js (Sentry's browser JavaScript SDK) and the Raven.js Vue plugin. + +On its own, Raven.js will report any uncaught exceptions triggered from your application. For advanced usage examples of Raven.js, please read :doc:`Raven.js usage <../usage>`. + +Additionally, the Raven.js Vue plugin will capture the name and props state of the active component where the error was thrown. This is reported via Vue's `config.errorHandler` hook. + +Installation +------------ + +Raven.js and the Raven.js Vue plugin are distributed using a few different methods. + +Using our CDN +~~~~~~~~~~~~~ + +For convenience, our CDN serves a single, minified JavaScript file containing both Raven.js and the Raven.js Vue plugin. It should be included **after** Vue, but **before** your application code. + +Example: + +.. sourcecode:: html + + + + + +Note that this CDN build auto-initializes the Vue plugin. + +Using package managers +~~~~~~~~~~~~~~~~~~~~~~ + +Both Raven.js and the Raven.js Vue plugin can be installed via npm and Bower. + +npm +```` + +.. code-block:: sh + + $ npm install raven-js --save + + +Bower +````` + +.. code-block:: sh + + $ bower install raven-js --save + +In your main application file, import and configure both Raven.js and the Raven.js Vue plugin as follows: + +.. code-block:: js + + import Raven from 'raven-js'; + import RavenVue from 'raven-js/plugins/vue'; + + Raven + .config('___PUBLIC_DSN___') + .addPlugin(RavenVue) + .install(); diff --git a/plugins/vue.js b/plugins/vue.js new file mode 100644 index 000000000000..20adcffc08d6 --- /dev/null +++ b/plugins/vue.js @@ -0,0 +1,29 @@ +/** + * Vue.js 2.0 plugin + * + */ +'use strict'; + +function vuePlugin(Raven, Vue) { + Vue = Vue || window.Vue; + + // quit if Vue isn't on the page + if (!Vue || !Vue.config) return; + + var _oldOnError = Vue.config.errorHandler; + Vue.config.errorHandler = function VueErrorHandler(error, vm) { + Raven.captureException(error, { + extra: { + componentName: Vue.util.formatComponentName(vm), + propsData: vm.$options.propsData + } + }); + + if (typeof _oldOnError === 'function') { + _oldOnError.call(this, error, vm); + } + }; +} + +module.exports = vuePlugin; + diff --git a/test/plugins/vue.test.js b/test/plugins/vue.test.js new file mode 100644 index 000000000000..354c8636c94a --- /dev/null +++ b/test/plugins/vue.test.js @@ -0,0 +1,62 @@ +var _Raven = require('../../src/raven'); +var vuePlugin = require('../../plugins/vue'); + +var Raven; +describe('Vue plugin', function () { + beforeEach(function () { + Raven = new _Raven(); + Raven.config('http://abc@example.com:80/2'); + }); + + describe('errorHandler', function () { + beforeEach(function () { + this.sinon.stub(Raven, 'captureException'); + this.MockVue = { + config: {}, + util: { + formatComponentName: function() { + return '' + } + } + }; + }); + + it('should capture component name and propsData', function () { + vuePlugin(Raven, this.MockVue); + + this.MockVue.config.errorHandler(new Error('foo'), { + $options: { + propsData: { + foo: 'bar' + } + } + }, {} /* vm */); + + assert.isTrue(Raven.captureException.calledOnce); + + assert.deepEqual(Raven.captureException.args[0][1].extra, { + propsData: { + foo: 'bar' + }, + componentName: '' + }); + }); + + it('should call the existing error handler', function () { + var errorHandler = this.sinon.stub(); + this.MockVue.config.errorHandler = errorHandler; + vuePlugin(Raven, this.MockVue); // should override errorHandler + + var err = new Error('foo'); + var vm = { + $options: { propsData: {} } + }; + this.MockVue.config.errorHandler(err, vm); + + assert.isTrue(Raven.captureException.calledOnce); + assert.isTrue(errorHandler.calledOnce); + assert.equal(errorHandler.args[0][0], err); + assert.equal(errorHandler.args[0][1], vm); + }); + }); +});