From 6fd3713a8dc7207bbd3515a399886f338260f424 Mon Sep 17 00:00:00 2001 From: Nic Jansma Date: Wed, 24 Jan 2018 11:06:38 -0500 Subject: [PATCH] Test fixes for modern browsers --- Gruntfile.js | 2 +- boomerang.js | 3 +- bower.json | 1 + plugins/auto-xhr.js | 17 ++- plugins/navtiming.js | 10 +- tests/assets/blank.js | 0 tests/boomerang-test-framework.js | 69 +++++++-- tests/e2e/e2e-debug.js | 16 ++- tests/e2e/e2e.js | 27 ++-- tests/karma.config.js | 11 +- .../00-basic/10-method-queue.html | 21 +-- .../03-load-order/00-before-page-load.js | 4 +- .../03-load-order/01-after-page-load.js | 4 +- .../02-after-page-load-tag-manager.js | 4 +- tests/page-templates/06-bugs/111096-2.html | 3 + tests/page-templates/07-autoxhr/02-onclick.js | 24 +++- .../07-autoxhr/03-xhrs-overlapping.html | 16 +-- .../07-autoxhr/03-xhrs-overlapping.js | 134 +++++++++++++----- .../05-xhr-before-onload-alwayssendxhr.js | 24 +++- .../07-autoxhr/22-xhrs-duplicate-no-tao.html | 13 +- .../07-autoxhr/23-xhrs-duplicate-tao.html | 3 +- .../07-autoxhr/24-xhrs-duplicate-no-tao.html | 3 +- .../07-autoxhr/25-xhrs-duplicate-tao.html | 3 +- .../09-backbone/26-page-params-spa-nav.html | 6 +- .../page-templates/09-backbone/support/app.js | 2 + .../09-backbone/support/home.html | 8 +- .../11-restiming/00-clear-onbeacon.js | 11 +- .../11-restiming/04-resource-sizes.html | 9 +- .../page-templates/11-restiming/06-iframes.js | 7 +- .../11-restiming/06-svg-image.html | 2 +- .../11-restiming/06-type-filter.html | 3 +- .../11-restiming/08-cross-origin.js | 7 +- .../support/07-script-attrs.linkasync.js | 0 .../25-autorun-false-onload-happens.js | 1 - .../33-events-xhr-wrap-xhret-before.js | 4 +- .../17-memory/00-dom-counts.html | 2 +- .../page-templates/19-navtiming/00-onload.js | 46 +++++- tests/server/app.js | 14 +- .../autoxhr/00-xhrs-duplicate.js | 25 ++-- tests/test-templates/common.js | 12 ++ tests/test-templates/spa/00-simple.js | 6 +- tests/test-templates/spa/04-route-change.js | 29 ++-- tests/unit/04-plugins-restiming.js | 5 + 43 files changed, 437 insertions(+), 174 deletions(-) create mode 100644 tests/assets/blank.js create mode 100644 tests/page-templates/11-restiming/support/07-script-attrs.linkasync.js diff --git a/Gruntfile.js b/Gruntfile.js index 99462ee16..baa283197 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -257,7 +257,7 @@ module.exports = function() { { // Send beacons to null pattern: /beacon_url: .*/, - replacement: "beacon_url: \"/blackhole\"," + replacement: "beacon_url: \"/beacon\"," } ] } diff --git a/boomerang.js b/boomerang.js index 6829fdbd8..f019814d0 100644 --- a/boomerang.js +++ b/boomerang.js @@ -1962,7 +1962,8 @@ BOOMR_check_doc_domain(); }; if (w.requestIdleCallback) { - w.requestIdleCallback(cb); + // set a timeout since rIC doesn't get called reliably in chrome headless + w.requestIdleCallback(cb, {timeout: 1000}); } else if (w.setImmediate) { w.setImmediate(cb); diff --git a/bower.json b/bower.json index 129044534..9f28aa800 100644 --- a/bower.json +++ b/bower.json @@ -44,6 +44,7 @@ "lodash": "~3.0.0", "mocha": "~3.4.2", "resourcetiming-compression": "^0.3.3", + "usertiming": "~0.1.8", "usertiming-compression": "~0.1.4" }, "resolutions": { diff --git a/plugins/auto-xhr.js b/plugins/auto-xhr.js index b7cce54f6..a93d7224b 100644 --- a/plugins/auto-xhr.js +++ b/plugins/auto-xhr.js @@ -678,11 +678,12 @@ /** * Called once the resource can be sent - * @param markEnd Sets loadEventEnd once the function is run + * @param {boolean} [markEnd] Sets loadEventEnd once the function is run + * @param {number} [endTimestamp] End timestamp */ - var sendResponseEnd = function(markEnd) { + var sendResponseEnd = function(markEnd, endTimestamp) { if (markEnd) { - resource.timing.loadEventEnd = BOOMR.now(); + resource.timing.loadEventEnd = endTimestamp || BOOMR.now(); } // send any queued beacons first @@ -736,7 +737,12 @@ // don't wait for onload if this was an aborted SPA navigation if ((!ev || !ev.aborted) && d && d.readyState && d.readyState !== "complete") { BOOMR.window.addEventListener("load", function() { - sendResponseEnd(true); + var loadTimestamp = BOOMR.now(); + + // run after the 'load' event handlers so loadEventEnd is captured + BOOMR.setImmediate(function() { + sendResponseEnd(true, loadTimestamp); + }); }); return; @@ -1023,7 +1029,7 @@ // if the attribute change affected the src/currentSrc attributes we want to know that // as that means we need to fetch a new Resource from the server - if (node._bmr && node._bmr.res && node._bmr.end[node._bmr.res]) { + if (node._bmr && typeof node._bmr.res === "number" && node._bmr.end[node._bmr.res]) { exisitingNodeSrcUrlChanged = true; } @@ -1110,6 +1116,7 @@ // update _bmr with details about this resource node._bmr.res = resourceNum; node._bmr.idx = index; + delete node._bmr.end[resourceNum]; node.addEventListener("load", function(ev) { self.load_cb(ev, resourceNum); }); node.addEventListener("error", function(ev) { self.load_cb(ev, resourceNum); }); diff --git a/plugins/navtiming.js b/plugins/navtiming.js index 99ed68b16..9c77aef84 100644 --- a/plugins/navtiming.js +++ b/plugins/navtiming.js @@ -310,12 +310,10 @@ data.nt_ssl_st = pt.secureConnectionStart; } - // XXX Inconsistency warning. msFirstPaint is in milliseconds while Chrome's firstPaintTime is in seconds.microseconds. - // The server needs to deal with this. - - if (pt.msFirstPaint) { + if (p.timing && p.timing.msFirstPaint) { // msFirstPaint is IE9+ http://msdn.microsoft.com/en-us/library/ff974719 - data.nt_first_paint = pt.msFirstPaint; + // and is in Unix Epoch format + data.nt_first_paint = p.timing.msFirstPaint; } if (pt.workerStart) { @@ -347,7 +345,7 @@ } for (k in data) { - if (data.hasOwnProperty(k) && !data[k]) { + if (data.hasOwnProperty(k) && data[k] === undefined) { delete data[k]; } } diff --git a/tests/assets/blank.js b/tests/assets/blank.js new file mode 100644 index 000000000..e69de29bb diff --git a/tests/boomerang-test-framework.js b/tests/boomerang-test-framework.js index 48fa517f9..0c8e8a843 100644 --- a/tests/boomerang-test-framework.js +++ b/tests/boomerang-test-framework.js @@ -19,6 +19,7 @@ fired_onbeacon: false, fired_before_unload: false, beacons: [], + sendBeacons: [], page_ready: function() { this.fired_page_ready = true; }, @@ -56,6 +57,24 @@ return true; } }; + + (function() { + var savedSendBeacon; + if (window.navigator && typeof window.navigator.sendBeacon === "function") { + savedSendBeacon = window.navigator.sendBeacon; + window.navigator.sendBeacon = function(url, data) { + var result = savedSendBeacon.apply(window.navigator, arguments); + if (result) { + var reader = new FileReader(); + reader.addEventListener("loadend", function() { + BOOMR.plugins.TestFramework.sendBeacons.push(reader.result); + }); + reader.readAsText(data); + } + return result; + }; + } + })(); })(window); // @@ -81,7 +100,7 @@ // // Constants // - t.BEACON_URL = "/blackhole"; + t.BEACON_URL = "/beacon"; t.MAX_RESOURCE_WAIT = 500; // @@ -294,9 +313,9 @@ t.isUserTimingSupported = function() { // don't check for PerformanceMark or PerformanceMeasure, they aren't polyfilled in usertiming.js return (window.performance && - typeof window.performance.getEntriesByType === "function" && - typeof window.performance.mark === "function" && - typeof window.performance.measure === "function"); + typeof window.performance.getEntriesByType === "function" && + typeof window.performance.mark === "function" && + typeof window.performance.measure === "function"); }; t.isNetworkAPISupported = function() { @@ -365,10 +384,12 @@ }; t.clearCookies = function() { + var date = new Date(); + date.setTime(date.getTime() - (24 * 60 * 60 * 1000)); var cookies = document.cookie.split(";"); for (var i = 0; i < cookies.length; i++) { - var name = cookies[i].split("=")[0]; - document.cookie = [name + "=", "expires" + new Date(), "path=/", "domain=" + location.hostname].join("; "); + var name = cookies[i].split("=")[0].trim(); + document.cookie = [name + "=", "expires=" + date.toGMTString(), "path=/", "domain=" + location.hostname].join("; "); } }; @@ -724,9 +745,12 @@ var objName = objs[i]; var subObj = window.performance[objName]; - copy[objName] = {}; - if (subObj) { + if (typeof subObj === "function") { + copy[objName] = window.performance[objName]; + continue; + } + copy[objName] = {}; for (var subObjAttr in subObj) { copy[objName][subObjAttr] = subObj[subObjAttr]; } @@ -769,4 +793,33 @@ // This only works if the test framework is loaded before boomerang window.BOOMR_LOGN_always = false; + /*eslint-disable no-extend-native*/ + // Polyfill via https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind + if (!Function.prototype.bind) { + Function.prototype.bind = function(oThis) { + if (typeof this !== "function") { + // closest thing possible to the ECMAScript 5 + // internal IsCallable function + throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function() {}, + fBound = function() { + return fToBind.apply(this instanceof fNOP ? this : oThis, + aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + if (this.prototype) { + // Function.prototype doesn't have a prototype property + fNOP.prototype = this.prototype; + } + fBound.prototype = new fNOP(); + + return fBound; + }; + } + /*eslint-enable no-extend-native*/ + }(window)); diff --git a/tests/e2e/e2e-debug.js b/tests/e2e/e2e-debug.js index 2ca16e829..035d90f37 100644 --- a/tests/e2e/e2e-debug.js +++ b/tests/e2e/e2e-debug.js @@ -4,7 +4,6 @@ // // Imports // -var fs = require("fs"); var chai = require("chai"); var assert = chai.assert; var path = require("path"); @@ -20,9 +19,19 @@ var ports = require(testsFile).ports; function run(testPath, file) { describe(testPath, function() { var fileName = file + ".html"; + it("Should pass " + testPath + "/" + fileName, function(done) { var logCount = 0; + if (typeof browser.waitForAngularEnabled === "function") { + browser.waitForAngularEnabled(false); + } + + console.log( + "Navigating to", + "http://" + servers.main + ":" + ports.main + "/pages/" + testPath + "/" + fileName + ); + browser.driver.get("http://" + servers.main + ":" + ports.main + "/pages/" + testPath + "/" + fileName); setInterval(function() { @@ -42,9 +51,10 @@ function run(testPath, file) { return browser.driver.isElementPresent(by.css("#BOOMR_test_complete")); }); - browser.driver.executeScript("return BOOMR_test.isComplete()").then(function(complete){ + browser.driver.executeScript("return BOOMR_test.isComplete()").then(function(complete) { assert.equal(complete, true, "BOOMR_test.isComplete()"); - browser.driver.executeScript("return BOOMR_test.getTestFailureMessages()").then(function(testFailures){ + + browser.driver.executeScript("return BOOMR_test.getTestFailureMessages()").then(function(testFailures) { if (testFailures.length > 0) { throw new Error(testFailures); } diff --git a/tests/e2e/e2e.js b/tests/e2e/e2e.js index e92f3f728..a01438236 100644 --- a/tests/e2e/e2e.js +++ b/tests/e2e/e2e.js @@ -6,29 +6,40 @@ // var chai = require("chai"); var assert = chai.assert; +var path = require("path"); + +var testsFile = path.join(__dirname, "e2e.json"); +var tests = require(testsFile).tests; +var servers = require(testsFile).server; +var ports = require(testsFile).ports; -var tests = require("./e2e.json").tests; -var servers = require("./e2e.json").server; -var ports = require("./e2e.json").ports; var disabledTests = require("./e2e.disabled.json"); // // Functions // -function run(path, file) { - describe(path, function() { +function run(testPath, file) { + describe(testPath, function() { var fileName = file + ".html"; - it("Should pass " + path + "/" + fileName, function(done) { + it("Should pass " + testPath + "/" + fileName, function(done) { + + if (typeof browser.waitForAngularEnabled === "function") { + browser.waitForAngularEnabled(false); + } - browser.driver.get("http://" + servers.main + ":" + ports.main + "/pages/" + path + "/" + fileName); + console.log( + "Navigating to", + "http://" + servers.main + ":" + ports.main + "/pages/" + testPath + "/" + fileName + ); + + browser.driver.get("http://" + servers.main + ":" + ports.main + "/pages/" + testPath + "/" + fileName); browser.driver.wait(function() { return browser.driver.isElementPresent(by.css("#BOOMR_test_complete")); }); browser.driver.executeScript("return BOOMR_test.isComplete()").then(function(complete) { - assert.equal(complete, true, "BOOMR_test.isComplete()"); browser.driver.executeScript("return BOOMR_test.getTestFailureMessages()").then(function(testFailures) { diff --git a/tests/karma.config.js b/tests/karma.config.js index 20a1dbecc..1496775d0 100644 --- a/tests/karma.config.js +++ b/tests/karma.config.js @@ -15,9 +15,18 @@ module.exports = function(config) { plugins: [ "karma-coverage", "karma-mocha", + + // reporters "karma-tap-reporter", "karma-mocha-reporter", - "karma-phantomjs-launcher" + + // launchers + "karma-chrome-launcher", + "karma-firefox-launcher", + "karma-ie-launcher", + "karma-opera-launcher", + "karma-phantomjs-launcher", + "karma-safari-launcher" ], browsers: ["PhantomJS"], diff --git a/tests/page-templates/00-basic/10-method-queue.html b/tests/page-templates/00-basic/10-method-queue.html index c5feb3ae5..ca2e9e979 100644 --- a/tests/page-templates/00-basic/10-method-queue.html +++ b/tests/page-templates/00-basic/10-method-queue.html @@ -1,21 +1,22 @@ <%= header %> -<%= boomerangSnippet %> - +<%= boomerangScript %> + + <%= footer %> diff --git a/tests/page-templates/03-load-order/00-before-page-load.js b/tests/page-templates/03-load-order/00-before-page-load.js index 61af803c0..81b992871 100644 --- a/tests/page-templates/03-load-order/00-before-page-load.js +++ b/tests/page-templates/03-load-order/00-before-page-load.js @@ -49,11 +49,11 @@ describe("e2e/03-load-order/00-before-page-load", function() { } }); - it("Should have a end timestamp sometime after the NavigationTiming's loadEventStart timestamp and before now (if NavTiming supported)", function() { + it("Should have a end timestamp sometime after the NavigationTiming's loadEventEnd timestamp and before now (if NavTiming supported)", function() { var b = tf.lastBeacon(); var now = +(new Date()); if (window.performance && window.performance.timing && window.performance.timing.navigationStart) { - assert.operator(b["rt.end"], ">=", window.performance.timing.loadEventStart); + assert.operator(b["rt.end"], ">=", window.performance.timing.loadEventEnd); assert.operator(b["rt.end"], "<=", now); } else { diff --git a/tests/page-templates/03-load-order/01-after-page-load.js b/tests/page-templates/03-load-order/01-after-page-load.js index 11bc66ea7..4aca38bd2 100644 --- a/tests/page-templates/03-load-order/01-after-page-load.js +++ b/tests/page-templates/03-load-order/01-after-page-load.js @@ -29,10 +29,10 @@ describe("e2e/03-load-order/01-after-page-load", function() { } }); - it("Should have a end timestamp equal to NavigationTiming's loadEventStart timestamp (if NavTiming supported)", function() { + it("Should have a end timestamp equal to NavigationTiming's loadEventEnd timestamp (if NavTiming supported)", function() { var b = tf.lastBeacon(); if (window.performance && window.performance.timing) { - assert.equal(b["rt.end"], window.performance.timing.loadEventStart); + assert.equal(b["rt.end"], window.performance.timing.loadEventEnd); } else { return this.skip(); diff --git a/tests/page-templates/03-load-order/02-after-page-load-tag-manager.js b/tests/page-templates/03-load-order/02-after-page-load-tag-manager.js index 49760b049..a474d64d8 100644 --- a/tests/page-templates/03-load-order/02-after-page-load-tag-manager.js +++ b/tests/page-templates/03-load-order/02-after-page-load-tag-manager.js @@ -9,10 +9,10 @@ describe("e2e/03-load-order/02-after-page-load-tag-manager", function() { t.validateBeaconWasSent(done); }); - it("Should have a end timestamp equal to NavigationTiming's loadEventStart timestamp (if NavTiming supported)", function() { + it("Should have a end timestamp equal to NavigationTiming's loadEventEnd timestamp (if NavTiming supported)", function() { var b = tf.lastBeacon(); if (window.performance && window.performance.timing) { - assert.equal(b["rt.end"], window.performance.timing.loadEventStart); + assert.equal(b["rt.end"], window.performance.timing.loadEventEnd); } else { return this.skip(); diff --git a/tests/page-templates/06-bugs/111096-2.html b/tests/page-templates/06-bugs/111096-2.html index d512d8fd0..0bc71d310 100644 --- a/tests/page-templates/06-bugs/111096-2.html +++ b/tests/page-templates/06-bugs/111096-2.html @@ -2,6 +2,9 @@ <%= boomerangSnippet %> <%= boomerangSnippet %> diff --git a/tests/page-templates/07-autoxhr/23-xhrs-duplicate-tao.html b/tests/page-templates/07-autoxhr/23-xhrs-duplicate-tao.html index f193419f7..1cf88d9f8 100644 --- a/tests/page-templates/07-autoxhr/23-xhrs-duplicate-tao.html +++ b/tests/page-templates/07-autoxhr/23-xhrs-duplicate-tao.html @@ -36,7 +36,8 @@ setTimeout(function(delay) { var xhr2 = new XMLHttpRequest(); // with Timing-Allow-Origin=* - xhr2.open("GET", urlPrefix + "/delay?delay=-1000&file=build/boomerang-latest-debug.js&TAO=1"); + // NOTE: Use POST, otherwise Chrome delays multiple GET XHRs for the same URL (2 at a time) + xhr2.open("POST", urlPrefix + "/delay?delay=-1000&file=build/boomerang-latest-debug.js&TAO=1"); xhr2.send(null); }, timeout, i * 1000); diff --git a/tests/page-templates/07-autoxhr/24-xhrs-duplicate-no-tao.html b/tests/page-templates/07-autoxhr/24-xhrs-duplicate-no-tao.html index 1860e2e96..597a26a90 100644 --- a/tests/page-templates/07-autoxhr/24-xhrs-duplicate-no-tao.html +++ b/tests/page-templates/07-autoxhr/24-xhrs-duplicate-no-tao.html @@ -36,7 +36,8 @@ setTimeout(function(delay) { var xhr2 = new XMLHttpRequest(); // no Timing-Allow-Origin - xhr2.open("GET", urlPrefix + "/delay?delay=%2B1000&file=build/boomerang-latest-debug.js&TAO=0"); + // NOTE: Use POST, otherwise Chrome delays multiple GET XHRs for the same URL (2 at a time) + xhr2.open("POST", urlPrefix + "/delay?delay=%2B1000&file=build/boomerang-latest-debug.js&TAO=0"); xhr2.send(null); }, timeout, i * 1000); diff --git a/tests/page-templates/07-autoxhr/25-xhrs-duplicate-tao.html b/tests/page-templates/07-autoxhr/25-xhrs-duplicate-tao.html index 9cc1f8688..fd146e664 100644 --- a/tests/page-templates/07-autoxhr/25-xhrs-duplicate-tao.html +++ b/tests/page-templates/07-autoxhr/25-xhrs-duplicate-tao.html @@ -36,7 +36,8 @@ setTimeout(function(delay) { var xhr2 = new XMLHttpRequest(); // with Timing-Allow-Origin=* - xhr2.open("GET", urlPrefix + "/delay?delay=%2B1000&file=build/boomerang-latest-debug.js&TAO=1"); + // NOTE: Use POST, otherwise Chrome delays multiple GET XHRs for the same URL (2 at a time) + xhr2.open("POST", urlPrefix + "/delay?delay=%2B1000&file=build/boomerang-latest-debug.js&TAO=1"); xhr2.send(null); }, timeout, i * 1000); diff --git a/tests/page-templates/09-backbone/26-page-params-spa-nav.html b/tests/page-templates/09-backbone/26-page-params-spa-nav.html index 63230b910..a90e93a01 100644 --- a/tests/page-templates/09-backbone/26-page-params-spa-nav.html +++ b/tests/page-templates/09-backbone/26-page-params-spa-nav.html @@ -8,7 +8,7 @@ -<%= footer %> \ No newline at end of file +<%= footer %> diff --git a/tests/page-templates/09-backbone/support/app.js b/tests/page-templates/09-backbone/support/app.js index ee2ec166d..5f6612139 100644 --- a/tests/page-templates/09-backbone/support/app.js +++ b/tests/page-templates/09-backbone/support/app.js @@ -81,9 +81,11 @@ app.HomeView = Backbone.View.extend({ var template = Handlebars.compile(app.TEMPLATES.home); var imgs = typeof window.backbone_imgs !== "undefined" ? window.backbone_imgs : [0]; + var hide_imgs = imgs[0] === -1; that.$el.html(template({ imgs: imgs, + hide_imgs: hide_imgs, widgets: app.widgets.toJSON(), rnd: Math.random() })); diff --git a/tests/page-templates/09-backbone/support/home.html b/tests/page-templates/09-backbone/support/home.html index 11fa38e94..563293e38 100644 --- a/tests/page-templates/09-backbone/support/home.html +++ b/tests/page-templates/09-backbone/support/home.html @@ -1,8 +1,10 @@

Home

- {{#each imgs}} - - {{/each}} + {{#unless hide_imgs}} + {{#each imgs}} + + {{/each}} + {{/unless}} diff --git a/tests/page-templates/11-restiming/00-clear-onbeacon.js b/tests/page-templates/11-restiming/00-clear-onbeacon.js index c1a5aadad..8b4e260a4 100644 --- a/tests/page-templates/11-restiming/00-clear-onbeacon.js +++ b/tests/page-templates/11-restiming/00-clear-onbeacon.js @@ -9,9 +9,18 @@ describe("e2e/11-restiming/00-clear-onbeacon", function() { }); it("Should clear ResourceTiming array after beacon (if ResourceTiming is enabled)", function() { + var a; if (t.isResourceTimingSupported()) { var entries = window.performance.getEntriesByType("resource"); - assert.equal(entries.length, 0); + if (entries.length === 1) { + // if we have 1 entry then it should be the beacon + a = document.createElement("a"); + a.href = entries[0].name; + assert.equal(a.pathname, BOOMR.getBeaconURL()); + } + else { + assert.equal(entries.length, 0); + } } else { this.skip(); diff --git a/tests/page-templates/11-restiming/04-resource-sizes.html b/tests/page-templates/11-restiming/04-resource-sizes.html index ed9cbf884..28e7332e4 100644 --- a/tests/page-templates/11-restiming/04-resource-sizes.html +++ b/tests/page-templates/11-restiming/04-resource-sizes.html @@ -3,7 +3,7 @@ - + + + + <%= footer %> diff --git a/tests/page-templates/11-restiming/06-iframes.js b/tests/page-templates/11-restiming/06-iframes.js index ead8e757f..7abde20ff 100644 --- a/tests/page-templates/11-restiming/06-iframes.js +++ b/tests/page-templates/11-restiming/06-iframes.js @@ -30,8 +30,13 @@ describe("e2e/11-restiming/06-iframes", function() { for (var i = 0; i < pageResources.length; i++) { var url = pageResources[i].name; + // ideally, we should skip anything in RT that is newer than our beacon // skip beacon URL - if (url.indexOf("blackhole") !== -1) { + if (url.indexOf(BOOMR.getBeaconURL()) !== -1) { + continue; + } + // skip favicon which is requested after beacon + if (url.indexOf("/favicon.ico") !== -1) { continue; } diff --git a/tests/page-templates/11-restiming/06-svg-image.html b/tests/page-templates/11-restiming/06-svg-image.html index 5bd851d1b..ea13d9bf6 100644 --- a/tests/page-templates/11-restiming/06-svg-image.html +++ b/tests/page-templates/11-restiming/06-svg-image.html @@ -5,7 +5,7 @@ - + - + + <%= footer %> diff --git a/tests/page-templates/11-restiming/08-cross-origin.js b/tests/page-templates/11-restiming/08-cross-origin.js index 258b1b818..d55af6998 100644 --- a/tests/page-templates/11-restiming/08-cross-origin.js +++ b/tests/page-templates/11-restiming/08-cross-origin.js @@ -31,7 +31,12 @@ describe("e2e/11-restiming/06-iframes", function() { var url = pageResources[i].name; // skip beacon URL - if (url.indexOf("blackhole") !== -1) { + if (url.indexOf("beacon") !== -1) { + continue; + } + + // skip favicon + if (url.indexOf("favicon.ico") !== -1) { continue; } diff --git a/tests/page-templates/11-restiming/support/07-script-attrs.linkasync.js b/tests/page-templates/11-restiming/support/07-script-attrs.linkasync.js new file mode 100644 index 000000000..e69de29bb diff --git a/tests/page-templates/14-errors/25-autorun-false-onload-happens.js b/tests/page-templates/14-errors/25-autorun-false-onload-happens.js index a5a4e2b9c..5df3e5148 100644 --- a/tests/page-templates/14-errors/25-autorun-false-onload-happens.js +++ b/tests/page-templates/14-errors/25-autorun-false-onload-happens.js @@ -84,7 +84,6 @@ describe("e2e/14-errors/25-autorun-false-onload-happens", function() { it("Should have put NavigationTiming metrics on the beacon (if NavigationTiming is supported)", function() { if (t.isNavigationTimingSupported()) { assert.isDefined(tf.beacons[0].nt_nav_st); - assert.isDefined(tf.beacons[0].nt_load_st); } else { return this.skip(); diff --git a/tests/page-templates/14-errors/33-events-xhr-wrap-xhret-before.js b/tests/page-templates/14-errors/33-events-xhr-wrap-xhret-before.js index 8d1ad4b34..c7031a0a6 100644 --- a/tests/page-templates/14-errors/33-events-xhr-wrap-xhret-before.js +++ b/tests/page-templates/14-errors/33-events-xhr-wrap-xhret-before.js @@ -118,12 +118,12 @@ describe("e2e/14-errors/33-events-xhr-wrap-xhret-before", function() { } }); - it("Should have lineNumber ~ " + (HEADER_LINES + 36), function() { + it("Should have lineNumber ~ " + (HEADER_LINES + 43), function() { var b = tf.lastBeacon(); var err = BOOMR.plugins.Errors.decompressErrors(C.jsUrlDecompress(b.err))[0]; if (err.lineNumber) { - assert.closeTo(err.lineNumber, HEADER_LINES + 36, 5); + assert.closeTo(err.lineNumber, HEADER_LINES + 43, 5); } else { return this.skip(); diff --git a/tests/page-templates/17-memory/00-dom-counts.html b/tests/page-templates/17-memory/00-dom-counts.html index 51f61a233..4d2d2b1fc 100644 --- a/tests/page-templates/17-memory/00-dom-counts.html +++ b/tests/page-templates/17-memory/00-dom-counts.html @@ -11,7 +11,7 @@ - + diff --git a/tests/page-templates/19-navtiming/00-onload.js b/tests/page-templates/19-navtiming/00-onload.js index 2a30fdd71..55a043382 100644 --- a/tests/page-templates/19-navtiming/00-onload.js +++ b/tests/page-templates/19-navtiming/00-onload.js @@ -7,8 +7,6 @@ describe("e2e/19-navtiming/00-onload", function() { var NT_PROPERTIES = [ "nt_nav_st", - "nt_red_st", - "nt_red_end", "nt_fet_st", "nt_dns_st", "nt_dns_end", @@ -23,7 +21,10 @@ describe("e2e/19-navtiming/00-onload", function() { "nt_domcontloaded_end", "nt_domcomp", "nt_load_st", - "nt_load_end", + "nt_load_end" + ]; + + var NT_PROPERTIES_OPTIONAL = [ "nt_unload_st", "nt_unload_end" ]; @@ -71,6 +72,19 @@ describe("e2e/19-navtiming/00-onload", function() { // make sure it's not decimal assert.notInclude(tf.lastBeacon()[NT_PROPERTIES[i]], "."); } + + for (var i = 0; i < NT_PROPERTIES_OPTIONAL.length; i++) { + if (typeof tf.lastBeacon()[NT_PROPERTIES_OPTIONAL[i]] !== "undefined") { + // Jan 1 2000 + assert.operator(parseInt(tf.lastBeacon()[NT_PROPERTIES_OPTIONAL[i]], 10), ">=", 946684800, NT_PROPERTIES_OPTIONAL[i]); + + // Jan 1 2050 + assert.operator(parseInt(tf.lastBeacon()[NT_PROPERTIES_OPTIONAL[i]], 10), "<=", 2524658358000, NT_PROPERTIES_OPTIONAL[i]); + + // make sure it's not decimal + assert.notInclude(tf.lastBeacon()[NT_PROPERTIES_OPTIONAL[i]], "."); + } + } }); it("Should have set set nt_* properties as full numbers, not decimals (if NavigationTiming is supported)", function() { @@ -81,6 +95,12 @@ describe("e2e/19-navtiming/00-onload", function() { for (var i = 0; i < NT_PROPERTIES.length; i++) { assert.notInclude(tf.lastBeacon()[NT_PROPERTIES[i]], ".", NT_PROPERTIES[i]); } + + for (var i = 0; i < NT_PROPERTIES_OPTIONAL.length; i++) { + if (typeof tf.lastBeacon()[NT_PROPERTIES_OPTIONAL[i]] !== "undefined") { + assert.notInclude(tf.lastBeacon()[NT_PROPERTIES_OPTIONAL[i]], ".", NT_PROPERTIES_OPTIONAL[i]); + } + } }); it("Should have set Chrome nt_* properties (if Chrome)", function() { @@ -142,12 +162,28 @@ describe("e2e/19-navtiming/00-onload", function() { } }); - it("Should have set nt_* navigation properties (if NavigationTiming is supported)", function() { + it("Should have set nt_nav_type property (if NavigationTiming is supported)", function() { if (!t.isNavigationTimingSupported()) { return this.skip(); } - assert.isNumber(tf.lastBeacon().nt_red_cnt, "nt_red_cnt"); assert.isNumber(tf.lastBeacon().nt_nav_type, "nt_nav_type"); }); + + it("Should have set nt_red_cnt property to 0 (if NavigationTiming is supported)", function() { + if (!t.isNavigationTimingSupported()) { + return this.skip(); + } + + assert.equal(tf.lastBeacon().nt_red_cnt, 0); + }); + + it("Should not have set redirect timing properties (if NavigationTiming is supported)", function() { + if (!t.isNavigationTimingSupported()) { + return this.skip(); + } + + assert.isUndefined(tf.lastBeacon().nt_red_st, "nt_red_st"); + assert.isUndefined(tf.lastBeacon().nt_red_end, "nt_red_end"); + }); }); diff --git a/tests/server/app.js b/tests/server/app.js index 1396544eb..f5abf2e32 100644 --- a/tests/server/app.js +++ b/tests/server/app.js @@ -65,7 +65,14 @@ function respond301(req, res) { // Routes // -// /blackhole and /204: returns a 204 +// Favicon empty response +app.get("/favicon.ico", respond204); + +// /beacon, /beacon/no-op and /blackhole: returns a 204 +app.get("/beacon", respond204); +app.post("/beacon", respond204); +app.get("/beacon/no-op", respond204); +app.post("/beacon/no-op", respond204); app.get("/blackhole", respond204); app.post("/blackhole", respond204); @@ -73,7 +80,7 @@ app.post("/blackhole", respond204); app.get("/delay", require("./route-delay")); app.post("/delay", require("./route-delay")); -// /301 - 301 redirects +// /redirect - 301 redirects app.get("/redirect", respond301); app.post("/redirect", respond301); @@ -81,9 +88,6 @@ app.post("/redirect", respond301); app.get("/chunked", require("./route-chunked")); app.post("/chunked", require("./route-chunked")); -app.get("/blackhole/no-op", respond204); -app.post("/blackhole/no-op", respond204); - // for every GET, look for a file with the same name appended with ".headers" // if found, parse the headers and write them on the response // whether found or not, let the req/res pass through with next() diff --git a/tests/test-templates/autoxhr/00-xhrs-duplicate.js b/tests/test-templates/autoxhr/00-xhrs-duplicate.js index a668b0c77..c8e2a79f9 100644 --- a/tests/test-templates/autoxhr/00-xhrs-duplicate.js +++ b/tests/test-templates/autoxhr/00-xhrs-duplicate.js @@ -12,58 +12,65 @@ BOOMR_test.templates.XHR["00-xhrs-duplicate"] = function() { done, function() { t.ensureBeaconCount(done, 5); - }); + }, + this.skip.bind(this)); }); function check(b, secs) { assert.closeTo(b.t_done, secs * 1000, 250); assert.closeTo(b.nt_res_end - b.nt_req_st, secs * 1000, 250, "response should be close to " + secs + " seconds"); + if (b.nt_fet_st) { // not avail in PhantomJS assert.ok(b.nt_fet_st <= b.nt_req_st, "nt_fet_st should be at most nt_req_st"); } + assert.ok(b.nt_req_st <= b.nt_res_st, "nt_req_st should be at most nt_res_st"); assert.ok(b.nt_res_st <= b.nt_res_end, "nt_res_st should be at most nt_res_end"); assert.ok(b.nt_res_end <= b.nt_load_st, "nt_res_end should be at most nt_load_st"); } - it("Should have the next beacon contain a time of around around 0 seconds", function(done) { + it("Should have the second beacon contain a time of around around 0 seconds", function(done) { this.timeout(30000); t.ifAutoXHR( done, function() { check(tf.beacons[1], 0); done(); - }); + }, + this.skip.bind(this)); }); - it("Should have the next beacon contain a time of around around 1 seconds", function(done) { + it("Should have the third beacon contain a time of around around 1 seconds", function(done) { this.timeout(30000); t.ifAutoXHR( done, function() { check(tf.beacons[2], 1); done(); - }); + }, + this.skip.bind(this)); }); - it("Should have the next beacon contain a time of around around 2 seconds", function(done) { + it("Should have the fourth beacon contain a time of around around 2 seconds", function(done) { this.timeout(30000); t.ifAutoXHR( done, function() { check(tf.beacons[3], 2); done(); - }); + }, + this.skip.bind(this)); }); - it("Should have the next beacon contain a time of around around 3 seconds", function(done) { + it("Should have the fifth beacon contain a time of around around 3 seconds", function(done) { this.timeout(30000); t.ifAutoXHR( done, function() { check(tf.beacons[4], 3); done(); - }); + }, + this.skip.bind(this)); }); }; diff --git a/tests/test-templates/common.js b/tests/test-templates/common.js index 208b40722..179afec52 100644 --- a/tests/test-templates/common.js +++ b/tests/test-templates/common.js @@ -42,6 +42,7 @@ describe("common", function() { if (b["rt.start"] === "navigation") { // page load beacon + // TODO } else if (b["rt.start"] === "manual") { if (b["http.initiator"] === "spa_hard") { @@ -57,6 +58,11 @@ describe("common", function() { assert.isUndefined(b.api, prefix + "does not have the api param"); assert.isDefined(b.pgu, prefix + "has the pgu param"); } + else if (b["http.initiator"] === "click") { + // click (AutoXHR) beacon + assert.isUndefined(b.api, prefix + "does not have the api param"); + assert.isDefined(b.pgu, prefix + "has the pgu param"); + } else if (b["http.initiator"] === "api_custom_metric") { // send metric beacon assert.equal(b.api, "1", prefix + "has the api param value equal to 1"); @@ -98,6 +104,12 @@ describe("common", function() { else if (b["rt.start"] === "cookie") { // TODO } + else if (b["rt.start"] === "csi") { + // TODO + } + else if (b["rt.start"] === "gtb") { + // TODO + } else if (typeof b["rt.start"] === "undefined") { if (b["http.initiator"] === "error") { // error beacon diff --git a/tests/test-templates/spa/00-simple.js b/tests/test-templates/spa/00-simple.js index 2886050be..71e0136b4 100644 --- a/tests/test-templates/spa/00-simple.js +++ b/tests/test-templates/spa/00-simple.js @@ -83,11 +83,11 @@ BOOMR_test.templates.SPA["00-simple"] = function() { it("Should have NavigationTiming metrics (if MutationObserver and NavigationTiming are supported)", function() { if (typeof window.MutationObserver !== "undefined" && typeof BOOMR.plugins.RT.navigationStart() !== "undefined") { var b = tf.lastBeacon(); - assert.isDefined(b.nt_red_cnt); + assert.equal(b.nt_red_cnt, 0); // no redirects assert.isDefined(b.nt_nav_type); assert.isDefined(b.nt_nav_st); - assert.isDefined(b.nt_red_st); - assert.isDefined(b.nt_red_end); + assert.isUndefined(b.nt_red_st); // no redirects + assert.isUndefined(b.nt_red_end); // no redirects assert.isDefined(b.nt_fet_st); assert.isDefined(b.nt_dns_st); assert.isDefined(b.nt_dns_end); diff --git a/tests/test-templates/spa/04-route-change.js b/tests/test-templates/spa/04-route-change.js index 5ce4a5941..949f57f37 100644 --- a/tests/test-templates/spa/04-route-change.js +++ b/tests/test-templates/spa/04-route-change.js @@ -98,8 +98,8 @@ BOOMR_test.templates.SPA["04-route-change"] = 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") { + it("Should have a t_resp of the root page (if MutationObserver and ResourceTiming are supported)", function() { + if (window.MutationObserver && t.isResourceTimingSupported()) { var pt = window.performance.timing; var b = tf.beacons[0]; assert.equal(b.t_resp, pt.responseStart - pt.navigationStart); @@ -109,9 +109,8 @@ BOOMR_test.templates.SPA["04-route-change"] = 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") { - var pt = window.performance.timing; + it("Should have a t_page of total - t_resp (if MutationObserver and ResourceTiming are supported)", function() { + if (window.MutationObserver && t.isResourceTimingSupported()) { var b = tf.beacons[0]; assert.equal(b.t_page, b.t_done - b.t_resp); } @@ -150,9 +149,8 @@ BOOMR_test.templates.SPA["04-route-change"] = 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") { - var pt = window.performance.timing; + it("Should have sent the second beacon with a t_resp value (if MutationObserver and ResourceTiming are supported)", function() { + if (window.MutationObserver && t.isResourceTimingSupported()) { var b = tf.beacons[1]; assert.operator(b.t_resp, ">=", 0); @@ -162,9 +160,8 @@ BOOMR_test.templates.SPA["04-route-change"] = 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") { - var pt = window.performance.timing; + it("Should have sent the second beacon with a t_page of total - t_resp (if MutationObserver and ResourceTiming are supported)", function() { + if (window.MutationObserver && t.isResourceTimingSupported()) { var b = tf.beacons[1]; assert.equal(b.t_page, b.t_done - b.t_resp); } @@ -201,9 +198,8 @@ BOOMR_test.templates.SPA["04-route-change"] = function() { } }); - 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") { - var pt = window.performance.timing; + it("Should have sent the third beacon with a t_resp value (if MutationObserver and ResourceTiming are supported)", function() { + if (window.MutationObserver && t.isResourceTimingSupported()) { var b = tf.beacons[2]; assert.operator(b.t_resp, ">=", 0); @@ -213,9 +209,8 @@ BOOMR_test.templates.SPA["04-route-change"] = 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") { - var pt = window.performance.timing; + it("Should have sent the third beacon with a t_page of total - t_resp (if MutationObserver and ResourceTiming are supported)", function() { + if (window.MutationObserver && t.isResourceTimingSupported()) { var b = tf.beacons[2]; assert.equal(b.t_page, b.t_done - b.t_resp); } diff --git a/tests/unit/04-plugins-restiming.js b/tests/unit/04-plugins-restiming.js index a6408e5da..836c2bfbf 100644 --- a/tests/unit/04-plugins-restiming.js +++ b/tests/unit/04-plugins-restiming.js @@ -1247,9 +1247,14 @@ describe("BOOMR.plugins.ResourceTiming", function() { var opt; it("Should get compressed & optimized timepoints", function() { + var scr = BOOMR.window.screen; + BOOMR.window.screen = { height: 768, width: 1024 }; + opt = BOOMR.plugins.ResourceTiming.getOptimizedTimepoints(timePoints); assert.strictEqual(opt, "a~b3b~3uw!5a~hd0~9n8!46~14ic~ibq!1e~4tm~n5c!1e-!~2s"); + + BOOMR.window.screen = scr; }); it("Should decompress optimized timings", function() {