Skip to content

Commit

Permalink
SPA.markNavigationComplete() support
Browse files Browse the repository at this point in the history
  • Loading branch information
nicjansma committed Apr 4, 2018
1 parent 73c2513 commit f253d1b
Show file tree
Hide file tree
Showing 7 changed files with 463 additions and 13 deletions.
2 changes: 0 additions & 2 deletions plugins/angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@
BOOMR.debug($rootScope.$id + ": " + msg, "angular");
}

log("Startup");

/**
* Fires the SPA route_change event.
*
Expand Down
48 changes: 40 additions & 8 deletions plugins/auto-xhr.js
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@
* @returns {undefined} - returns early if the event already completed
*/
MutationHandler.prototype.sendEvent = function(i) {
var ev = this.pending_events[i], self = this;
var ev = this.pending_events[i], self = this, now = BOOMR.now();

if (!ev || ev.complete) {
return;
Expand Down Expand Up @@ -432,8 +432,8 @@

// if this was a SPA nav that triggered no additional resources, substract the
// SPA_TIMEOUT from now to determine the end time
if (ev.total_nodes === 0) {
ev.resource.timing.loadEventEnd = BOOMR.now() - SPA_TIMEOUT;
if (!ev.forced && ev.total_nodes === 0) {
ev.resource.timing.loadEventEnd = now - SPA_TIMEOUT;
}
}

Expand Down Expand Up @@ -1025,21 +1025,53 @@
* @return {boolean} True if there are no outstanding resources
*/
MutationHandler.prototype.queue_is_empty = function() {
return this.nodesWaitingFor() === 0;
};

/**
* Determines how many nodes are being waited on
* @return {number} Number of nodes being waited on
*/
MutationHandler.prototype.nodesWaitingFor = function() {
if (this.pending_events.length === 0) {
return true;
return 0;
}

var index = this.pending_events.length - 1;

if (!this.pending_events[index]) {
return true;
return 0;
}

if (this.pending_events[index].nodes_to_wait === 0) {
return true;
return this.pending_events[index].nodes_to_wait;
};

/**
* Completes the current event, marking the end time as 'now'.
*/
MutationHandler.prototype.completeEvent = function() {
var now = BOOMR.now(), index, ev;

if (this.pending_events.length === 0) {
// no active events
return;
}

index = this.pending_events.length - 1;
ev = this.pending_events[index];
if (!ev) {
// unknown event
return;
}

return false;
// set the end timestamp to now
ev.resource.timing.loadEventEnd = now;

// note that this end was forced
ev.forced = true;

// complete this event
this.sendEvent(index);
};

handler = new MutationHandler();
Expand Down
50 changes: 50 additions & 0 deletions plugins/spa.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
(function() {
var hooked = false,
initialized = false,
initialRouteChangeStarted = false,
initialRouteChangeCompleted = false,
autoXhrEnabled = false,
Expand All @@ -18,6 +19,15 @@
return;
}

/**
* Debug logging for this plugin
*
* @param {string} msg Message
*/
function log(msg) {
BOOMR.debug(msg, "spa");
}

var impl = {
/**
* Called after a SPA Hard navigation that missed the route change
Expand Down Expand Up @@ -60,6 +70,14 @@
// to NavigationTiming's performance.loadEventEnd (instead of 'now')
resource.timing.loadEventEnd = stopTime;
}
},

/**
* Fired on each beacon.
*/
onBeacon: function() {
// remove all of the potential parameters we added to the beacon
BOOMR.removeVar("spa.missed", "spa.forced", "spa.waiting");
}
};

Expand Down Expand Up @@ -90,6 +108,14 @@
BOOMR.plugins.AutoXHR.enableAutoXhr();
}
}

if (initialized) {
return;
}

initialized = true;

BOOMR.subscribe("onbeacon", impl.onBeacon, null, impl);
},
/**
* Registers a framework with the SPA plugin
Expand Down Expand Up @@ -149,6 +175,8 @@
hook: function(hadRouteChange, options) {
options = options || {};

log("Hooked");

if (hooked) {
return this;
}
Expand Down Expand Up @@ -182,12 +210,15 @@
* @param {object[]} routeFilterArgs Route Filter arguments
*/
route_change: function(onComplete, routeFilterArgs) {
log("Route Change");

var firedEvent = false;

// if we have a routeFilter, see if they want to track this route
if (routeFilter) {
try {
if (!routeFilter.apply(null, routeFilterArgs)) {
log("Route filter returned false; not tracking this route");
return;
}
}
Expand Down Expand Up @@ -281,6 +312,25 @@

latestResource = null;
}
},

/**
* Marks the current navigation as complete and sends a beacon.
*/
markNavigationComplete: function() {
log("Navigation being marked complete");

var mh = BOOMR.plugins.AutoXHR.getMutationHandler();
if (mh) {
// note that the navigation was forced complete
BOOMR.addVar("spa.forced", "1");

// add the count of nodes we were waiting for
BOOMR.addVar("spa.waiting", mh.nodesWaitingFor());

// finalize this navigation
mh.completeEvent();
}
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<div ng-view>
</div>
</div>
<script src="113-route-change-abld.js" type="text/javascript"></script>
<script src="114-route-change-abld.js" type="text/javascript"></script>
<script>

// view a widget then come back so debugging (F5) is easier
Expand All @@ -28,7 +28,7 @@
// issue a route change while the spa soft is still loading
$timeout(function() {
window.nav2time = BOOMR.now();
$location.url("113-route-change-abld.html");
$location.url("114-route-change-abld.html");
}, 2000);
}, 2000);
}]);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*eslint-env mocha*/
/*global BOOMR_test*/

describe("e2e/05-angular/113-route-change-abld", function() {
describe("e2e/05-angular/114-route-change-abld", function() {
var tf = BOOMR.plugins.TestFramework;
var t = BOOMR_test;

Expand Down
53 changes: 53 additions & 0 deletions tests/page-templates/05-angular/117-route-change-markcomplete.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<%= header %>
<%= boomerangScript %>
<base href="/pages/05-angular/04-route-change.html" />
<script src="../../vendor/angular/angular.js"></script>
<script src="../../vendor/angular-resource/angular-resource.js"></script>
<script src="../../vendor/angular-route/angular-route.js"></script>
<script src="../../vendor/resourcetiming-compression/src/resourcetiming-decompression.js" type="text/javascript"></script>
<script>
window.angular_imgs = [5000];

window.angular_html5_mode = true;
</script>
<script src="support/app.js"></script>
<div ng-app="app">
<div ng-view>
</div>
</div>
<script src="117-route-change-markcomplete.js" type="text/javascript"></script>
<script>

// view a widget then come back so debugging (F5) is easier
app.run(["$location", "$timeout", function($location, $timeout) {
// issue a route change while the spa hard is still loading
$timeout(function() {
window.nav1time = BOOMR.now();
BOOMR.plugins.SPA.markNavigationComplete();

// now navigate to the second URL
$location.url("/widgets/10");

// issue a route change while the spa soft is still loading
$timeout(function() {
window.nav2time = BOOMR.now();
BOOMR.plugins.SPA.markNavigationComplete();

$location.url("117-route-change-markcomplete.html");
}, 1000);
}, 1000);
}]);

BOOMR_test.init({
testAfterOnBeacon: 3,
Angular: {
enabled: true
},
ResourceTiming: {
enabled: true
},
instrument_xhr: true,
autorun: false
});
</script>
<%= footer %>
Loading

0 comments on commit f253d1b

Please sign in to comment.