forked from bluesmoon/boomerang
-
Notifications
You must be signed in to change notification settings - Fork 294
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Errors: Loader Snippet to capture errors before Boomerang arrives
- Loading branch information
Showing
8 changed files
with
343 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<script> | ||
<%= captureErrorsSnippetNoScript %> | ||
</script> |
56 changes: 56 additions & 0 deletions
56
tests/page-template-snippets/captureErrorsSnippetNoScript.tpl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
(function(w){ | ||
w.BOOMR = w.BOOMR || {}; | ||
|
||
w.BOOMR.globalOnErrorOrig = w.BOOMR.globalOnError = w.onerror; | ||
w.BOOMR.globalErrors = []; | ||
|
||
var now = (function() { | ||
try { | ||
if ("performance" in w) { | ||
return function() { | ||
return Math.round(w.performance.now() + performance.timing.navigationStart); | ||
}; | ||
} | ||
} | ||
catch (ignore) {} | ||
|
||
return Date.now || function() { | ||
return new Date().getTime(); | ||
}; | ||
})(); | ||
|
||
w.onerror = function BOOMR_plugins_errors_onerror(message, fileName, lineNumber, columnNumber, error) { | ||
if (w.BOOMR.version) { | ||
// If Boomerang has already loaded, the only reason this function would still be alive would be if | ||
// we're in the chain from another handler that overwrote window.onerror. In that case, we should | ||
// run globalOnErrorOrig which presumably hasn't been overwritten by Boomerang. | ||
if (typeof w.BOOMR.globalOnErrorOrig === "function") { | ||
w.BOOMR.globalOnErrorOrig.apply(w, arguments); | ||
} | ||
|
||
return; | ||
} | ||
|
||
if (typeof error !== "undefined" && error !== null) { | ||
error.timestamp = now(); | ||
w.BOOMR.globalErrors.push(error); | ||
} | ||
else { | ||
w.BOOMR.globalErrors.push({ | ||
message: message, | ||
fileName: fileName, | ||
lineNumber: lineNumber, | ||
columnNumber: columnNumber, | ||
noStack: true, | ||
timestamp: now() | ||
}); | ||
} | ||
|
||
if (typeof w.BOOMR.globalOnError === "function") { | ||
w.BOOMR.globalOnError.apply(w, arguments); | ||
} | ||
}; | ||
|
||
// make it easier to detect this is our wrapped handler | ||
w.onerror._bmr = true; | ||
})(window); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<%= header %> | ||
<script> | ||
window.errorsLogged = 0; | ||
window.onerror = function() { | ||
window.errorsLogged++; | ||
}; | ||
</script> | ||
<%= captureErrorsSnippet %> | ||
<script> | ||
function errorFunction1() { | ||
// a is not defined | ||
a.foo = 1; | ||
} | ||
function errorFunction2() { | ||
// a is not defined | ||
a.foo = 1; | ||
} | ||
function errorFunction3() { | ||
// a is not defined | ||
a.foo = 2; | ||
} | ||
errorFunction1(); | ||
</script> | ||
<script> | ||
errorFunction2(); | ||
</script> | ||
<%= boomerangScriptMin %> | ||
<script src="26-loader-snippet.js" type="text/javascript"></script> | ||
<script> | ||
BOOMR_test.init({ | ||
testAfterOnBeacon: true, | ||
Errors: { | ||
enabled: true, | ||
monitorGlobal: true | ||
} | ||
}); | ||
</script> | ||
<!-- delay the page by 1second so an error can fire --> | ||
<img src="/delay?delay=1000&file=/assets/img.jpg" style="width: 100px" /> | ||
<script> | ||
errorFunction3(); | ||
</script> | ||
<%= footer %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
/*eslint-env mocha*/ | ||
/*global BOOMR_test,assert*/ | ||
|
||
describe("e2e/14-errors/26-loader-snippet", function() { | ||
var tf = BOOMR.plugins.TestFramework; | ||
var t = BOOMR_test; | ||
var C = BOOMR.utils.Compression; | ||
|
||
it("Should have sent a single beacon validation", function(done) { | ||
t.validateBeaconWasSent(done); | ||
}); | ||
|
||
it("Should have put the err on the beacon", function() { | ||
var b = tf.lastBeacon(); | ||
assert.isDefined(b.err); | ||
}); | ||
|
||
it("Should have had 3 errors", function() { | ||
var b = tf.lastBeacon(); | ||
assert.equal(C.jsUrlDecompress(b.err).length, 3); | ||
}); | ||
|
||
it("Should have count = 1 for each error", function() { | ||
var b = tf.lastBeacon(); | ||
var errs = BOOMR.plugins.Errors.decompressErrors(C.jsUrlDecompress(b.err)); | ||
for (var i = 0; i < 3; i++) { | ||
var err = errs[i]; | ||
assert.equal(err.count, 1); | ||
} | ||
}); | ||
|
||
it("Should have fileName of the page (if set) for each error", function() { | ||
var b = tf.lastBeacon(); | ||
var errs = BOOMR.plugins.Errors.decompressErrors(C.jsUrlDecompress(b.err)); | ||
for (var i = 0; i < 3; i++) { | ||
var err = errs[i]; | ||
|
||
if (err.fileName) { | ||
assert.include(err.fileName, "26-loader-snippet.html"); | ||
} | ||
} | ||
}); | ||
|
||
it("Should have functionName of 'errorFunction' for each error", function() { | ||
var b = tf.lastBeacon(); | ||
var errs = BOOMR.plugins.Errors.decompressErrors(C.jsUrlDecompress(b.err)); | ||
for (var i = 0; i < 3; i++) { | ||
var err = errs[i]; | ||
|
||
if (err.functionName) { | ||
assert.include(err.functionName, "errorFunction"); | ||
} | ||
} | ||
}); | ||
|
||
it("Should have message = 'a is not defined' or 'Can't find variable: a' or ''a' is undefined' for each error", function() { | ||
var b = tf.lastBeacon(); | ||
var errs = BOOMR.plugins.Errors.decompressErrors(C.jsUrlDecompress(b.err)); | ||
for (var i = 0; i < 3; i++) { | ||
var err = errs[i]; | ||
|
||
// Chrome, Firefox == a is not defined, Safari = Can't find variable | ||
assert.isTrue( | ||
err.message.indexOf("a is not defined") !== -1 || | ||
err.message.indexOf("Can't find variable: a") !== -1 || | ||
err.message.indexOf("'a' is undefined") !== -1); | ||
} | ||
}); | ||
|
||
it("Should have source = APP for each error", function() { | ||
var b = tf.lastBeacon(); | ||
var errs = BOOMR.plugins.Errors.decompressErrors(C.jsUrlDecompress(b.err)); | ||
for (var i = 0; i < 3; i++) { | ||
var err = errs[i]; | ||
|
||
assert.equal(err.source, BOOMR.plugins.Errors.SOURCE_APP); | ||
} | ||
}); | ||
|
||
it("Should have stack with the stack for each error", function() { | ||
var b = tf.lastBeacon(); | ||
var errs = BOOMR.plugins.Errors.decompressErrors(C.jsUrlDecompress(b.err)); | ||
for (var i = 0; i < 3; i++) { | ||
var err = errs[i]; | ||
|
||
assert.isDefined(err.stack); | ||
} | ||
}); | ||
|
||
it("Should have type = 'ReferenceError' or 'Error' for each error", function() { | ||
var b = tf.lastBeacon(); | ||
var errs = BOOMR.plugins.Errors.decompressErrors(C.jsUrlDecompress(b.err)); | ||
for (var i = 0; i < 3; i++) { | ||
var err = errs[i]; | ||
|
||
// Chrome, Firefox == ReferenceError, Safari = Error | ||
assert.isTrue(err.type === "ReferenceError" || err.type === "Error"); | ||
} | ||
}); | ||
|
||
it("Should have via = GLOBAL_EXCEPTION_HANDLER for each error", function() { | ||
var b = tf.lastBeacon(); | ||
var errs = BOOMR.plugins.Errors.decompressErrors(C.jsUrlDecompress(b.err)); | ||
for (var i = 0; i < 3; i++) { | ||
var err = errs[i]; | ||
|
||
assert.equal(err.via, BOOMR.plugins.Errors.VIA_GLOBAL_EXCEPTION_HANDLER); | ||
} | ||
}); | ||
|
||
it("Should have columNumber to be a number if specified for each error", function() { | ||
var b = tf.lastBeacon(); | ||
var errs = BOOMR.plugins.Errors.decompressErrors(C.jsUrlDecompress(b.err)); | ||
for (var i = 0; i < 3; i++) { | ||
var err = errs[i]; | ||
|
||
if (typeof err.columnNumber !== "undefined") { | ||
assert.isTrue(err.columnNumber >= 0); | ||
} | ||
} | ||
}); | ||
|
||
it("Should have called the original window.onerror for each error", function() { | ||
assert.equal(window.errorsLogged, 3); | ||
}); | ||
}); |
51 changes: 51 additions & 0 deletions
51
tests/page-templates/14-errors/27-loader-snippet-overwritten.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<%= header %> | ||
<script> | ||
window.errorsLogged1 = 0; | ||
window.onerror = function() { | ||
window.errorsLogged1++; | ||
}; | ||
</script> | ||
<%= captureErrorsSnippet %> | ||
<script> | ||
// now have another snippet override ours | ||
window.oldOnError = window.onerror; | ||
window.errorsLogged2 = 0; | ||
window.onerror = function() { | ||
window.errorsLogged2++; | ||
window.oldOnError.apply(window, arguments); | ||
}; | ||
|
||
function errorFunction1() { | ||
// a is not defined | ||
a.foo = 1; | ||
} | ||
function errorFunction2() { | ||
// a is not defined | ||
a.foo = 1; | ||
} | ||
function errorFunction3() { | ||
// a is not defined | ||
a.foo = 2; | ||
} | ||
errorFunction1(); | ||
</script> | ||
<script> | ||
errorFunction2(); | ||
</script> | ||
<%= boomerangScriptMin %> | ||
<script src="27-loader-snippet-overwritten.js" type="text/javascript"></script> | ||
<script> | ||
BOOMR_test.init({ | ||
testAfterOnBeacon: true, | ||
Errors: { | ||
enabled: true, | ||
monitorGlobal: true | ||
} | ||
}); | ||
</script> | ||
<!-- delay the page by 1second so an error can fire --> | ||
<img src="/delay?delay=1000&file=/assets/img.jpg" style="width: 100px" /> | ||
<script> | ||
errorFunction3(); | ||
</script> | ||
<%= footer %> |
30 changes: 30 additions & 0 deletions
30
tests/page-templates/14-errors/27-loader-snippet-overwritten.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/*eslint-env mocha*/ | ||
/*global BOOMR_test,assert*/ | ||
|
||
describe("e2e/14-errors/26-loader-snippet", function() { | ||
var tf = BOOMR.plugins.TestFramework; | ||
var t = BOOMR_test; | ||
var C = BOOMR.utils.Compression; | ||
|
||
it("Should have sent a single beacon validation", function(done) { | ||
t.validateBeaconWasSent(done); | ||
}); | ||
|
||
it("Should have put the err on the beacon", function() { | ||
var b = tf.lastBeacon(); | ||
assert.isDefined(b.err); | ||
}); | ||
|
||
it("Should have had 3 errors", function() { | ||
var b = tf.lastBeacon(); | ||
assert.equal(C.jsUrlDecompress(b.err).length, 3); | ||
}); | ||
|
||
it("Should have called the original window.onerror for each error", function() { | ||
assert.equal(window.errorsLogged1, 3); | ||
}); | ||
|
||
it("Should have called the second window.onerror for each error", function() { | ||
assert.equal(window.errorsLogged2, 3); | ||
}); | ||
}); |