Skip to content

Commit

Permalink
AutoXHR: Wait once up to 1,000ms after an uninteresting mutation
Browse files Browse the repository at this point in the history
  • Loading branch information
nicjansma committed Apr 4, 2018
1 parent 1fdfcda commit 69840cd
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 6 deletions.
34 changes: 28 additions & 6 deletions plugins/auto-xhr.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,25 @@
*/
var SPA_TIMEOUT = 1000;

/**
* Clicks and XHR events get 50ms for an interesting thing to happen before
* being cancelled.
* @type {number}
* @constant
* @default
*/
var CLICK_XHR_TIMEOUT = 50;

/**
* If we get a Mutation event that doesn't have any interesting nodes after
* a Click or XHR event started, wait up to 1,000ms for an interesting one
* to happen before cancelling the event.
* @type {number}
* @constant
* @default
*/
var UNINTERESTING_MUTATION_TIMEOUT = 1000;

/**
* How long to wait if we're not ready to send a beacon to try again.
* @constant
Expand Down Expand Up @@ -348,9 +367,9 @@
}
else {
if (!BOOMR.utils.inArray(ev.type, BOOMR.constants.BEACON_TYPE_SPAS)) {
// Give clicks and history changes 50ms to see if they resulted
// Give Click and XHR events 50ms to see if they resulted
// in DOM mutations (and thus it is an 'interesting event').
this.setTimeout(50, index);
this.setTimeout(CLICK_XHR_TIMEOUT, index);
}
else {
// Give SPAs a bit more time to do something since we know this was
Expand Down Expand Up @@ -987,11 +1006,14 @@
});
}

if (!this.timer && !evt.interesting) {
if (!evt.interesting && !this.timeoutExtended) {
// timeout the event if we haven't already created a timer and
// we didn't have any interesting nodes for this MO callback or
// any prior callbacks
this.setTimeout(SPA_TIMEOUT, index);
this.setTimeout(UNINTERESTING_MUTATION_TIMEOUT, index);

// only extend the timeout for an interesting thing to happen once
this.timeoutExtended = true;
}

return true;
Expand Down Expand Up @@ -1478,7 +1500,7 @@
* - We turn on DOM observer, and wait up to 50 milliseconds for something
* - If nothing happens after the timeout, we stop watching and clear the resource without firing the event
* - If a history event happened recently/will happen shortly, use the URL as the resource.url
* - Else if something uninteresting happens, we set the timeout for 1 second if it wasn't already started
* - Else if something uninteresting happens, we set the timeout for 1 more second (only once)
* - We don't want to continuously extend the timeout with each uninteresting event
* - Else if an interesting node is added, we add load and error listeners and turn off the timeout but keep watching
* - If we do not have a resource.url, and if this is a script, then we use the script's URL
Expand All @@ -1492,7 +1514,7 @@
* - If a history event happened recently/will happen shortly, use the URL as the resource.url
* - We watch for all changes in state (for async requests) and for load (for all requests)
* - On load, we turn on DOM observer, and wait up to 50 milliseconds for something
* - If something uninteresting happens, we set the timeout for 1 second if it wasn't already started
* - If something uninteresting happens, we set the timeout for 1 more second (only once)
* - We don't want to continuously extend the timeout with each uninteresting event
* - Else if an interesting node is added, we add load and error listeners and turn off the timeout
* - Once all listeners have fired, we stop watching, fire the event and clear the resource
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<%= header %>
<!--
Verify that creating uninteresting mutation observer events doesn't hold an xhr beacon from being sent
-->
<script src="39-uninteresting-mo-followed-by-interesting.js" type="text/javascript"></script>
<%= boomerangSnippet %>
<script>
BOOMR_test.init({
"instrument_xhr": true,
testAfterOnBeacon: BOOMR.plugins.AutoXHR ? 2 : 1,
afterFirstBeacon:
function() {
if (!BOOMR.plugins.AutoXHR) {
return;
}

// start a XHR
var xhr = new XMLHttpRequest();
xhr.open("GET", "/assets/blank.html");
xhr.send();

// create a non-interesting MO event right afterwards.
// this should extend the timeout to 1s.
setTimeout(function() {
var div = window.document.createElement("div");
window.document.body.appendChild(div);
}, 10);

// create an interesting MO event at 500ms.
// this should trigger the beacon.
setTimeout(function() {
var img = window.document.createElement("img");
img.src = "/assets/img.jpg";
window.document.body.appendChild(img);
}, 500);
}
});
</script>
<%= footer %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*eslint-env mocha*/
/*global assert*/

describe("e2e/07-autoxhr/39-uninteresting-mo-followed-by-interesting", function() {
var t = BOOMR_test;
var tf = BOOMR.plugins.TestFramework;

it("Should get 2 beacons: 1 onload, 1 click (XMLHttpRequest !== null)", function(done) {
this.timeout(10000);
t.ifAutoXHR(
done,
function() {
t.ensureBeaconCount(done, 2);
});
});

it("Should have the first beacon be a page load beacon (XMLHttpRequest !== null)", function(done) {
t.ifAutoXHR(
done,
function() {
assert.include(tf.beacons[0].u, "39-uninteresting-mo-followed-by-interesting.html");
done();
});
});

it("Should have the second beacon be a XHR beacon (XMLHttpRequest !== null)", function(done) {
t.ifAutoXHR(
done,
function() {
assert.equal(tf.beacons[1]["http.initiator"], "xhr");
done();
});
});

it("Should have the second beacon have the URL of the XHR (XMLHttpRequest !== null)", function(done) {
t.ifAutoXHR(
done,
function() {
assert.include(tf.beacons[1].u, "blank.html");
done();
});
});
});

0 comments on commit 69840cd

Please sign in to comment.