Testing web UI interaction response times with CasperJS

I’ve written a few utilities lately to measure how fast a page loads over the wire.  While watching Nicholas Zakas’ presentation at Velocity, I started wondering how I would measure the load times for popups, tabs, and other dynamic content loaded via user interaction.  CasperJS has already proven extremely handy for automating some pretty complex functional tests that had previously been done manually, so I pulled that out of the tool box to see if I could add some measurements.

Unfortunately, Nicholas’ demo was so fast and consistent that the numbers didn’t look believable :-) So, like most web developers, I turned to jQuery. And, as always, jQuery had exactly what I needed. The jQuery UI Tabs Example came complete with dynamically loaded, slow, and even broken tabs.  The Gist and output are below.

var colorizer = require('colorizer').create('Colorizer');
var casper = require('casper').create();
var totalTests=3;
casper.start('http://jqueryui.com/resources/demos/tabs/ajax.html', function(){
	casper.viewport(1024, 768);
	this.test.assertHttpStatus(200, "The page has loaded.");
	this.test.assertSelectorExists('#tabs', "We got tabs.");
	this.test.assertVisible('#tabs-1', "Content 1 is visible.");
	this.capture('ui-id-1.png');
});
testTabLoad('#ui-id-2', '#ui-tabs-1', "Tab 1", "tab1.png");
testTabLoad('#ui-id-3', '#ui-tabs-2', "Tab 2", "tab2.png");
testTabLoad('#ui-id-4', '#ui-tabs-3', "Tab 3 (slow)", "tab3.png");
testTabLoad('#ui-id-5', '#ui-tabs-4', "Tab 4 (broken)", "tab4.png");
casper.run(function() {
	this.test.done(totalTests);
	this.test.renderResults(true);
});
function testTabLoad(tab, content, name, capfilename){
	totalTests+=4;
	casper.then(function() {
		if(name)casper.echo(name, "COMMENT");
		var start=Date.now();
		this.test.assertSelectorExists(tab, "Tab selector exists.");
		this.test.assertSelectorExists(content, "Content selector exists.");
		this.test.assertDoesntExist(content+'>p', "Content is not already populated.");
		this.test.assertNotVisible(content, "Content selector is not currently visible.");
		this.click(tab);
		this.waitUntilVisible(content+'>p', function(){
			casper.echo("Content became visible in " + (Date.now()-start) + " ms", "INFO_BAR");
			if(capfilename)this.captureSelector(capfilename, content);
		});
	});	
}

Selection_012