diff --git a/boomerang.js b/boomerang.js index 0ab0ce655..94e567c9e 100644 --- a/boomerang.js +++ b/boomerang.js @@ -1453,6 +1453,24 @@ BOOMR_check_doc_domain(); } }, + /** + * MutationObserver feature detection + * + * @returns {boolean} Returns true if MutationObserver is supported. + * Always returns false for IE 11 due several bugs in it's implementation that MS flagged as Won't Fix. + * In IE11, XHR responseXML might be malformed if MO is enabled (where extra newlines get added in nodes with UTF-8 content). + * Another IE 11 MO bug can cause the process to crash when certain mutations occur. + * For the process crash issue, see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8137215/ and + * https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/15167323/ + * + * @memberof BOOMR.utils + */ + isMutationObserverSupported: function() { + // We can only detect IE 11 bugs by UA sniffing. + var ie11 = (w && w.navigator && w.navigator.userAgent && w.navigator.userAgent.match(/Trident.*rv[ :]*11\./)); + return (!ie11 && w && w.MutationObserver && typeof w.MutationObserver === "function"); + }, + /** * The callback function may return a falsy value to disconnect the * observer after it returns, or a truthy value to keep watching for @@ -1492,7 +1510,7 @@ BOOMR_check_doc_domain(); addObserver: function(el, config, timeout, callback, callback_data, callback_ctx) { var o = {observer: null, timer: null}; - if (!BOOMR.window || !BOOMR.window.MutationObserver || !callback || !el) { + if (!this.isMutationObserverSupported() || !callback || !el) { return null; } diff --git a/plugins/auto-xhr.js b/plugins/auto-xhr.js index a93d7224b..8a94c2cfd 100644 --- a/plugins/auto-xhr.js +++ b/plugins/auto-xhr.js @@ -77,6 +77,9 @@ * [MutationObserver]{@link https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver} * and [XMLHttpRequest]{@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest}. * + * We will not use MutationObserver in IE 11 due to several browser bugs. + * See {@link BOOMR.utils.isMutationObserverSupported} for details. + * * ## Excluding Certain Requests From Instrumentation * * Whenever Boomerang intercepts an `XMLHttpRequest`, it will check if that request @@ -222,8 +225,7 @@ singlePageApp = false, autoXhrEnabled = false, alwaysSendXhr = false, - readyStateMap = ["uninitialized", "open", "responseStart", "domInteractive", "responseEnd"], - ie10or11; + readyStateMap = ["uninitialized", "open", "responseStart", "domInteractive", "responseEnd"]; /** * Single Page Applications get an additional timeout for all XHR Requests to settle in. @@ -315,14 +317,6 @@ return; } - // User-agent sniff IE 10 and IE 11 to apply a workaround for an XHR bug (see below when - // this variable is used). We can only detect this bug by UA sniffing. IE 11 requires a - // different way of detection than IE 11. - ie10or11 = (w.navigator && w.navigator.appVersion && w.navigator.appVersion.indexOf("MSIE 10") !== -1) || - (w.navigator && w.navigator.userAgent && w.navigator.userAgent.match(/Trident.*rv[ :]*11\./)); - - - function log(msg) { BOOMR.debug(msg, "AutoXHR"); } @@ -1546,19 +1540,6 @@ if (ename === "readystatechange") { resource.timing[readyStateMap[req.readyState]] = BOOMR.now(); - // For IE 10 and 11, we need to turn off the MutationObserver before responseXML - // is first referenced, otherwise responseXML might be malformed due to a browser - // bug (where extra newlines get added in nodes with UTF-8 content) - if (impl.ie1011fix && ie10or11 && req.readyState === 4) { - MutationHandler.pause(); - - // this reference to responseXML with MO off is enough to ensure the browser - // bug is not triggered - var nop = req.responseXML; - - MutationHandler.resume(); - } - // Listen here as well, as DOM changes might happen on other listeners // of readyState = 4 (complete), and we want to make sure we've // started the addEvent() if so. Only listen if the status is non-zero, @@ -1702,8 +1683,6 @@ * Container for AutoXHR plugin Closure specific state configuration data * * @property {string[]} spaBackendResources Default resources to count as Back-End during a SPA nav - * @property {boolean} ie1011fix If true, the MutationObserver will be paused on - * IE10/11 to avoid delayed processing, see {@link ProxyXHRImplementation#addListener} for more info * @property {FilterObject[]} filters Array of {@link FilterObject} that is used to apply filters on XHR Requests * @property {boolean} initialized Set to true after the first run of * @property {string[]} addedVars Vars added to the next beacon only @@ -1711,7 +1690,6 @@ */ impl = { spaBackEndResources: SPA_RESOURCES_BACK_END, - ie1011fix: true, excludeFilters: [], initialized: false, addedVars: [], @@ -1788,8 +1766,6 @@ * @param {boolean} [config.instrument_xhr] Whether or not to instrument XHR * @param {string[]} [config.AutoXHR.spaBackEndResources] Default resources to count as * Back-End during a SPA nav - * @param {boolean} [config.AutoXHR.ie1011fix] If true, the MutationObserver will be paused on - * IE10/11 to avoid delayed processing * @param {boolean} [config.AutoXHR.alwaysSendXhr] Whether or not to send XHR * beacons for every XHR. * @@ -1808,7 +1784,7 @@ a = BOOMR.window.document.createElement("A"); // gather config and config overrides - BOOMR.utils.pluginConfig(impl, config, "AutoXHR", ["spaBackEndResources", "ie1011fix"]); + BOOMR.utils.pluginConfig(impl, config, "AutoXHR", ["spaBackEndResources"]); BOOMR.instrumentXHR = instrumentXHR; BOOMR.uninstrumentXHR = uninstrumentXHR; diff --git a/tests/boomerang-test-framework.js b/tests/boomerang-test-framework.js index 72095a14b..bfb454975 100644 --- a/tests/boomerang-test-framework.js +++ b/tests/boomerang-test-framework.js @@ -407,7 +407,11 @@ }; t.isMutationObserverSupported = function() { - return (window.MutationObserver && typeof window.MutationObserver === "function"); + var w = window; + // Use the same logic as BOOM.utils.isMutationObserverSupported. + // Boomerang will not use MO in IE 11 due to browser bugs + var ie11 = (w && w.navigator && w.navigator.userAgent && w.navigator.userAgent.match(/Trident.*rv[ :]*11\./)); + return (!ie11 && w && w.MutationObserver && typeof w.MutationObserver === "function"); }; t.validateBeaconWasXhr = function(done) { diff --git a/tests/page-templates/05-angular/03-ng-app.js b/tests/page-templates/05-angular/03-ng-app.js index 717ed87e6..b2497ff2e 100644 --- a/tests/page-templates/05-angular/03-ng-app.js +++ b/tests/page-templates/05-angular/03-ng-app.js @@ -18,26 +18,26 @@ describe("e2e/05-angular/03-ng-app", function() { }); it("Should take as long as the longest img load (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { t.validateBeaconWasSentAfter(0, "img.jpg", 100, 3000, 30000, true); } }); it("Should not have a load time (if MutationObserver is supported but NavigationTiming is not)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { var b = tf.lastBeacon(); assert.equal(b.t_done, undefined); } }); it("Should take as long as the XHRs (if MutationObserver is not supported but NavigationTiming is)", function() { - if (typeof window.MutationObserver === "undefined" && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (!t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { t.validateBeaconWasSentAfter(0, "widgets.json", 100, 0, 30000, true); } }); it("Shouldn't have a load time (if MutationObserver and NavigationTiming are not supported)", function() { - if (typeof window.MutationObserver === "undefined" && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { + if (!t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { var b = tf.lastBeacon(); assert.equal(b.t_done, undefined); assert.equal(b["rt.start"], "none"); diff --git a/tests/page-templates/05-angular/102-ui-router.js b/tests/page-templates/05-angular/102-ui-router.js index fe7a113c2..be6b43df8 100644 --- a/tests/page-templates/05-angular/102-ui-router.js +++ b/tests/page-templates/05-angular/102-ui-router.js @@ -33,26 +33,26 @@ describe("e2e/05-angular/102-ui-router", function() { }); it("Should take as long as the longest img load (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { t.validateBeaconWasSentAfter(0, "img.jpg&id=home", 500, 3000, 30000, 0); } }); it("Should not have a load time (if MutationObserver is supported but NavigationTiming is not)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { var b = tf.beacons[0]; assert.equal(b.t_done, undefined); } }); it("Should take as long as the XHRs (if MutationObserver is not supported but NavigationTiming is)", function() { - if (typeof window.MutationObserver === "undefined" && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (!t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { t.validateBeaconWasSentAfter(0, "widgets.json", 500, 0, 30000, false); } }); it("Shouldn't have a load time (if MutationObserver and NavigationTiming are not supported)", function() { - if (typeof window.MutationObserver === "undefined" && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { + if (!t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { var b = tf.beacons[0]; assert.equal(b.t_done, undefined); assert.equal(b["rt.start"], "none"); @@ -68,7 +68,7 @@ describe("e2e/05-angular/102-ui-router", function() { }); it("Should have sent the second beacon with a timestamp of at least 1 second (if MutationObserver is supported)", function() { - if (window.MutationObserver) { + if (t.isMutationObserverSupported()) { // because of the widget IMG delaying 1 second var b = tf.beacons[1]; assert.operator(b.t_done, ">=", 1000); @@ -76,7 +76,7 @@ describe("e2e/05-angular/102-ui-router", function() { }); it("Should have sent the second beacon with a timestamp of at least 1 millisecond (if MutationObserver is not supported)", function() { - if (typeof window.MutationObserver === "undefined") { + if (!t.isMutationObserverSupported()) { // because of the widget IMG delaying 1 second but we couldn't track it because no MO support var b = tf.beacons[1]; assert.operator(b.t_done, ">=", 0); @@ -92,14 +92,14 @@ describe("e2e/05-angular/102-ui-router", function() { }); it("Should have sent the third with a timestamp of at least 3 seconds (if MutationObserver is supported)", function() { - if (window.MutationObserver) { + if (t.isMutationObserverSupported()) { var b = tf.beacons[2]; assert.operator(b.t_done, ">=", 3000); } }); it("Should have sent the third with a timestamp of under 1 second (if MutationObserver is not supported)", function() { - if (!window.MutationObserver) { + if (!t.isMutationObserverSupported()) { var b = tf.beacons[2]; assert.operator(b.t_done, "<=", 1000); } diff --git a/tests/page-templates/05-angular/108-location-change-only.js b/tests/page-templates/05-angular/108-location-change-only.js index 775a14331..5db71710b 100644 --- a/tests/page-templates/05-angular/108-location-change-only.js +++ b/tests/page-templates/05-angular/108-location-change-only.js @@ -55,27 +55,27 @@ describe("e2e/05-angular/108-location-change-only", function() { }); it("Should have a load time (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var b = tf.beacons[0]; assert.isDefined(b.t_done); } }); it("Should not have a load time (if MutationObserver is supported but NavigationTiming is not)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { var b = tf.beacons[0]; assert.equal(b.t_done, undefined); } }); it("Should take as long as the XHRs (if MutationObserver is not supported but NavigationTiming is)", function() { - if (typeof window.MutationObserver === "undefined" && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (!t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { t.validateBeaconWasSentAfter(0, "widgets.json", 500, 0, 30000, false); } }); it("Shouldn't have a load time (if MutationObserver and NavigationTiming are not supported)", function() { - if (typeof window.MutationObserver === "undefined" && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { + if (!t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { var b = tf.beacons[0]; assert.equal(b.t_done, undefined); assert.equal(b["rt.start"], "none"); @@ -83,7 +83,7 @@ describe("e2e/05-angular/108-location-change-only", function() { }); it("Should have a t_resp of the root page (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[0]; assert.equal(b.t_resp, pt.responseStart - pt.navigationStart); @@ -91,7 +91,7 @@ describe("e2e/05-angular/108-location-change-only", function() { }); it("Should have a t_page of total - t_resp (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[0]; assert.equal(b.t_page, b.t_done - b.t_resp); @@ -107,7 +107,7 @@ describe("e2e/05-angular/108-location-change-only", function() { }); it("Should have sent the second beacon with a timestamp of ~0 seconds (if MutationObserver is supported)", function() { - if (window.MutationObserver) { + if (t.isMutationObserverSupported()) { var b = tf.beacons[1]; assert.closeTo(b.t_done, 0, 50); } @@ -122,7 +122,7 @@ describe("e2e/05-angular/108-location-change-only", function() { }); it("Should have sent the third with a timestamp of at around 0 seconds (if MutationObserver is supported)", function() { - if (window.MutationObserver) { + if (t.isMutationObserverSupported()) { var b = tf.beacons[2]; assert.closeTo(b.t_done, 0, 50); } diff --git a/tests/page-templates/05-angular/109-multiple-iframes.html b/tests/page-templates/05-angular/109-multiple-iframes.html index 80e5a8a5d..8686d1d2a 100644 --- a/tests/page-templates/05-angular/109-multiple-iframes.html +++ b/tests/page-templates/05-angular/109-multiple-iframes.html @@ -2,8 +2,8 @@ <%= boomerangScript %> - - + + + + <%= footer %> diff --git a/tests/page-templates/05-angular/113-late-locationchangestart.js b/tests/page-templates/05-angular/113-late-locationchangestart.js index 2caf142aa..cf43d6196 100644 --- a/tests/page-templates/05-angular/113-late-locationchangestart.js +++ b/tests/page-templates/05-angular/113-late-locationchangestart.js @@ -33,26 +33,26 @@ describe("e2e/05-angular/113-late-locationchangestart", function() { }); it("Should take as long as the longest img load (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { t.validateBeaconWasSentAfter(0, "img.jpg&id=home", 500, 3000, 30000, 0); } }); it("Should not have a load time (if MutationObserver is supported but NavigationTiming is not)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { var b = tf.beacons[0]; assert.equal(b.t_done, undefined); } }); it("Should take as long as the XHRs (if MutationObserver is not supported but NavigationTiming is)", function() { - if (typeof window.MutationObserver === "undefined" && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (!t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { t.validateBeaconWasSentAfter(0, "widgets.json", 500, 0, 30000, false); } }); it("Shouldn't have a load time (if MutationObserver and NavigationTiming are not supported)", function() { - if (typeof window.MutationObserver === "undefined" && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { + if (!t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { var b = tf.beacons[0]; assert.equal(b.t_done, undefined); assert.equal(b["rt.start"], "none"); @@ -68,7 +68,7 @@ describe("e2e/05-angular/113-late-locationchangestart", function() { }); it("Should have sent the second beacon with a timestamp of at least 1 second (if MutationObserver is supported)", function() { - if (window.MutationObserver) { + if (t.isMutationObserverSupported()) { // because of the widget IMG delaying 1 second var b = tf.beacons[1]; assert.operator(b.t_done, ">=", 1000); @@ -76,7 +76,7 @@ describe("e2e/05-angular/113-late-locationchangestart", function() { }); it("Should have sent the second beacon with a timestamp of at least 1 millisecond (if MutationObserver is not supported)", function() { - if (typeof window.MutationObserver === "undefined") { + if (!t.isMutationObserverSupported()) { // because of the widget IMG delaying 1 second but we couldn't track it because no MO support var b = tf.beacons[1]; assert.operator(b.t_done, ">=", 0); @@ -92,14 +92,14 @@ describe("e2e/05-angular/113-late-locationchangestart", function() { }); it("Should have sent the third with a timestamp of at least 3 seconds (if MutationObserver is supported)", function() { - if (window.MutationObserver) { + if (t.isMutationObserverSupported()) { var b = tf.beacons[2]; assert.operator(b.t_done, ">=", 3000); } }); it("Should have sent the third with a timestamp of under 1 second (if MutationObserver is not supported)", function() { - if (!window.MutationObserver) { + if (!t.isMutationObserverSupported()) { var b = tf.beacons[2]; assert.operator(b.t_done, "<=", 1000); } diff --git a/tests/page-templates/05-angular/114-route-change-abld.js b/tests/page-templates/05-angular/114-route-change-abld.js index 54ddcbfd5..c1e12636b 100644 --- a/tests/page-templates/05-angular/114-route-change-abld.js +++ b/tests/page-templates/05-angular/114-route-change-abld.js @@ -65,13 +65,13 @@ describe("e2e/05-angular/114-route-change-abld", function() { }); it("Should have sent the first beacon with a load time of when the abort happened (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { assert.closeTo(tf.beacons[0].t_done, window.nav1time - BOOMR.plugins.RT.navigationStart(), 100); } }); it("Should have sent the first beacon without a load time (if MutationObserver is supported but NavigationTiming is not)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { var b = tf.beacons[0]; assert.equal(b.t_done, undefined); assert.equal(b["rt.start"], "none"); @@ -79,7 +79,7 @@ describe("e2e/05-angular/114-route-change-abld", function() { }); it("Should have sent the first beacon with a t_resp of the root page (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[0]; assert.equal(b.t_resp, pt.responseStart - pt.navigationStart); @@ -87,7 +87,7 @@ describe("e2e/05-angular/114-route-change-abld", function() { }); it("Should have sent the first beacon with a t_page of total - t_resp (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[0]; assert.equal(b.t_page, b.t_done - b.t_resp); @@ -95,7 +95,7 @@ describe("e2e/05-angular/114-route-change-abld", function() { }); it("Should have sent the first beacon with rt.quit and rt.abld (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var b = tf.beacons[0]; assert.equal(b["rt.quit"], ""); assert.equal(b["rt.abld"], ""); @@ -137,14 +137,14 @@ describe("e2e/05-angular/114-route-change-abld", function() { }); it("Should have sent the second beacon with a timestamp of when the abort happened (if MutationObserver is supported)", function() { - if (window.MutationObserver) { + if (t.isMutationObserverSupported()) { var b = tf.beacons[1]; assert.closeTo(b.t_done, window.nav2time - b["rt.tstart"], 100); } }); it("Should have sent the second beacon with a timestamp of at least 1 millisecond (if MutationObserver is not supported)", function() { - if (typeof window.MutationObserver === "undefined") { + if (!t.isMutationObserverSupported()) { // because of the widget IMG delaying 1 second but we couldn't track it because no MO support var b = tf.beacons[1]; assert.operator(b.t_done, ">=", 0); @@ -152,7 +152,7 @@ describe("e2e/05-angular/114-route-change-abld", function() { }); it("Should have sent the second beacon with a t_resp value (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[1]; @@ -161,7 +161,7 @@ describe("e2e/05-angular/114-route-change-abld", function() { }); it("Should have sent the second beacon with a t_page of total - t_resp (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[1]; assert.equal(b.t_page, b.t_done - b.t_resp); @@ -169,7 +169,7 @@ describe("e2e/05-angular/114-route-change-abld", function() { }); it("Should have sent the second beacon with rt.quit and rt.abld (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var b = tf.beacons[1]; assert.equal(b["rt.quit"], ""); assert.equal(b["rt.abld"], ""); @@ -211,21 +211,21 @@ describe("e2e/05-angular/114-route-change-abld", function() { }); it("Should have sent the third with a timestamp of at least 3 seconds (if MutationObserver is supported)", function() { - if (window.MutationObserver) { + if (t.isMutationObserverSupported()) { var b = tf.beacons[2]; assert.operator(b.t_done, ">=", 3000); } }); it("Should have sent the third with a timestamp of under 1 second (if MutationObserver is not supported)", function() { - if (!window.MutationObserver) { + if (!t.isMutationObserverSupported()) { var b = tf.beacons[2]; assert.operator(b.t_done, "<=", 1000); } }); it("Should have sent the third beacon with a t_resp value (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[2]; @@ -234,7 +234,7 @@ describe("e2e/05-angular/114-route-change-abld", function() { }); it("Should have sent the third beacon with a t_page of total - t_resp (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[2]; assert.equal(b.t_page, b.t_done - b.t_resp); diff --git a/tests/page-templates/05-angular/115-no-url-change.js b/tests/page-templates/05-angular/115-no-url-change.js index 13dd30384..3f18c792e 100644 --- a/tests/page-templates/05-angular/115-no-url-change.js +++ b/tests/page-templates/05-angular/115-no-url-change.js @@ -38,26 +38,26 @@ describe("e2e/05-angular/115-no-url-change", function() { }); it("Should take as long as the longest img load (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { t.validateBeaconWasSentAfter(0, "img.jpg&id=home", 500, 3000, 30000, 0); } }); it("Should not have a load time (if MutationObserver is supported but NavigationTiming is not)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { var b = tf.beacons[0]; assert.equal(b.t_done, undefined); } }); it("Should take as long as the XHRs (if MutationObserver is not supported but NavigationTiming is)", function() { - if (typeof window.MutationObserver === "undefined" && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (!t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { t.validateBeaconWasSentAfter(0, "widgets.json", 500, 0, 30000, false); } }); it("Shouldn't have a load time (if MutationObserver and NavigationTiming are not supported)", function() { - if (typeof window.MutationObserver === "undefined" && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { + if (!t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { var b = tf.beacons[0]; assert.equal(b.t_done, undefined); assert.equal(b["rt.start"], "none"); @@ -73,7 +73,7 @@ describe("e2e/05-angular/115-no-url-change", function() { }); it("Should have sent the second beacon with a timestamp of at least 1 second (if MutationObserver is supported)", function() { - if (window.MutationObserver) { + if (t.isMutationObserverSupported()) { // because of the widget IMG delaying 1 second var b = tf.beacons[1]; assert.operator(b.t_done, ">=", 1000); @@ -81,7 +81,7 @@ describe("e2e/05-angular/115-no-url-change", function() { }); it("Should have sent the second beacon with a timestamp of at least 1 millisecond (if MutationObserver is not supported)", function() { - if (typeof window.MutationObserver === "undefined") { + if (!t.isMutationObserverSupported()) { // because of the widget IMG delaying 1 second but we couldn't track it because no MO support var b = tf.beacons[1]; assert.operator(b.t_done, ">=", 0); @@ -97,14 +97,14 @@ describe("e2e/05-angular/115-no-url-change", function() { }); it("Should have sent the third with a timestamp of at least 3 seconds (if MutationObserver is supported)", function() { - if (window.MutationObserver) { + if (t.isMutationObserverSupported()) { var b = tf.beacons[2]; assert.operator(b.t_done, ">=", 3000); } }); it("Should have sent the third with a timestamp of under 1 second (if MutationObserver is not supported)", function() { - if (!window.MutationObserver) { + if (!t.isMutationObserverSupported()) { var b = tf.beacons[2]; assert.operator(b.t_done, "<=", 1000); } diff --git a/tests/page-templates/05-angular/117-route-change-markcomplete.js b/tests/page-templates/05-angular/117-route-change-markcomplete.js index 3d1200cc4..056315e99 100644 --- a/tests/page-templates/05-angular/117-route-change-markcomplete.js +++ b/tests/page-templates/05-angular/117-route-change-markcomplete.js @@ -65,13 +65,13 @@ describe("e2e/05-angular/117-route-change-markcomplete", function() { }); it("Should have sent the first beacon with a load time of when the completion happened (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { assert.closeTo(tf.beacons[0].t_done, window.nav1time - BOOMR.plugins.RT.navigationStart(), 100); } }); it("Should have sent the first beacon without a load time (if MutationObserver is supported but NavigationTiming is not)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() === "undefined") { var b = tf.beacons[0]; assert.equal(b.t_done, undefined); assert.equal(b["rt.start"], "none"); @@ -79,7 +79,7 @@ describe("e2e/05-angular/117-route-change-markcomplete", function() { }); it("Should have sent the first beacon with a t_resp of the root page (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[0]; assert.equal(b.t_resp, pt.responseStart - pt.navigationStart); @@ -87,7 +87,7 @@ describe("e2e/05-angular/117-route-change-markcomplete", function() { }); it("Should have sent the first beacon with a t_page of total - t_resp (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[0]; assert.equal(b.t_page, b.t_done - b.t_resp); @@ -95,7 +95,7 @@ describe("e2e/05-angular/117-route-change-markcomplete", function() { }); it("Should have sent the first beacon without rt.quit or rt.abld (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var b = tf.beacons[0]; assert.isUndefined(b["rt.quit"]); assert.isUndefined(b["rt.abld"]); @@ -103,14 +103,14 @@ describe("e2e/05-angular/117-route-change-markcomplete", function() { }); it("Should have sent the first beacon with spa.forced (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var b = tf.beacons[0]; assert.equal(b["spa.forced"], "1"); } }); it("Should have sent the first beacon with spa.waiting (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var b = tf.beacons[0]; assert.operator(parseInt(b["spa.forced"], 10), ">=", 1); } @@ -151,14 +151,14 @@ describe("e2e/05-angular/117-route-change-markcomplete", function() { }); it("Should have sent the second beacon with a timestamp of when the completion happened (if MutationObserver is supported)", function() { - if (window.MutationObserver) { + if (t.isMutationObserverSupported()) { var b = tf.beacons[1]; assert.closeTo(b.t_done, window.nav2time - b["rt.tstart"], 100); } }); it("Should have sent the second beacon with a timestamp of around 1 second (if MutationObserver is not supported)", function() { - if (typeof window.MutationObserver === "undefined") { + if (!t.isMutationObserverSupported()) { // because of the widget IMG delaying 1 second but we couldn't track it because no MO support var b = tf.beacons[1]; assert.closeTo(parseInt(b.t_done, 10), 1000, 50); @@ -166,7 +166,7 @@ describe("e2e/05-angular/117-route-change-markcomplete", function() { }); it("Should have sent the second beacon with a t_resp value (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[1]; @@ -175,7 +175,7 @@ describe("e2e/05-angular/117-route-change-markcomplete", function() { }); it("Should have sent the second beacon with a t_page of total - t_resp (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[1]; assert.equal(b.t_page, b.t_done - b.t_resp); @@ -183,7 +183,7 @@ describe("e2e/05-angular/117-route-change-markcomplete", function() { }); it("Should have sent the second beacon without rt.quit and rt.abld (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var b = tf.beacons[1]; assert.isUndefined(b["rt.quit"]); assert.isUndefined(b["rt.abld"]); @@ -191,14 +191,14 @@ describe("e2e/05-angular/117-route-change-markcomplete", function() { }); it("Should have sent the second beacon with spa.forced (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var b = tf.beacons[1]; assert.equal(b["spa.forced"], "1"); } }); it("Should have sent the second beacon with spa.waiting (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var b = tf.beacons[1]; assert.operator(parseInt(b["spa.forced"], 10), ">=", 1); } @@ -239,21 +239,21 @@ describe("e2e/05-angular/117-route-change-markcomplete", function() { }); it("Should have sent the third with a timestamp of at least 3 seconds (if MutationObserver is supported)", function() { - if (window.MutationObserver) { + if (t.isMutationObserverSupported()) { var b = tf.beacons[2]; assert.operator(parseInt(b.t_done, 10), ">=", 3000); } }); it("Should have sent the third with a timestamp of under 1 second (if MutationObserver is not supported)", function() { - if (!window.MutationObserver) { + if (!t.isMutationObserverSupported()) { var b = tf.beacons[2]; assert.operator(parseInt(b.t_done, 10), "<=", 1000); } }); it("Should have sent the third beacon with a t_resp value (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[2]; @@ -262,7 +262,7 @@ describe("e2e/05-angular/117-route-change-markcomplete", function() { }); it("Should have sent the third beacon with a t_page of total - t_resp (if MutationObserver and NavigationTiming are supported)", function() { - if (window.MutationObserver && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { + if (t.isMutationObserverSupported() && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var pt = window.performance.timing; var b = tf.beacons[2]; assert.equal(b.t_page, b.t_done - b.t_resp); diff --git a/tests/page-templates/07-autoxhr/01-img-src-change.html b/tests/page-templates/07-autoxhr/01-img-src-change.html index 06dcc8470..e90086cb6 100644 --- a/tests/page-templates/07-autoxhr/01-img-src-change.html +++ b/tests/page-templates/07-autoxhr/01-img-src-change.html @@ -4,7 +4,7 @@ <%= boomerangScript %>