From 5606a0f7607bb5572ac9ac73af5c4ad965e4edb7 Mon Sep 17 00:00:00 2001 From: Ben Vinegar Date: Wed, 27 Jul 2016 18:00:22 -0700 Subject: [PATCH] Update Angular error regex to work w/ minified exceptions (fixes #606) --- plugins/angular.js | 39 +++++++++++++--------- test/plugins/angular.test.js | 65 ++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 16 deletions(-) create mode 100644 test/plugins/angular.test.js diff --git a/plugins/angular.js b/plugins/angular.js index 15a8c5da2bac..b30ae772a29d 100644 --- a/plugins/angular.js +++ b/plugins/angular.js @@ -6,7 +6,8 @@ 'use strict'; // See https://github.com/angular/angular.js/blob/v1.4.7/src/minErr.js -var angularPattern = /^\[((?:[$a-zA-Z0-9]+:)?(?:[$a-zA-Z0-9]+))\] (.+?)\n(\S+)$/; +var angularPattern = /^\[((?:[$a-zA-Z0-9]+:)?(?:[$a-zA-Z0-9]+))\] (.*?)\n?(\S+)$/; + function angularPlugin(Raven, angular) { angular = angular || window.angular; @@ -38,23 +39,29 @@ function angularPlugin(Raven, angular) { .config(['$provide', ExceptionHandlerProvider]); Raven.setDataCallback(function(data, original) { - // We only care about mutating an exception - var exception = data.exception; - if (exception) { - exception = exception.values[0]; - var matches = angularPattern.exec(exception.value); - - if (matches) { - // This type now becomes something like: $rootScope:inprog - exception.type = matches[1]; - exception.value = matches[2]; - data.message = exception.type + ': ' + exception.value; - // auto set a new tag specifically for the angular error url - data.extra.angularDocs = matches[3].substr(0, 250); - } - } + angularPlugin._normalizeData(data); + original && original(data); }); } +angularPlugin._normalizeData = function (data) { + // We only care about mutating an exception + var exception = data.exception; + if (exception) { + exception = exception.values[0]; + var matches = angularPattern.exec(exception.value); + + if (matches) { + // This type now becomes something like: $rootScope:inprog + exception.type = matches[1]; + exception.value = matches[2]; + + data.message = exception.type + ': ' + exception.value; + // auto set a new tag specifically for the angular error url + data.extra.angularDocs = matches[3].substr(0, 250); + } + } +}; + module.exports = angularPlugin; diff --git a/test/plugins/angular.test.js b/test/plugins/angular.test.js new file mode 100644 index 000000000000..974c67e0d72c --- /dev/null +++ b/test/plugins/angular.test.js @@ -0,0 +1,65 @@ +var _Raven = require('../../src/raven'); +var angularPlugin = require('../../plugins/angular'); + +var Raven; +describe('Angular plugin', function () { + beforeEach(function () { + Raven = new _Raven(); + Raven.config('http://abc@example.com:80/2'); + }); + + describe('_normalizeData()', function () { + it('should extract type, value, and the angularDocs URL from unminified exceptions', function () { + var data = { + project: '2', + logger: 'javascript', + platform: 'javascript', + + culprit: 'http://example.org/app.js', + message: 'Error: crap', + exception: { + type: 'Error', + values: [{ + value: + '[ngRepeat:dupes] Duplicates in a repeater are not allowed. Use \'track by\' expression to specify unique keys. Repeater: element in elements | orderBy: \'createdAt\' track by element.id, Duplicate key: 25, Duplicate value: {"id":"booking-40"}\n' + + 'http://errors.angularjs.org/1.4.3/ngRepeat/dupes?p0=element%20in%20elements…00%3A00%22%2C%22ends_at%22%3A%222016-06-09T23%3A59%3A59%2B00%3A00%22%7D%7D' + }] + }, + extra: {} + }; + + angularPlugin._normalizeData(data); + + var exception = data.exception.values[0]; + assert.equal(exception.type, 'ngRepeat:dupes'); + assert.equal(exception.value, 'Duplicates in a repeater are not allowed. Use \'track by\' expression to specify unique keys. Repeater: element in elements | orderBy: \'createdAt\' track by element.id, Duplicate key: 25, Duplicate value: {"id":"booking-40"}'); + assert.equal(data.extra.angularDocs, 'http://errors.angularjs.org/1.4.3/ngRepeat/dupes?p0=element%20in%20elements…00%3A00%22%2C%22ends_at%22%3A%222016-06-09T23%3A59%3A59%2B00%3A00%22%7D%7D'); + }); + + it('should extract type and the angularDocs URL minified exceptions', function () { + var data = { + project: '2', + logger: 'javascript', + platform: 'javascript', + + culprit: 'http://example.org/app.js', + message: 'Error: crap', + exception: { + type: 'Error', + values: [{ + // no message, no newlines + value: '[ngRepeat:dupes] http://errors.angularjs.org/1.4.3/ngRepeat/dupes?p0=element%20in%20elements…00%3A00%22%2C%22ends_at%22%3A%222016-06-09T23%3A59%3A59%2B00%3A00%22%7D%7D' + }] + }, + extra: {} + }; + + angularPlugin._normalizeData(data); + + var exception = data.exception.values[0]; + assert.equal(exception.type, 'ngRepeat:dupes'); + assert.equal(exception.value, ''); + assert.equal(data.extra.angularDocs, 'http://errors.angularjs.org/1.4.3/ngRepeat/dupes?p0=element%20in%20elements…00%3A00%22%2C%22ends_at%22%3A%222016-06-09T23%3A59%3A59%2B00%3A00%22%7D%7D'); + }); + }); +});