15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * QUnit - A JavaScript Unit Testing Framework
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * http://docs.jquery.com/QUnit
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (c) 2011 John Resig, Jörn Zaefferer
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Dual licensed under the MIT (MIT-LICENSE.txt)
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * or GPL (GPL-LICENSE.txt) licenses.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)(function(window) {
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var defined = {
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	setTimeout: typeof window.setTimeout !== "undefined",
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	sessionStorage: (function() {
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		try {
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			return !!sessionStorage.getItem;
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} catch(e){
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			return false;
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  })()
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var testId = 0;
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var Test = function(name, testName, expected, testEnvironmentArg, async, callback) {
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	this.name = name;
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	this.testName = testName;
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	this.expected = expected;
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	this.testEnvironmentArg = testEnvironmentArg;
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	this.async = async;
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	this.callback = callback;
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	this.assertions = [];
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Test.prototype = {
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	init: function() {
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var tests = id("qunit-tests");
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (tests) {
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var b = document.createElement("strong");
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				b.innerHTML = "Running " + this.name;
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var li = document.createElement("li");
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				li.appendChild( b );
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				li.className = "running";
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				li.id = this.id = "test-output" + testId++;
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			tests.appendChild( li );
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	setup: function() {
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (this.module != config.previousModule) {
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if ( config.previousModule ) {
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				QUnit.moduleDone( {
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					name: config.previousModule,
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					failed: config.moduleStats.bad,
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					passed: config.moduleStats.all - config.moduleStats.bad,
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					total: config.moduleStats.all
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				} );
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			config.previousModule = this.module;
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			config.moduleStats = { all: 0, bad: 0 };
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			QUnit.moduleStart( {
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				name: this.module
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} );
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		config.current = this;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		this.testEnvironment = extend({
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			setup: function() {},
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			teardown: function() {}
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}, this.moduleTestEnvironment);
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (this.testEnvironmentArg) {
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			extend(this.testEnvironment, this.testEnvironmentArg);
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.testStart( {
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			name: this.testName
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} );
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		// allow utility functions to access the current test environment
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		// TODO why??
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.current_testEnvironment = this.testEnvironment;
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		try {
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if ( !config.pollution ) {
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				saveGlobal();
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			this.testEnvironment.setup.call(this.testEnvironment);
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} catch(e) {
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			QUnit.ok( false, "Setup failed on " + this.testName + ": " + e.message );
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	run: function() {
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( this.async ) {
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			QUnit.stop();
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( config.notrycatch ) {
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			this.callback.call(this.testEnvironment);
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			return;
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		try {
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			this.callback.call(this.testEnvironment);
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} catch(e) {
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			fail("Test " + this.testName + " died, exception and test follows", e, this.callback);
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) );
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// else next test will carry the responsibility
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			saveGlobal();
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// Restart the tests if they're blocking
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if ( config.blocking ) {
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				start();
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	teardown: function() {
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		try {
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			this.testEnvironment.teardown.call(this.testEnvironment);
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			checkPollution();
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} catch(e) {
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message );
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	finish: function() {
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( this.expected && this.expected != this.assertions.length ) {
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" );
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var good = 0, bad = 0,
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			tests = id("qunit-tests");
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		config.stats.all += this.assertions.length;
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		config.moduleStats.all += this.assertions.length;
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( tests ) {
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var ol  = document.createElement("ol");
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			for ( var i = 0; i < this.assertions.length; i++ ) {
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				var assertion = this.assertions[i];
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				var li = document.createElement("li");
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				li.className = assertion.result ? "pass" : "fail";
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed");
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				ol.appendChild( li );
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				if ( assertion.result ) {
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					good++;
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				} else {
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					bad++;
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					config.stats.bad++;
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					config.moduleStats.bad++;
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				}
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// store result when possible
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if ( QUnit.config.reorder && defined.sessionStorage ) {
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				if (bad) {
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					sessionStorage.setItem("qunit-" + this.module + "-" + this.testName, bad);
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				} else {
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					sessionStorage.removeItem("qunit-" + this.module + "-" + this.testName);
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				}
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if (bad == 0) {
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				ol.style.display = "none";
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var b = document.createElement("strong");
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var a = document.createElement("a");
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			a.innerHTML = "Rerun";
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			a.href = QUnit.url({ filter: getText([b]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") });
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			addEvent(b, "click", function() {
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				var next = b.nextSibling.nextSibling,
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					display = next.style.display;
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				next.style.display = display === "none" ? "block" : "none";
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			});
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			addEvent(b, "dblclick", function(e) {
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				var target = e && e.target ? e.target : window.event.srcElement;
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					target = target.parentNode;
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				}
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					window.location = QUnit.url({ filter: getText([target]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") });
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				}
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			});
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var li = id(this.id);
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			li.className = bad ? "fail" : "pass";
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			li.removeChild( li.firstChild );
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			li.appendChild( b );
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			li.appendChild( a );
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			li.appendChild( ol );
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} else {
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			for ( var i = 0; i < this.assertions.length; i++ ) {
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				if ( !this.assertions[i].result ) {
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					bad++;
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					config.stats.bad++;
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					config.moduleStats.bad++;
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				}
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		try {
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			QUnit.reset();
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} catch(e) {
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			fail("reset() failed, following Test " + this.testName + ", exception and reset fn follows", e, QUnit.reset);
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.testDone( {
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			name: this.testName,
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			failed: bad,
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			passed: this.assertions.length - bad,
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			total: this.assertions.length
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} );
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	queue: function() {
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var test = this;
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		synchronize(function() {
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			test.init();
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		});
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		function run() {
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// each of these can by async
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			synchronize(function() {
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				test.setup();
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			});
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			synchronize(function() {
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				test.run();
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			});
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			synchronize(function() {
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				test.teardown();
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			});
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			synchronize(function() {
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				test.finish();
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			});
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		// defer when previous test run passed, if storage is available
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem("qunit-" + this.module + "-" + this.testName);
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (bad) {
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			run();
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} else {
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			synchronize(run);
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		};
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var QUnit = {
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// call on start of module test to prepend name to all tests
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	module: function(name, testEnvironment) {
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		config.currentModule = name;
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		config.currentModuleTestEnviroment = testEnvironment;
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	asyncTest: function(testName, expected, callback) {
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( arguments.length === 2 ) {
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			callback = expected;
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			expected = 0;
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.test(testName, expected, callback, true);
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	test: function(testName, expected, callback, async) {
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var name = '<span class="test-name">' + testName + '</span>', testEnvironmentArg;
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( arguments.length === 2 ) {
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			callback = expected;
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			expected = null;
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		// is 2nd argument a testEnvironment?
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( expected && typeof expected === 'object') {
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			testEnvironmentArg =  expected;
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			expected = null;
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( config.currentModule ) {
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			name = '<span class="module-name">' + config.currentModule + "</span>: " + name;
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( !validTest(config.currentModule + ": " + testName) ) {
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			return;
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var test = new Test(name, testName, expected, testEnvironmentArg, async, callback);
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		test.module = config.currentModule;
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		test.moduleTestEnvironment = config.currentModuleTestEnviroment;
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		test.queue();
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	/**
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 */
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	expect: function(asserts) {
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		config.current.expected = asserts;
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	/**
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * Asserts true.
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 */
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	ok: function(a, msg) {
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		a = !!a;
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var details = {
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			result: a,
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			message: msg
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		};
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		msg = escapeHtml(msg);
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.log(details);
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		config.current.assertions.push({
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			result: a,
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			message: msg
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		});
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	/**
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * Checks that the first two arguments are equal, with an optional message.
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * Prints out both actual and expected values.
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 *
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * Prefered to ok( actual == expected, message )
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 *
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." );
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 *
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * @param Object actual
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * @param Object expected
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * @param String message (optional)
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 */
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	equal: function(actual, expected, message) {
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.push(expected == actual, actual, expected, message);
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	notEqual: function(actual, expected, message) {
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.push(expected != actual, actual, expected, message);
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	deepEqual: function(actual, expected, message) {
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.push(QUnit.equiv(actual, expected), actual, expected, message);
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	notDeepEqual: function(actual, expected, message) {
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message);
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	strictEqual: function(actual, expected, message) {
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.push(expected === actual, actual, expected, message);
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	notStrictEqual: function(actual, expected, message) {
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.push(expected !== actual, actual, expected, message);
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	raises: function(block, expected, message) {
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var actual, ok = false;
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (typeof expected === 'string') {
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			message = expected;
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			expected = null;
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		try {
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			block();
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} catch (e) {
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			actual = e;
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (actual) {
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// we don't want to validate thrown error
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if (!expected) {
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				ok = true;
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// expected is a regexp
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else if (QUnit.objectType(expected) === "regexp") {
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				ok = expected.test(actual);
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// expected is a constructor
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else if (actual instanceof expected) {
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				ok = true;
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// expected is a validation function which returns true is validation passed
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else if (expected.call({}, actual) === true) {
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				ok = true;
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.ok(ok, message);
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	start: function() {
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		config.semaphore--;
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (config.semaphore > 0) {
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// don't start until equal number of stop-calls
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			return;
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (config.semaphore < 0) {
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// ignore if start is called more often then stop
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			config.semaphore = 0;
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		// A slight delay, to avoid any current callbacks
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( defined.setTimeout ) {
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			window.setTimeout(function() {
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				if ( config.timeout ) {
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					clearTimeout(config.timeout);
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				}
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				config.blocking = false;
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				process();
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}, 13);
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} else {
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			config.blocking = false;
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			process();
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	stop: function(timeout) {
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		config.semaphore++;
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		config.blocking = true;
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( timeout && defined.setTimeout ) {
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			clearTimeout(config.timeout);
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			config.timeout = window.setTimeout(function() {
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				QUnit.ok( false, "Test timed out" );
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				QUnit.start();
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}, timeout);
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Backwards compatibility, deprecated
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)QUnit.equals = QUnit.equal;
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)QUnit.same = QUnit.deepEqual;
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Maintain internal state
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var config = {
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// The queue of tests to run
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	queue: [],
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// block until document ready
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	blocking: true,
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// by default, run previously failed tests first
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// very useful in combination with "Hide passed tests" checked
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	reorder: true,
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	noglobals: false,
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	notrycatch: false
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Load paramaters
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)(function() {
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var location = window.location || { search: "", protocol: "file:" },
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		params = location.search.slice( 1 ).split( "&" ),
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		length = params.length,
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		urlParams = {},
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		current;
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( params[ 0 ] ) {
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		for ( var i = 0; i < length; i++ ) {
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			current = params[ i ].split( "=" );
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			current[ 0 ] = decodeURIComponent( current[ 0 ] );
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// allow just a key to turn on a flag, e.g., test.html?noglobals
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			urlParams[ current[ 0 ] ] = current[ 1 ];
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if ( current[ 0 ] in config ) {
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				config[ current[ 0 ] ] = current[ 1 ];
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	QUnit.urlParams = urlParams;
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	config.filter = urlParams.filter;
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// Figure out if we're running the tests from a server or not
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	QUnit.isLocal = !!(location.protocol === 'file:');
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)})();
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Expose the API as global variables, unless an 'exports'
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// object exists, in that case we assume we're in CommonJS
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)if ( typeof exports === "undefined" || typeof require === "undefined" ) {
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	extend(window, QUnit);
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	window.QUnit = QUnit;
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} else {
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	extend(exports, QUnit);
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	exports.QUnit = QUnit;
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// define these after exposing globals to keep them in these QUnit namespace only
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)extend(QUnit, {
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	config: config,
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// Initialize the configuration options
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	init: function() {
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		extend(config, {
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			stats: { all: 0, bad: 0 },
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			moduleStats: { all: 0, bad: 0 },
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			started: +new Date,
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			updateRate: 1000,
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			blocking: false,
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			autostart: true,
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			autorun: false,
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			filter: "",
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			queue: [],
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			semaphore: 0
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		});
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var tests = id( "qunit-tests" ),
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			banner = id( "qunit-banner" ),
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			result = id( "qunit-testresult" );
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( tests ) {
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			tests.innerHTML = "";
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( banner ) {
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			banner.className = "";
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( result ) {
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			result.parentNode.removeChild( result );
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( tests ) {
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			result = document.createElement( "p" );
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			result.id = "qunit-testresult";
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			result.className = "result";
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			tests.parentNode.insertBefore( result, tests );
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			result.innerHTML = 'Running...<br/>&nbsp;';
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	/**
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * Resets the test setup. Useful for tests that modify the DOM.
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 *
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 */
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	reset: function() {
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( window.jQuery ) {
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			jQuery( "#qunit-fixture" ).html( config.fixture );
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} else {
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var main = id( 'qunit-fixture' );
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if ( main ) {
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				main.innerHTML = config.fixture;
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	/**
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * Trigger an event on an element.
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 *
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * @example triggerEvent( document.body, "click" );
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 *
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * @param DOMElement elem
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 * @param String type
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 */
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	triggerEvent: function( elem, type, event ) {
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( document.createEvent ) {
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			event = document.createEvent("MouseEvents");
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				0, 0, 0, 0, 0, false, false, false, false, 0, null);
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			elem.dispatchEvent( event );
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} else if ( elem.fireEvent ) {
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			elem.fireEvent("on"+type);
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// Safe object type checking
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	is: function( type, obj ) {
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		return QUnit.objectType( obj ) == type;
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	objectType: function( obj ) {
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (typeof obj === "undefined") {
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				return "undefined";
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		// consider: typeof null === object
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (obj === null) {
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				return "null";
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var type = Object.prototype.toString.call( obj )
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			.match(/^\[object\s(.*)\]$/)[1] || '';
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		switch (type) {
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				case 'Number':
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)						if (isNaN(obj)) {
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)								return "nan";
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)						} else {
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)								return "number";
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)						}
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				case 'String':
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				case 'Boolean':
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				case 'Array':
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				case 'Date':
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				case 'RegExp':
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				case 'Function':
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)						return type.toLowerCase();
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (typeof obj === "object") {
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				return "object";
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		return undefined;
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	push: function(result, actual, expected, message) {
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var details = {
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			result: result,
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			message: message,
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			actual: actual,
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			expected: expected
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		};
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		message = escapeHtml(message) || (result ? "okay" : "failed");
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		message = '<span class="test-message">' + message + "</span>";
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		expected = escapeHtml(QUnit.jsDump.parse(expected));
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		actual = escapeHtml(QUnit.jsDump.parse(actual));
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var output = message + '<table><tr class="test-expected"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>';
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (actual != expected) {
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			output += '<tr class="test-actual"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>';
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			output += '<tr class="test-diff"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>';
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (!result) {
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var source = sourceFromStacktrace();
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if (source) {
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				details.source = source;
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				output += '<tr class="test-source"><th>Source: </th><td><pre>' + escapeHtml(source) + '</pre></td></tr>';
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		output += "</table>";
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.log(details);
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		config.current.assertions.push({
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			result: !!result,
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			message: output
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		});
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	url: function( params ) {
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		params = extend( extend( {}, QUnit.urlParams ), params );
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var querystring = "?",
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			key;
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		for ( key in params ) {
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			querystring += encodeURIComponent( key ) + "=" +
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				encodeURIComponent( params[ key ] ) + "&";
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		return window.location.pathname + querystring.slice( 0, -1 );
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	},
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// Logging callbacks; all receive a single argument with the listed properties
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// run test/logs.html for any related changes
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	begin: function() {},
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// done: { failed, passed, total, runtime }
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	done: function() {},
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// log: { result, actual, expected, message }
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	log: function() {},
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// testStart: { name }
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	testStart: function() {},
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// testDone: { name, failed, passed, total }
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	testDone: function() {},
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// moduleStart: { name }
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	moduleStart: function() {},
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// moduleDone: { name, failed, passed, total }
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	moduleDone: function() {}
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)});
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)if ( typeof document === "undefined" || document.readyState === "complete" ) {
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	config.autorun = true;
6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)addEvent(window, "load", function() {
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	QUnit.begin({});
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// Initialize the config, saving the execution queue
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var oldconfig = extend({}, config);
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	QUnit.init();
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	extend(config, oldconfig);
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	config.blocking = false;
6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var userAgent = id("qunit-userAgent");
6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( userAgent ) {
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		userAgent.innerHTML = navigator.userAgent;
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var banner = id("qunit-header");
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( banner ) {
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		banner.innerHTML = '<a href="' + QUnit.url({ filter: undefined }) + '"> ' + banner.innerHTML + '</a> ' +
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			'<label><input name="noglobals" type="checkbox"' + ( config.noglobals ? ' checked="checked"' : '' ) + '>noglobals</label>' +
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			'<label><input name="notrycatch" type="checkbox"' + ( config.notrycatch ? ' checked="checked"' : '' ) + '>notrycatch</label>';
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		addEvent( banner, "change", function( event ) {
6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var params = {};
6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			params[ event.target.name ] = event.target.checked ? true : undefined;
6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			window.location = QUnit.url( params );
6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		});
6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
6985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var toolbar = id("qunit-testrunner-toolbar");
7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( toolbar ) {
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var filter = document.createElement("input");
7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		filter.type = "checkbox";
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		filter.id = "qunit-filter-pass";
7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		addEvent( filter, "click", function() {
7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var ol = document.getElementById("qunit-tests");
7065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if ( filter.checked ) {
7075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				ol.className = ol.className + " hidepass";
7085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else {
7095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				var tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " ";
7105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				ol.className = tmp.replace(/ hidepass /, " ");
7115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
7125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if ( defined.sessionStorage ) {
7135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				if (filter.checked) {
7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					sessionStorage.setItem("qunit-filter-passed-tests",  "true");
7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				} else {
7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					sessionStorage.removeItem("qunit-filter-passed-tests");
7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				}
7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		});
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) {
7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			filter.checked = true;
7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var ol = document.getElementById("qunit-tests");
7235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			ol.className = ol.className + " hidepass";
7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		toolbar.appendChild( filter );
7265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var label = document.createElement("label");
7285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		label.setAttribute("for", "qunit-filter-pass");
7295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		label.innerHTML = "Hide passed tests";
7305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		toolbar.appendChild( label );
7315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
7325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var main = id('qunit-fixture');
7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( main ) {
7355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		config.fixture = main.innerHTML;
7365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
7375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if (config.autostart) {
7395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.start();
7405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
7415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)});
7425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function done() {
7445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	config.autorun = true;
7455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	// Log the last module results
7475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( config.currentModule ) {
7485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		QUnit.moduleDone( {
7495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			name: config.currentModule,
7505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			failed: config.moduleStats.bad,
7515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			passed: config.moduleStats.all - config.moduleStats.bad,
7525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			total: config.moduleStats.all
7535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} );
7545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
7555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var banner = id("qunit-banner"),
7575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		tests = id("qunit-tests"),
7585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		runtime = +new Date - config.started,
7595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		passed = config.stats.all - config.stats.bad,
7605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		html = [
7615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			'Tests completed in ',
7625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			runtime,
7635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			' milliseconds.<br/>',
7645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			'<span class="passed">',
7655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			passed,
7665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			'</span> tests of <span class="total">',
7675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			config.stats.all,
7685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			'</span> passed, <span class="failed">',
7695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			config.stats.bad,
7705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			'</span> failed.'
7715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		].join('');
7725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( banner ) {
7745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass");
7755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
7765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( tests ) {
7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		id( "qunit-testresult" ).innerHTML = html;
7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( typeof document !== "undefined" && document.title ) {
7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		// show ✖ for good, ✔ for bad suite result in title
7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		// use escape sequences in case file gets loaded with non-utf-8-charset
7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		document.title = (config.stats.bad ? "\u2716" : "\u2714") + " " + document.title;
7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	QUnit.done( {
7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		failed: config.stats.bad,
7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		passed: passed,
7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		total: config.stats.all,
7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		runtime: runtime
7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	} );
7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function validTest( name ) {
7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var filter = config.filter,
7975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		run = false;
7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( !filter ) {
8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		return true;
8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var not = filter.charAt( 0 ) === "!";
8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( not ) {
8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		filter = filter.slice( 1 );
8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( name.indexOf( filter ) !== -1 ) {
8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		return !not;
8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
8115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( not ) {
8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		run = true;
8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	return run;
8175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// so far supports only Firefox, Chrome and Opera (buggy)
8205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// could be extended in the future to use something like https://github.com/csnover/TraceKit
8215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function sourceFromStacktrace() {
8225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	try {
8235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		throw new Error();
8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	} catch ( e ) {
8255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (e.stacktrace) {
8265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// Opera
8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			return e.stacktrace.split("\n")[6];
8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} else if (e.stack) {
8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			// Firefox, Chrome
8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			return e.stack.split("\n")[4];
8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function escapeHtml(s) {
8365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if (!s) {
8375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		return "";
8385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	s = s + "";
8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	return s.replace(/[\&"<>\\]/g, function(s) {
8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		switch(s) {
8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			case "&": return "&amp;";
8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			case "\\": return "\\\\";
8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			case '"': return '\"';
8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			case "<": return "&lt;";
8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			case ">": return "&gt;";
8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			default: return s;
8485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
8495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	});
8505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function synchronize( callback ) {
8535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	config.queue.push( callback );
8545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( config.autorun && !config.blocking ) {
8565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		process();
8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
8585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function process() {
8615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var start = (new Date()).getTime();
8625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	while ( config.queue.length && !config.blocking ) {
8645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) {
8655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			config.queue.shift()();
8665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} else {
8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			window.setTimeout( process, 13 );
8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			break;
8695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
8705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
8715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (!config.blocking && !config.queue.length) {
8725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    done();
8735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
8745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function saveGlobal() {
8775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	config.pollution = [];
8785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( config.noglobals ) {
8805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		for ( var key in window ) {
8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			config.pollution.push( key );
8825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
8835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
8845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function checkPollution( name ) {
8875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var old = config.pollution;
8885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	saveGlobal();
8895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var newGlobals = diff( config.pollution, old );
8915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( newGlobals.length > 0 ) {
8925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		ok( false, "Introduced global variable(s): " + newGlobals.join(", ") );
8935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
8945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var deletedGlobals = diff( old, config.pollution );
8965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( deletedGlobals.length > 0 ) {
8975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") );
8985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
8995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// returns a new Array with the elements that are in a but not in b
9025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function diff( a, b ) {
9035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var result = a.slice();
9045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	for ( var i = 0; i < result.length; i++ ) {
9055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		for ( var j = 0; j < b.length; j++ ) {
9065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if ( result[i] === b[j] ) {
9075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				result.splice(i, 1);
9085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				i--;
9095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				break;
9105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
9115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
9125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
9135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	return result;
9145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function fail(message, exception, callback) {
9175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( typeof console !== "undefined" && console.error && console.warn ) {
9185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		console.error(message);
9195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		console.error(exception);
9205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		console.warn(callback.toString());
9215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	} else if ( window.opera && opera.postError ) {
9235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		opera.postError(message, exception, callback.toString);
9245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
9255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function extend(a, b) {
9285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	for ( var prop in b ) {
9295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( b[prop] === undefined ) {
9305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			delete a[prop];
9315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} else {
9325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			a[prop] = b[prop];
9335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
9345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
9355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	return a;
9375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function addEvent(elem, type, fn) {
9405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	if ( elem.addEventListener ) {
9415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		elem.addEventListener( type, fn, false );
9425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	} else if ( elem.attachEvent ) {
9435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		elem.attachEvent( "on" + type, fn );
9445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	} else {
9455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		fn();
9465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
9475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function id(name) {
9505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	return !!(typeof document !== "undefined" && document && document.getElementById) &&
9515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		document.getElementById( name );
9525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Test for equality any JavaScript type.
9555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Discussions and reference: http://philrathe.com/articles/equiv
9565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Test suites: http://philrathe.com/tests/equiv
9575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Author: Philippe Rathé <prathe@gmail.com>
9585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)QUnit.equiv = function () {
9595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var innerEquiv; // the real equiv function
9615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var callers = []; // stack to decide between skip/abort functions
9625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var parents = []; // stack to avoiding loops from circular referencing
9635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Call the o related callback with the given arguments.
9655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function bindCallbacks(o, callbacks, args) {
9665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var prop = QUnit.objectType(o);
9675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (prop) {
9685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (QUnit.objectType(callbacks[prop]) === "function") {
9695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return callbacks[prop].apply(callbacks, args);
9705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else {
9715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return callbacks[prop]; // or undefined
9725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
9735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
9745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var callbacks = function () {
9775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // for string, boolean, number and null
9795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function useStrictEquality(b, a) {
9805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (b instanceof a.constructor || a instanceof b.constructor) {
9815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // to catch short annotaion VS 'new' annotation of a declaration
9825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // e.g. var i = 1;
9835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                //      var j = new Number(1);
9845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return a == b;
9855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else {
9865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return a === b;
9875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
9885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
9895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return {
9915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            "string": useStrictEquality,
9925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            "boolean": useStrictEquality,
9935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            "number": useStrictEquality,
9945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            "null": useStrictEquality,
9955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            "undefined": useStrictEquality,
9965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            "nan": function (b) {
9985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return isNaN(b);
9995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            },
10005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            "date": function (b, a) {
10025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf();
10035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            },
10045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            "regexp": function (b, a) {
10065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return QUnit.objectType(b) === "regexp" &&
10075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    a.source === b.source && // the regex itself
10085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    a.global === b.global && // and its modifers (gmi) ...
10095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    a.ignoreCase === b.ignoreCase &&
10105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    a.multiline === b.multiline;
10115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            },
10125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // - skip when the property is a method of an instance (OOP)
10145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // - abort otherwise,
10155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            //   initial === would have catch identical references anyway
10165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            "function": function () {
10175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var caller = callers[callers.length - 1];
10185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return caller !== Object &&
10195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        typeof caller !== "undefined";
10205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            },
10215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            "array": function (b, a) {
10235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var i, j, loop;
10245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var len;
10255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // b could be an object literal here
10275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if ( ! (QUnit.objectType(b) === "array")) {
10285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return false;
10295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                len = a.length;
10325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (len !== b.length) { // safe and faster
10335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return false;
10345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                //track reference to avoid circular references
10375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                parents.push(a);
10385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for (i = 0; i < len; i++) {
10395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    loop = false;
10405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    for(j=0;j<parents.length;j++){
10415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if(parents[j] === a[i]){
10425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            loop = true;//dont rewalk array
10435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
10445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
10455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (!loop && ! innerEquiv(a[i], b[i])) {
10465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        parents.pop();
10475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return false;
10485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
10495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                parents.pop();
10515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return true;
10525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            },
10535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            "object": function (b, a) {
10555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var i, j, loop;
10565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var eq = true; // unless we can proove it
10575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var aProperties = [], bProperties = []; // collection of strings
10585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // comparing constructors is more strict than using instanceof
10605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if ( a.constructor !== b.constructor) {
10615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return false;
10625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // stack constructor before traversing properties
10655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                callers.push(a.constructor);
10665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                //track reference to avoid circular references
10675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                parents.push(a);
10685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for (i in a) { // be strict: don't ensures hasOwnProperty and go deep
10705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    loop = false;
10715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    for(j=0;j<parents.length;j++){
10725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if(parents[j] === a[i])
10735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            loop = true; //don't go down the same path twice
10745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
10755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    aProperties.push(i); // collect a's properties
10765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (!loop && ! innerEquiv(a[i], b[i])) {
10785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        eq = false;
10795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        break;
10805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
10815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                callers.pop(); // unstack, we are done
10845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                parents.pop();
10855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for (i in b) {
10875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    bProperties.push(i); // collect b's properties
10885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // Ensures identical properties name
10915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return eq && innerEquiv(aProperties.sort(), bProperties.sort());
10925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
10935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
10945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }();
10955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    innerEquiv = function () { // can take multiple arguments
10975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var args = Array.prototype.slice.apply(arguments);
10985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (args.length < 2) {
10995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true; // end transition
11005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return (function (a, b) {
11035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (a === b) {
11045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return true; // catch the most you can
11055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else if (a === null || b === null || typeof a === "undefined" || typeof b === "undefined" || QUnit.objectType(a) !== QUnit.objectType(b)) {
11065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false; // don't lose time with error prone cases
11075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else {
11085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return bindCallbacks(a, callbacks, [b, a]);
11095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
11105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // apply transition with (1..n) arguments
11125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        })(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length -1));
11135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
11145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return innerEquiv;
11165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}();
11185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
11205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * jsDump
11215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
11225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php)
11235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Date: 5/15/2008
11245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @projectDescription Advanced and extensible data dumping for Javascript.
11255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @version 1.0.0
11265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @author Ariel Flesler
11275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
11285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
11295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)QUnit.jsDump = (function() {
11305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	function quote( str ) {
11315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		return '"' + str.toString().replace(/"/g, '\\"') + '"';
11325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	};
11335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	function literal( o ) {
11345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		return o + '';
11355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	};
11365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	function join( pre, arr, post ) {
11375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var s = jsDump.separator(),
11385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			base = jsDump.indent(),
11395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			inner = jsDump.indent(1);
11405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( arr.join )
11415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			arr = arr.join( ',' + s + inner );
11425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( !arr )
11435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			return pre + post;
11445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		return [ pre, inner + arr, base + post ].join(s);
11455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	};
11465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	function array( arr ) {
11475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var i = arr.length,	ret = Array(i);
11485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		this.up();
11495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		while ( i-- )
11505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			ret[i] = this.parse( arr[i] );
11515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		this.down();
11525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		return join( '[', ret, ']' );
11535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	};
11545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var reName = /^function (\w+)/;
11565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var jsDump = {
11585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		parse:function( obj, type ) { //type is used mostly internally, you can fix a (custom)type in advance
11595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var	parser = this.parsers[ type || this.typeOf(obj) ];
11605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			type = typeof parser;
11615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			return type == 'function' ? parser.call( this, obj ) :
11635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				   type == 'string' ? parser :
11645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				   this.parsers.error;
11655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		},
11665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		typeOf:function( obj ) {
11675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var type;
11685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if ( obj === null ) {
11695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				type = "null";
11705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else if (typeof obj === "undefined") {
11715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				type = "undefined";
11725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else if (QUnit.is("RegExp", obj)) {
11735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				type = "regexp";
11745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else if (QUnit.is("Date", obj)) {
11755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				type = "date";
11765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else if (QUnit.is("Function", obj)) {
11775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				type = "function";
11785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else if (typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined") {
11795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				type = "window";
11805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else if (obj.nodeType === 9) {
11815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				type = "document";
11825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else if (obj.nodeType) {
11835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				type = "node";
11845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else if (typeof obj === "object" && typeof obj.length === "number" && obj.length >= 0) {
11855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				type = "array";
11865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			} else {
11875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				type = typeof obj;
11885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
11895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			return type;
11905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		},
11915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		separator:function() {
11925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			return this.multiline ?	this.HTML ? '<br />' : '\n' : this.HTML ? '&nbsp;' : ' ';
11935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		},
11945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing
11955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if ( !this.multiline )
11965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				return '';
11975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			var chr = this.indentChar;
11985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if ( this.HTML )
11995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				chr = chr.replace(/\t/g,'   ').replace(/ /g,'&nbsp;');
12005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			return Array( this._depth_ + (extra||0) ).join(chr);
12015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		},
12025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		up:function( a ) {
12035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			this._depth_ += a || 1;
12045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		},
12055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		down:function( a ) {
12065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			this._depth_ -= a || 1;
12075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		},
12085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		setParser:function( name, parser ) {
12095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			this.parsers[name] = parser;
12105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		},
12115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		// The next 3 are exposed so you can use them
12125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		quote:quote,
12135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		literal:literal,
12145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		join:join,
12155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		//
12165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		_depth_: 1,
12175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		// This is the list of parsers, to modify them, use jsDump.setParser
12185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		parsers:{
12195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			window: '[Window]',
12205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			document: '[Document]',
12215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			error:'[ERROR]', //when no parser is found, shouldn't happen
12225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			unknown: '[Unknown]',
12235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			'null':'null',
12245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			'undefined':'undefined',
12255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			'function':function( fn ) {
12265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				var ret = 'function',
12275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE
12285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				if ( name )
12295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					ret += ' ' + name;
12305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				ret += '(';
12315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join('');
12335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' );
12345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			},
12355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			array: array,
12365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			nodelist: array,
12375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			arguments: array,
12385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			object:function( map ) {
12395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				var ret = [ ];
12405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				QUnit.jsDump.up();
12415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				for ( var key in map )
12425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(map[key]) );
12435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				QUnit.jsDump.down();
12445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				return join( '{', ret, '}' );
12455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			},
12465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			node:function( node ) {
12475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				var open = QUnit.jsDump.HTML ? '&lt;' : '<',
12485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					close = QUnit.jsDump.HTML ? '&gt;' : '>';
12495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				var tag = node.nodeName.toLowerCase(),
12515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					ret = open + tag;
12525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				for ( var a in QUnit.jsDump.DOMAttrs ) {
12545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					var val = node[QUnit.jsDump.DOMAttrs[a]];
12555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					if ( val )
12565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)						ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' );
12575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				}
12585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				return ret + close + open + '/' + tag + close;
12595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			},
12605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function
12615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				var l = fn.length;
12625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				if ( !l ) return '';
12635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				var args = Array(l);
12655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				while ( l-- )
12665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					args[l] = String.fromCharCode(97+l);//97 is 'a'
12675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				return ' ' + args.join(', ') + ' ';
12685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			},
12695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			key:quote, //object calls it internally, the key part of an item in a map
12705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			functionCode:'[code]', //function calls it internally, it's the content of the function
12715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			attribute:quote, //node calls it internally, it's an html attribute value
12725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			string:quote,
12735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			date:quote,
12745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			regexp:literal, //regex
12755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			number:literal,
12765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			'boolean':literal
12775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		},
12785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		DOMAttrs:{//attributes to dump from nodes, name=>realName
12795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			id:'id',
12805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			name:'name',
12815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			'class':'className'
12825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		},
12835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		HTML:false,//if true, entities are escaped ( <, >, \t, space and \n )
12845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		indentChar:'  ',//indentation unit
12855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		multiline:true //if true, items in a collection, are separated by a \n, else just a space.
12865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	};
12875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	return jsDump;
12895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)})();
12905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// from Sizzle.js
12925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function getText( elems ) {
12935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	var ret = "", elem;
12945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	for ( var i = 0; elems[i]; i++ ) {
12965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		elem = elems[i];
12975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		// Get the text from text nodes and CDATA nodes
12995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
13005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			ret += elem.nodeValue;
13015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		// Traverse everything else, except comment nodes
13035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		} else if ( elem.nodeType !== 8 ) {
13045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			ret += getText( elem.childNodes );
13055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
13065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
13075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	return ret;
13095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
13105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
13125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Javascript Diff Algorithm
13135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  By John Resig (http://ejohn.org/)
13145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  Modified by Chu Alan "sprite"
13155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
13165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Released under the MIT license.
13175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
13185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * More Info:
13195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  http://ejohn.org/projects/javascript-diff-algorithm/
13205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
13215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Usage: QUnit.diff(expected, actual)
13225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
13235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
13245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
13255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)QUnit.diff = (function() {
13265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	function diff(o, n){
13275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var ns = new Object();
13285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var os = new Object();
13295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		for (var i = 0; i < n.length; i++) {
13315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if (ns[n[i]] == null)
13325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				ns[n[i]] = {
13335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					rows: new Array(),
13345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					o: null
13355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				};
13365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			ns[n[i]].rows.push(i);
13375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
13385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		for (var i = 0; i < o.length; i++) {
13405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if (os[o[i]] == null)
13415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				os[o[i]] = {
13425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					rows: new Array(),
13435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					n: null
13445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				};
13455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			os[o[i]].rows.push(i);
13465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
13475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		for (var i in ns) {
13495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {
13505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				n[ns[i].rows[0]] = {
13515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					text: n[ns[i].rows[0]],
13525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					row: os[i].rows[0]
13535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				};
13545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				o[os[i].rows[0]] = {
13555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					text: o[os[i].rows[0]],
13565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					row: ns[i].rows[0]
13575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				};
13585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
13595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
13605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		for (var i = 0; i < n.length - 1; i++) {
13625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null &&
13635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			n[i + 1] == o[n[i].row + 1]) {
13645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				n[i + 1] = {
13655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					text: n[i + 1],
13665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					row: n[i].row + 1
13675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				};
13685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				o[n[i].row + 1] = {
13695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					text: o[n[i].row + 1],
13705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					row: i + 1
13715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				};
13725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
13735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
13745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		for (var i = n.length - 1; i > 0; i--) {
13765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null &&
13775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			n[i - 1] == o[n[i].row - 1]) {
13785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				n[i - 1] = {
13795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					text: n[i - 1],
13805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					row: n[i].row - 1
13815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				};
13825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				o[n[i].row - 1] = {
13835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					text: o[n[i].row - 1],
13845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					row: i - 1
13855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				};
13865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
13875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
13885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		return {
13905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			o: o,
13915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			n: n
13925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		};
13935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	}
13945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	return function(o, n){
13965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		o = o.replace(/\s+$/, '');
13975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		n = n.replace(/\s+$/, '');
13985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/));
13995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var str = "";
14015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var oSpace = o.match(/\s+/g);
14035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (oSpace == null) {
14045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			oSpace = [" "];
14055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
14065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		else {
14075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			oSpace.push(" ");
14085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
14095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		var nSpace = n.match(/\s+/g);
14105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (nSpace == null) {
14115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			nSpace = [" "];
14125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
14135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		else {
14145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			nSpace.push(" ");
14155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
14165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		if (out.n.length == 0) {
14185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			for (var i = 0; i < out.o.length; i++) {
14195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				str += '<del>' + out.o[i] + oSpace[i] + "</del>";
14205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
14215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
14225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		else {
14235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			if (out.n[0].text == null) {
14245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
14255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					str += '<del>' + out.o[n] + oSpace[n] + "</del>";
14265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				}
14275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
14285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			for (var i = 0; i < out.n.length; i++) {
14305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				if (out.n[i].text == null) {
14315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					str += '<ins>' + out.n[i] + nSpace[i] + "</ins>";
14325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				}
14335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				else {
14345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					var pre = "";
14355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) {
14375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)						pre += '<del>' + out.o[n] + oSpace[n] + "</del>";
14385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					}
14395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					str += " " + out.n[i].text + nSpace[i] + pre;
14405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				}
14415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			}
14425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		}
14435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		return str;
14455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	};
14465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)})();
14475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)})(this);
1449