mirror of
https://github.com/jquery/jquery-ui.git
synced 2024-11-21 11:04:24 +00:00
Tests: Updated QUnit.
This commit is contained in:
parent
c96c249780
commit
3ce23223ae
94
external/qunit.css
vendored
94
external/qunit.css
vendored
@ -10,7 +10,7 @@
|
||||
|
||||
/** Resets */
|
||||
|
||||
#qunit-tests, #qunit-tests li ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
|
||||
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
@ -20,10 +20,13 @@
|
||||
|
||||
#qunit-header {
|
||||
padding: 0.5em 0 0.5em 1em;
|
||||
|
||||
color: #fff;
|
||||
text-shadow: rgba(0, 0, 0, 0.5) 4px 4px 1px;
|
||||
|
||||
color: #8699a4;
|
||||
background-color: #0d3349;
|
||||
|
||||
font-size: 1.5em;
|
||||
line-height: 1em;
|
||||
font-weight: normal;
|
||||
|
||||
border-radius: 15px 15px 0 0;
|
||||
-moz-border-radius: 15px 15px 0 0;
|
||||
@ -33,7 +36,12 @@
|
||||
|
||||
#qunit-header a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
color: #c2ccd1;
|
||||
}
|
||||
|
||||
#qunit-header a:hover,
|
||||
#qunit-header a:focus {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#qunit-banner {
|
||||
@ -41,7 +49,9 @@
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar {
|
||||
padding: 0em 0 0.5em 2em;
|
||||
padding: 0.5em 0 0.5em 2em;
|
||||
color: #5E740B;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
#qunit-userAgent {
|
||||
@ -68,7 +78,7 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#qunit-tests li ol {
|
||||
#qunit-tests ol {
|
||||
margin-top: 0.5em;
|
||||
padding: 0.5em;
|
||||
|
||||
@ -83,6 +93,45 @@
|
||||
-webkit-box-shadow: inset 0px 2px 13px #999;
|
||||
}
|
||||
|
||||
#qunit-tests table {
|
||||
border-collapse: collapse;
|
||||
margin-top: .2em;
|
||||
}
|
||||
|
||||
#qunit-tests th {
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
padding: 0 .5em 0 0;
|
||||
}
|
||||
|
||||
#qunit-tests td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#qunit-tests pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#qunit-tests del {
|
||||
background-color: #e0f2be;
|
||||
color: #374e0c;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#qunit-tests ins {
|
||||
background-color: #ffcaca;
|
||||
color: #500;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/*** Test Counts */
|
||||
|
||||
#qunit-tests b.counts { color: black; }
|
||||
#qunit-tests b.passed { color: #5E740B; }
|
||||
#qunit-tests b.failed { color: #710909; }
|
||||
|
||||
#qunit-tests li li {
|
||||
margin: 0.5em;
|
||||
padding: 0.4em 0.5em 0.4em 0.5em;
|
||||
@ -99,13 +148,11 @@
|
||||
border-left: 26px solid #C6E746;
|
||||
}
|
||||
|
||||
#qunit-tests li.pass { color: #528CE0; background-color: #D2E0E6; }
|
||||
#qunit-tests li.pass span.test-name { color: #366097; }
|
||||
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||
#qunit-tests .pass .test-name { color: #366097; }
|
||||
|
||||
#qunit-tests li li.pass span.test-actual,
|
||||
#qunit-tests li li.pass span.test-expected { color: #999999; }
|
||||
|
||||
strong b.pass { color: #5E740B; }
|
||||
#qunit-tests .pass .test-actual,
|
||||
#qunit-tests .pass .test-expected { color: #999999; }
|
||||
|
||||
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
||||
|
||||
@ -117,31 +164,28 @@ strong b.pass { color: #5E740B; }
|
||||
border-left: 26px solid #EE5757;
|
||||
}
|
||||
|
||||
#qunit-tests li.fail { color: #000000; background-color: #EE5757; }
|
||||
#qunit-tests li.fail span.test-name,
|
||||
#qunit-tests li.fail span.module-name { color: #000000; }
|
||||
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
||||
#qunit-tests .fail .test-name,
|
||||
#qunit-tests .fail .module-name { color: #000000; }
|
||||
|
||||
#qunit-tests li li.fail span.test-actual { color: #EE5757; }
|
||||
#qunit-tests li li.fail span.test-expected { color: green; }
|
||||
#qunit-tests .fail .test-actual { color: #EE5757; }
|
||||
#qunit-tests .fail .test-expected { color: green; }
|
||||
|
||||
strong b.fail { color: #710909; }
|
||||
|
||||
#qunit-banner.qunit-fail,
|
||||
#qunit-testrunner-toolbar { background-color: #EE5757; }
|
||||
#qunit-banner.qunit-fail { background-color: #EE5757; }
|
||||
|
||||
|
||||
/** Footer */
|
||||
|
||||
#qunit-testresult {
|
||||
padding: 0.5em 0.5em 0.5em 2.5em;
|
||||
|
||||
|
||||
color: #2b81af;
|
||||
background-color: #D2E0E6;
|
||||
|
||||
border-radius: 0 0 15px 15px;
|
||||
-moz-border-radius: 0 0 15px 15px;
|
||||
-webkit-border-bottom-right-radius: 15px;
|
||||
-webkit-border-bottom-left-radius: 15px;
|
||||
-webkit-border-bottom-left-radius: 15px;
|
||||
}
|
||||
|
||||
/** Fixture */
|
||||
@ -150,4 +194,4 @@ strong b.fail { color: #710909; }
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
}
|
||||
}
|
730
external/qunit.js
vendored
730
external/qunit.js
vendored
@ -3,30 +3,246 @@
|
||||
*
|
||||
* http://docs.jquery.com/QUnit
|
||||
*
|
||||
* Copyright (c) 2009 John Resig, Jörn Zaefferer
|
||||
* Copyright (c) 2011 John Resig, Jörn Zaefferer
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
* or GPL (GPL-LICENSE.txt) licenses.
|
||||
*/
|
||||
|
||||
(function(window) {
|
||||
|
||||
var defined = {
|
||||
setTimeout: typeof window.setTimeout !== "undefined",
|
||||
sessionStorage: (function() {
|
||||
try {
|
||||
return !!sessionStorage.getItem;
|
||||
} catch(e){
|
||||
return false;
|
||||
}
|
||||
})()
|
||||
}
|
||||
|
||||
var testId = 0;
|
||||
|
||||
var Test = function(name, testName, expected, testEnvironmentArg, async, callback) {
|
||||
this.name = name;
|
||||
this.testName = testName;
|
||||
this.expected = expected;
|
||||
this.testEnvironmentArg = testEnvironmentArg;
|
||||
this.async = async;
|
||||
this.callback = callback;
|
||||
this.assertions = [];
|
||||
};
|
||||
Test.prototype = {
|
||||
init: function() {
|
||||
var tests = id("qunit-tests");
|
||||
if (tests) {
|
||||
var b = document.createElement("strong");
|
||||
b.innerHTML = "Running " + this.name;
|
||||
var li = document.createElement("li");
|
||||
li.appendChild( b );
|
||||
li.id = this.id = "test-output" + testId++;
|
||||
tests.appendChild( li );
|
||||
}
|
||||
},
|
||||
setup: function() {
|
||||
if (this.module != config.previousModule) {
|
||||
if ( config.previousModule ) {
|
||||
QUnit.moduleDone( {
|
||||
name: config.previousModule,
|
||||
failed: config.moduleStats.bad,
|
||||
passed: config.moduleStats.all - config.moduleStats.bad,
|
||||
total: config.moduleStats.all
|
||||
} );
|
||||
}
|
||||
config.previousModule = this.module;
|
||||
config.moduleStats = { all: 0, bad: 0 };
|
||||
QUnit.moduleStart( {
|
||||
name: this.module
|
||||
} );
|
||||
}
|
||||
|
||||
config.current = this;
|
||||
this.testEnvironment = extend({
|
||||
setup: function() {},
|
||||
teardown: function() {}
|
||||
}, this.moduleTestEnvironment);
|
||||
if (this.testEnvironmentArg) {
|
||||
extend(this.testEnvironment, this.testEnvironmentArg);
|
||||
}
|
||||
|
||||
QUnit.testStart( {
|
||||
name: this.testName
|
||||
} );
|
||||
|
||||
// allow utility functions to access the current test environment
|
||||
// TODO why??
|
||||
QUnit.current_testEnvironment = this.testEnvironment;
|
||||
|
||||
try {
|
||||
if ( !config.pollution ) {
|
||||
saveGlobal();
|
||||
}
|
||||
|
||||
this.testEnvironment.setup.call(this.testEnvironment);
|
||||
} catch(e) {
|
||||
QUnit.ok( false, "Setup failed on " + this.testName + ": " + e.message );
|
||||
}
|
||||
},
|
||||
run: function() {
|
||||
if ( this.async ) {
|
||||
QUnit.stop();
|
||||
}
|
||||
|
||||
if ( config.notrycatch ) {
|
||||
this.callback.call(this.testEnvironment);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.callback.call(this.testEnvironment);
|
||||
} catch(e) {
|
||||
fail("Test " + this.testName + " died, exception and test follows", e, this.callback);
|
||||
QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) );
|
||||
// else next test will carry the responsibility
|
||||
saveGlobal();
|
||||
|
||||
// Restart the tests if they're blocking
|
||||
if ( config.blocking ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
},
|
||||
teardown: function() {
|
||||
try {
|
||||
checkPollution();
|
||||
this.testEnvironment.teardown.call(this.testEnvironment);
|
||||
} catch(e) {
|
||||
QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message );
|
||||
}
|
||||
},
|
||||
finish: function() {
|
||||
if ( this.expected && this.expected != this.assertions.length ) {
|
||||
QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" );
|
||||
}
|
||||
|
||||
var good = 0, bad = 0,
|
||||
tests = id("qunit-tests");
|
||||
|
||||
config.stats.all += this.assertions.length;
|
||||
config.moduleStats.all += this.assertions.length;
|
||||
|
||||
if ( tests ) {
|
||||
var ol = document.createElement("ol");
|
||||
|
||||
for ( var i = 0; i < this.assertions.length; i++ ) {
|
||||
var assertion = this.assertions[i];
|
||||
|
||||
var li = document.createElement("li");
|
||||
li.className = assertion.result ? "pass" : "fail";
|
||||
li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed");
|
||||
ol.appendChild( li );
|
||||
|
||||
if ( assertion.result ) {
|
||||
good++;
|
||||
} else {
|
||||
bad++;
|
||||
config.stats.bad++;
|
||||
config.moduleStats.bad++;
|
||||
}
|
||||
}
|
||||
|
||||
// store result when possible
|
||||
defined.sessionStorage && sessionStorage.setItem("qunit-" + this.testName, bad);
|
||||
|
||||
if (bad == 0) {
|
||||
ol.style.display = "none";
|
||||
}
|
||||
|
||||
var b = document.createElement("strong");
|
||||
b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
|
||||
|
||||
addEvent(b, "click", function() {
|
||||
var next = b.nextSibling, display = next.style.display;
|
||||
next.style.display = display === "none" ? "block" : "none";
|
||||
});
|
||||
|
||||
addEvent(b, "dblclick", function(e) {
|
||||
var target = e && e.target ? e.target : window.event.srcElement;
|
||||
if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
|
||||
target = target.parentNode;
|
||||
}
|
||||
if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
|
||||
window.location.search = "?" + encodeURIComponent(getText([target]).replace(/\(.+\)$/, "").replace(/(^\s*|\s*$)/g, ""));
|
||||
}
|
||||
});
|
||||
|
||||
var li = id(this.id);
|
||||
li.className = bad ? "fail" : "pass";
|
||||
li.style.display = resultDisplayStyle(!bad);
|
||||
li.removeChild( li.firstChild );
|
||||
li.appendChild( b );
|
||||
li.appendChild( ol );
|
||||
|
||||
} else {
|
||||
for ( var i = 0; i < this.assertions.length; i++ ) {
|
||||
if ( !this.assertions[i].result ) {
|
||||
bad++;
|
||||
config.stats.bad++;
|
||||
config.moduleStats.bad++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
QUnit.reset();
|
||||
} catch(e) {
|
||||
fail("reset() failed, following Test " + this.testName + ", exception and reset fn follows", e, QUnit.reset);
|
||||
}
|
||||
|
||||
QUnit.testDone( {
|
||||
name: this.testName,
|
||||
failed: bad,
|
||||
passed: this.assertions.length - bad,
|
||||
total: this.assertions.length
|
||||
} );
|
||||
},
|
||||
|
||||
queue: function() {
|
||||
var test = this;
|
||||
synchronize(function() {
|
||||
test.init();
|
||||
});
|
||||
function run() {
|
||||
// each of these can by async
|
||||
synchronize(function() {
|
||||
test.setup();
|
||||
});
|
||||
synchronize(function() {
|
||||
test.run();
|
||||
});
|
||||
synchronize(function() {
|
||||
test.teardown();
|
||||
});
|
||||
synchronize(function() {
|
||||
test.finish();
|
||||
});
|
||||
}
|
||||
// defer when previous test run passed, if storage is available
|
||||
var bad = defined.sessionStorage && +sessionStorage.getItem("qunit-" + this.testName);
|
||||
if (bad) {
|
||||
run();
|
||||
} else {
|
||||
synchronize(run);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var QUnit = {
|
||||
|
||||
// call on start of module test to prepend name to all tests
|
||||
module: function(name, testEnvironment) {
|
||||
config.currentModule = name;
|
||||
|
||||
synchronize(function() {
|
||||
if ( config.currentModule ) {
|
||||
QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
|
||||
}
|
||||
|
||||
config.currentModule = name;
|
||||
config.moduleTestEnvironment = testEnvironment;
|
||||
config.moduleStats = { all: 0, bad: 0 };
|
||||
|
||||
QUnit.moduleStart( name, testEnvironment );
|
||||
});
|
||||
config.currentModuleTestEnviroment = testEnvironment;
|
||||
},
|
||||
|
||||
asyncTest: function(testName, expected, callback) {
|
||||
@ -39,7 +255,7 @@ var QUnit = {
|
||||
},
|
||||
|
||||
test: function(testName, expected, callback, async) {
|
||||
var name = '<span class="test-name">' + testName + '</span>', testEnvironment, testEnvironmentArg;
|
||||
var name = '<span class="test-name">' + testName + '</span>', testEnvironmentArg;
|
||||
|
||||
if ( arguments.length === 2 ) {
|
||||
callback = expected;
|
||||
@ -58,174 +274,18 @@ var QUnit = {
|
||||
if ( !validTest(config.currentModule + ": " + testName) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronize(function() {
|
||||
|
||||
testEnvironment = extend({
|
||||
setup: function() {},
|
||||
teardown: function() {}
|
||||
}, config.moduleTestEnvironment);
|
||||
if (testEnvironmentArg) {
|
||||
extend(testEnvironment,testEnvironmentArg);
|
||||
}
|
||||
|
||||
QUnit.testStart( testName, testEnvironment );
|
||||
|
||||
// allow utility functions to access the current test environment
|
||||
QUnit.current_testEnvironment = testEnvironment;
|
||||
|
||||
config.assertions = [];
|
||||
config.expected = expected;
|
||||
|
||||
var tests = id("qunit-tests");
|
||||
if (tests) {
|
||||
var b = document.createElement("strong");
|
||||
b.innerHTML = "Running " + name;
|
||||
var li = document.createElement("li");
|
||||
li.appendChild( b );
|
||||
li.id = "current-test-output";
|
||||
tests.appendChild( li )
|
||||
}
|
||||
|
||||
try {
|
||||
if ( !config.pollution ) {
|
||||
saveGlobal();
|
||||
}
|
||||
|
||||
testEnvironment.setup.call(testEnvironment);
|
||||
} catch(e) {
|
||||
QUnit.ok( false, "Setup failed on " + name + ": " + e.message );
|
||||
}
|
||||
});
|
||||
|
||||
synchronize(function() {
|
||||
if ( async ) {
|
||||
QUnit.stop();
|
||||
}
|
||||
|
||||
try {
|
||||
callback.call(testEnvironment);
|
||||
} catch(e) {
|
||||
fail("Test " + name + " died, exception and test follows", e, callback);
|
||||
QUnit.ok( false, "Died on test #" + (config.assertions.length + 1) + ": " + e.message );
|
||||
// else next test will carry the responsibility
|
||||
saveGlobal();
|
||||
|
||||
// Restart the tests if they're blocking
|
||||
if ( config.blocking ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
synchronize(function() {
|
||||
try {
|
||||
checkPollution();
|
||||
testEnvironment.teardown.call(testEnvironment);
|
||||
} catch(e) {
|
||||
QUnit.ok( false, "Teardown failed on " + name + ": " + e.message );
|
||||
}
|
||||
});
|
||||
|
||||
synchronize(function() {
|
||||
try {
|
||||
QUnit.reset();
|
||||
} catch(e) {
|
||||
fail("reset() failed, following Test " + name + ", exception and reset fn follows", e, reset);
|
||||
}
|
||||
|
||||
if ( config.expected && config.expected != config.assertions.length ) {
|
||||
QUnit.ok( false, "Expected " + config.expected + " assertions, but " + config.assertions.length + " were run" );
|
||||
}
|
||||
|
||||
var good = 0, bad = 0,
|
||||
tests = id("qunit-tests");
|
||||
|
||||
config.stats.all += config.assertions.length;
|
||||
config.moduleStats.all += config.assertions.length;
|
||||
|
||||
if ( tests ) {
|
||||
var ol = document.createElement("ol");
|
||||
|
||||
for ( var i = 0; i < config.assertions.length; i++ ) {
|
||||
var assertion = config.assertions[i];
|
||||
|
||||
var li = document.createElement("li");
|
||||
li.className = assertion.result ? "pass" : "fail";
|
||||
li.innerHTML = assertion.message || "(no message)";
|
||||
ol.appendChild( li );
|
||||
|
||||
if ( assertion.result ) {
|
||||
good++;
|
||||
} else {
|
||||
bad++;
|
||||
config.stats.bad++;
|
||||
config.moduleStats.bad++;
|
||||
}
|
||||
}
|
||||
if (bad == 0) {
|
||||
ol.style.display = "none";
|
||||
}
|
||||
|
||||
var b = document.createElement("strong");
|
||||
b.innerHTML = name + " <b style='color:black;'>(<b class='fail'>" + bad + "</b>, <b class='pass'>" + good + "</b>, " + config.assertions.length + ")</b>";
|
||||
|
||||
addEvent(b, "click", function() {
|
||||
var next = b.nextSibling, display = next.style.display;
|
||||
next.style.display = display === "none" ? "block" : "none";
|
||||
});
|
||||
|
||||
addEvent(b, "dblclick", function(e) {
|
||||
var target = e && e.target ? e.target : window.event.srcElement;
|
||||
if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
|
||||
target = target.parentNode;
|
||||
}
|
||||
if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
|
||||
window.location.search = "?" + encodeURIComponent(getText([target]).replace(/\(.+\)$/, "").replace(/(^\s*|\s*$)/g, ""));
|
||||
}
|
||||
});
|
||||
|
||||
var li = id("current-test-output");
|
||||
li.id = "";
|
||||
li.className = bad ? "fail" : "pass";
|
||||
li.removeChild( li.firstChild );
|
||||
li.appendChild( b );
|
||||
li.appendChild( ol );
|
||||
|
||||
if ( bad ) {
|
||||
var toolbar = id("qunit-testrunner-toolbar");
|
||||
if ( toolbar ) {
|
||||
toolbar.style.display = "block";
|
||||
id("qunit-filter-pass").disabled = null;
|
||||
id("qunit-filter-missing").disabled = null;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for ( var i = 0; i < config.assertions.length; i++ ) {
|
||||
if ( !config.assertions[i].result ) {
|
||||
bad++;
|
||||
config.stats.bad++;
|
||||
config.moduleStats.bad++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QUnit.testDone( testName, bad, config.assertions.length );
|
||||
|
||||
if ( !window.setTimeout && !config.queue.length ) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
synchronize( done );
|
||||
|
||||
var test = new Test(name, testName, expected, testEnvironmentArg, async, callback);
|
||||
test.module = config.currentModule;
|
||||
test.moduleTestEnvironment = config.currentModuleTestEnviroment;
|
||||
test.queue();
|
||||
},
|
||||
|
||||
/**
|
||||
* Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
|
||||
*/
|
||||
expect: function(asserts) {
|
||||
config.expected = asserts;
|
||||
config.current.expected = asserts;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -233,11 +293,15 @@ var QUnit = {
|
||||
* @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
|
||||
*/
|
||||
ok: function(a, msg) {
|
||||
a = !!a;
|
||||
var details = {
|
||||
result: a,
|
||||
message: msg
|
||||
};
|
||||
msg = escapeHtml(msg);
|
||||
QUnit.log(a, msg);
|
||||
|
||||
config.assertions.push({
|
||||
result: !!a,
|
||||
QUnit.log(details);
|
||||
config.current.assertions.push({
|
||||
result: a,
|
||||
message: msg
|
||||
});
|
||||
},
|
||||
@ -255,42 +319,74 @@ var QUnit = {
|
||||
* @param String message (optional)
|
||||
*/
|
||||
equal: function(actual, expected, message) {
|
||||
push(expected == actual, actual, expected, message);
|
||||
QUnit.push(expected == actual, actual, expected, message);
|
||||
},
|
||||
|
||||
notEqual: function(actual, expected, message) {
|
||||
push(expected != actual, actual, expected, message);
|
||||
QUnit.push(expected != actual, actual, expected, message);
|
||||
},
|
||||
|
||||
deepEqual: function(actual, expected, message) {
|
||||
push(QUnit.equiv(actual, expected), actual, expected, message);
|
||||
QUnit.push(QUnit.equiv(actual, expected), actual, expected, message);
|
||||
},
|
||||
|
||||
notDeepEqual: function(actual, expected, message) {
|
||||
push(!QUnit.equiv(actual, expected), actual, expected, message);
|
||||
QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message);
|
||||
},
|
||||
|
||||
strictEqual: function(actual, expected, message) {
|
||||
push(expected === actual, actual, expected, message);
|
||||
QUnit.push(expected === actual, actual, expected, message);
|
||||
},
|
||||
|
||||
notStrictEqual: function(actual, expected, message) {
|
||||
push(expected !== actual, actual, expected, message);
|
||||
QUnit.push(expected !== actual, actual, expected, message);
|
||||
},
|
||||
|
||||
raises: function(fn, message) {
|
||||
raises: function(block, expected, message) {
|
||||
var actual, ok = false;
|
||||
|
||||
if (typeof expected === 'string') {
|
||||
message = expected;
|
||||
expected = null;
|
||||
}
|
||||
|
||||
try {
|
||||
fn();
|
||||
ok( false, message );
|
||||
block();
|
||||
} catch (e) {
|
||||
actual = e;
|
||||
}
|
||||
catch (e) {
|
||||
ok( true, message );
|
||||
|
||||
if (actual) {
|
||||
// we don't want to validate thrown error
|
||||
if (!expected) {
|
||||
ok = true;
|
||||
// expected is a regexp
|
||||
} else if (QUnit.objectType(expected) === "regexp") {
|
||||
ok = expected.test(actual);
|
||||
// expected is a constructor
|
||||
} else if (actual instanceof expected) {
|
||||
ok = true;
|
||||
// expected is a validation function which returns true is validation passed
|
||||
} else if (expected.call({}, actual) === true) {
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
QUnit.ok(ok, message);
|
||||
},
|
||||
|
||||
start: function() {
|
||||
config.semaphore--;
|
||||
if (config.semaphore > 0) {
|
||||
// don't start until equal number of stop-calls
|
||||
return;
|
||||
}
|
||||
if (config.semaphore < 0) {
|
||||
// ignore if start is called more often then stop
|
||||
config.semaphore = 0;
|
||||
}
|
||||
// A slight delay, to avoid any current callbacks
|
||||
if ( window.setTimeout ) {
|
||||
if ( defined.setTimeout ) {
|
||||
window.setTimeout(function() {
|
||||
if ( config.timeout ) {
|
||||
clearTimeout(config.timeout);
|
||||
@ -306,9 +402,11 @@ var QUnit = {
|
||||
},
|
||||
|
||||
stop: function(timeout) {
|
||||
config.semaphore++;
|
||||
config.blocking = true;
|
||||
|
||||
if ( timeout && window.setTimeout ) {
|
||||
if ( timeout && defined.setTimeout ) {
|
||||
clearTimeout(config.timeout);
|
||||
config.timeout = window.setTimeout(function() {
|
||||
QUnit.ok( false, "Test timed out" );
|
||||
QUnit.start();
|
||||
@ -342,6 +440,10 @@ var config = {
|
||||
GETParams.splice( i, 1 );
|
||||
i--;
|
||||
config.noglobals = true;
|
||||
} else if ( GETParams[i] === "notrycatch" ) {
|
||||
GETParams.splice( i, 1 );
|
||||
i--;
|
||||
config.notrycatch = true;
|
||||
} else if ( GETParams[i].search('=') > -1 ) {
|
||||
GETParams.splice( i, 1 );
|
||||
i--;
|
||||
@ -379,9 +481,9 @@ extend(QUnit, {
|
||||
blocking: false,
|
||||
autostart: true,
|
||||
autorun: false,
|
||||
assertions: [],
|
||||
filters: [],
|
||||
queue: []
|
||||
queue: [],
|
||||
semaphore: 0
|
||||
});
|
||||
|
||||
var tests = id("qunit-tests"),
|
||||
@ -403,10 +505,17 @@ extend(QUnit, {
|
||||
|
||||
/**
|
||||
* Resets the test setup. Useful for tests that modify the DOM.
|
||||
*
|
||||
* If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
|
||||
*/
|
||||
reset: function() {
|
||||
if ( window.jQuery ) {
|
||||
jQuery("#main, #qunit-fixture").html( config.fixture );
|
||||
jQuery( "#main, #qunit-fixture" ).html( config.fixture );
|
||||
} else {
|
||||
var main = id( 'main' ) || id( 'qunit-fixture' );
|
||||
if ( main ) {
|
||||
main.innerHTML = config.fixture;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -469,14 +578,55 @@ extend(QUnit, {
|
||||
return undefined;
|
||||
},
|
||||
|
||||
// Logging callbacks
|
||||
push: function(result, actual, expected, message) {
|
||||
var details = {
|
||||
result: result,
|
||||
message: message,
|
||||
actual: actual,
|
||||
expected: expected
|
||||
};
|
||||
|
||||
message = escapeHtml(message) || (result ? "okay" : "failed");
|
||||
message = '<span class="test-message">' + message + "</span>";
|
||||
expected = escapeHtml(QUnit.jsDump.parse(expected));
|
||||
actual = escapeHtml(QUnit.jsDump.parse(actual));
|
||||
var output = message + '<table><tr class="test-expected"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>';
|
||||
if (actual != expected) {
|
||||
output += '<tr class="test-actual"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>';
|
||||
output += '<tr class="test-diff"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>';
|
||||
}
|
||||
if (!result) {
|
||||
var source = sourceFromStacktrace();
|
||||
if (source) {
|
||||
details.source = source;
|
||||
output += '<tr class="test-source"><th>Source: </th><td><pre>' + source +'</pre></td></tr>';
|
||||
}
|
||||
}
|
||||
output += "</table>";
|
||||
|
||||
QUnit.log(details);
|
||||
|
||||
config.current.assertions.push({
|
||||
result: !!result,
|
||||
message: output
|
||||
});
|
||||
},
|
||||
|
||||
// Logging callbacks; all receive a single argument with the listed properties
|
||||
// run test/logs.html for any related changes
|
||||
begin: function() {},
|
||||
done: function(failures, total) {},
|
||||
log: function(result, message) {},
|
||||
testStart: function(name, testEnvironment) {},
|
||||
testDone: function(name, failures, total) {},
|
||||
moduleStart: function(name, testEnvironment) {},
|
||||
moduleDone: function(name, failures, total) {}
|
||||
// done: { failed, passed, total, runtime }
|
||||
done: function() {},
|
||||
// log: { result, actual, expected, message }
|
||||
log: function() {},
|
||||
// testStart: { name }
|
||||
testStart: function() {},
|
||||
// testDone: { name, failed, passed, total }
|
||||
testDone: function() {},
|
||||
// moduleStart: { name }
|
||||
moduleStart: function() {},
|
||||
// moduleDone: { name, failed, passed, total }
|
||||
moduleDone: function() {}
|
||||
});
|
||||
|
||||
if ( typeof document === "undefined" || document.readyState === "complete" ) {
|
||||
@ -484,7 +634,7 @@ if ( typeof document === "undefined" || document.readyState === "complete" ) {
|
||||
}
|
||||
|
||||
addEvent(window, "load", function() {
|
||||
QUnit.begin();
|
||||
QUnit.begin({});
|
||||
|
||||
// Initialize the config, saving the execution queue
|
||||
var oldconfig = extend({}, config);
|
||||
@ -499,17 +649,23 @@ addEvent(window, "load", function() {
|
||||
}
|
||||
var banner = id("qunit-header");
|
||||
if ( banner ) {
|
||||
banner.innerHTML = '<a href="' + location.href + '">' + banner.innerHTML + '</a>';
|
||||
var paramsIndex = location.href.lastIndexOf(location.search);
|
||||
if ( paramsIndex > -1 ) {
|
||||
var mainPageLocation = location.href.slice(0, paramsIndex);
|
||||
if ( mainPageLocation == location.href ) {
|
||||
banner.innerHTML = '<a href=""> ' + banner.innerHTML + '</a> ';
|
||||
} else {
|
||||
var testName = decodeURIComponent(location.search.slice(1));
|
||||
banner.innerHTML = '<a href="' + mainPageLocation + '">' + banner.innerHTML + '</a> › <a href="">' + testName + '</a>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var toolbar = id("qunit-testrunner-toolbar");
|
||||
if ( toolbar ) {
|
||||
toolbar.style.display = "none";
|
||||
|
||||
var filter = document.createElement("input");
|
||||
filter.type = "checkbox";
|
||||
filter.id = "qunit-filter-pass";
|
||||
filter.disabled = true;
|
||||
addEvent( filter, "click", function() {
|
||||
var li = document.getElementsByTagName("li");
|
||||
for ( var i = 0; i < li.length; i++ ) {
|
||||
@ -517,32 +673,19 @@ addEvent(window, "load", function() {
|
||||
li[i].style.display = filter.checked ? "none" : "";
|
||||
}
|
||||
}
|
||||
if ( defined.sessionStorage ) {
|
||||
sessionStorage.setItem("qunit-filter-passed-tests", filter.checked ? "true" : "");
|
||||
}
|
||||
});
|
||||
if ( defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) {
|
||||
filter.checked = true;
|
||||
}
|
||||
toolbar.appendChild( filter );
|
||||
|
||||
var label = document.createElement("label");
|
||||
label.setAttribute("for", "qunit-filter-pass");
|
||||
label.innerHTML = "Hide passed tests";
|
||||
toolbar.appendChild( label );
|
||||
|
||||
var missing = document.createElement("input");
|
||||
missing.type = "checkbox";
|
||||
missing.id = "qunit-filter-missing";
|
||||
missing.disabled = true;
|
||||
addEvent( missing, "click", function() {
|
||||
var li = document.getElementsByTagName("li");
|
||||
for ( var i = 0; i < li.length; i++ ) {
|
||||
if ( li[i].className.indexOf("fail") > -1 && li[i].innerHTML.indexOf('missing test - untested code is broken code') > - 1 ) {
|
||||
li[i].parentNode.parentNode.style.display = missing.checked ? "none" : "block";
|
||||
}
|
||||
}
|
||||
});
|
||||
toolbar.appendChild( missing );
|
||||
|
||||
label = document.createElement("label");
|
||||
label.setAttribute("for", "qunit-filter-missing");
|
||||
label.innerHTML = "Hide missing tests (untested code is broken code)";
|
||||
toolbar.appendChild( label );
|
||||
}
|
||||
|
||||
var main = id('main') || id('qunit-fixture');
|
||||
@ -556,35 +699,34 @@ addEvent(window, "load", function() {
|
||||
});
|
||||
|
||||
function done() {
|
||||
if ( config.doneTimer && window.clearTimeout ) {
|
||||
window.clearTimeout( config.doneTimer );
|
||||
config.doneTimer = null;
|
||||
}
|
||||
|
||||
if ( config.queue.length ) {
|
||||
config.doneTimer = window.setTimeout(function(){
|
||||
if ( !config.queue.length ) {
|
||||
done();
|
||||
} else {
|
||||
synchronize( done );
|
||||
}
|
||||
}, 13);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
config.autorun = true;
|
||||
|
||||
// Log the last module results
|
||||
if ( config.currentModule ) {
|
||||
QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
|
||||
QUnit.moduleDone( {
|
||||
name: config.currentModule,
|
||||
failed: config.moduleStats.bad,
|
||||
passed: config.moduleStats.all - config.moduleStats.bad,
|
||||
total: config.moduleStats.all
|
||||
} );
|
||||
}
|
||||
|
||||
var banner = id("qunit-banner"),
|
||||
tests = id("qunit-tests"),
|
||||
html = ['Tests completed in ',
|
||||
+new Date - config.started, ' milliseconds.<br/>',
|
||||
'<span class="passed">', config.stats.all - config.stats.bad, '</span> tests of <span class="total">', config.stats.all, '</span> passed, <span class="failed">', config.stats.bad,'</span> failed.'].join('');
|
||||
runtime = +new Date - config.started,
|
||||
passed = config.stats.all - config.stats.bad,
|
||||
html = [
|
||||
'Tests completed in ',
|
||||
runtime,
|
||||
' milliseconds.<br/>',
|
||||
'<span class="passed">',
|
||||
passed,
|
||||
'</span> tests of <span class="total">',
|
||||
config.stats.all,
|
||||
'</span> passed, <span class="failed">',
|
||||
config.stats.bad,
|
||||
'</span> failed.'
|
||||
].join('');
|
||||
|
||||
if ( banner ) {
|
||||
banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass");
|
||||
@ -603,7 +745,12 @@ function done() {
|
||||
result.innerHTML = html;
|
||||
}
|
||||
|
||||
QUnit.done( config.stats.bad, config.stats.all );
|
||||
QUnit.done( {
|
||||
failed: config.stats.bad,
|
||||
passed: passed,
|
||||
total: config.stats.all,
|
||||
runtime: runtime
|
||||
} );
|
||||
}
|
||||
|
||||
function validTest( name ) {
|
||||
@ -634,8 +781,31 @@ function validTest( name ) {
|
||||
return run;
|
||||
}
|
||||
|
||||
// so far supports only Firefox, Chrome and Opera (buggy)
|
||||
// could be extended in the future to use something like https://github.com/csnover/TraceKit
|
||||
function sourceFromStacktrace() {
|
||||
try {
|
||||
throw new Error();
|
||||
} catch ( e ) {
|
||||
if (e.stacktrace) {
|
||||
// Opera
|
||||
return e.stacktrace.split("\n")[6];
|
||||
} else if (e.stack) {
|
||||
// Firefox, Chrome
|
||||
return e.stack.split("\n")[4];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resultDisplayStyle(passed) {
|
||||
return passed && id("qunit-filter-pass") && id("qunit-filter-pass").checked ? 'none' : '';
|
||||
}
|
||||
|
||||
function escapeHtml(s) {
|
||||
s = s === null ? "" : s + "";
|
||||
if (!s) {
|
||||
return "";
|
||||
}
|
||||
s = s + "";
|
||||
return s.replace(/[\&"<>\\]/g, function(s) {
|
||||
switch(s) {
|
||||
case "&": return "&";
|
||||
@ -648,24 +818,6 @@ function escapeHtml(s) {
|
||||
});
|
||||
}
|
||||
|
||||
function push(result, actual, expected, message) {
|
||||
message = escapeHtml(message) || (result ? "okay" : "failed");
|
||||
message = '<span class="test-message">' + message + "</span>";
|
||||
expected = escapeHtml(QUnit.jsDump.parse(expected));
|
||||
actual = escapeHtml(QUnit.jsDump.parse(actual));
|
||||
var output = message + ', expected: <span class="test-expected">' + expected + '</span>';
|
||||
if (actual != expected) {
|
||||
output += ' result: <span class="test-actual">' + actual + '</span>, diff: ' + QUnit.diff(expected, actual);
|
||||
}
|
||||
|
||||
// can't use ok, as that would double-escape messages
|
||||
QUnit.log(result, output);
|
||||
config.assertions.push({
|
||||
result: !!result,
|
||||
message: output
|
||||
});
|
||||
}
|
||||
|
||||
function synchronize( callback ) {
|
||||
config.queue.push( callback );
|
||||
|
||||
@ -680,12 +832,14 @@ function process() {
|
||||
while ( config.queue.length && !config.blocking ) {
|
||||
if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) {
|
||||
config.queue.shift()();
|
||||
|
||||
} else {
|
||||
setTimeout( process, 13 );
|
||||
window.setTimeout( process, 13 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!config.blocking && !config.queue.length) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
function saveGlobal() {
|
||||
@ -705,13 +859,13 @@ function checkPollution( name ) {
|
||||
var newGlobals = diff( old, config.pollution );
|
||||
if ( newGlobals.length > 0 ) {
|
||||
ok( false, "Introduced global variable(s): " + newGlobals.join(", ") );
|
||||
config.expected++;
|
||||
config.current.expected++;
|
||||
}
|
||||
|
||||
var deletedGlobals = diff( config.pollution, old );
|
||||
if ( deletedGlobals.length > 0 ) {
|
||||
ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") );
|
||||
config.expected++;
|
||||
config.current.expected++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -988,7 +1142,7 @@ QUnit.jsDump = (function() {
|
||||
type = "date";
|
||||
} else if (QUnit.is("Function", obj)) {
|
||||
type = "function";
|
||||
} else if (obj.setInterval && obj.document && !obj.nodeType) {
|
||||
} else if (typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined") {
|
||||
type = "window";
|
||||
} else if (obj.nodeType === 9) {
|
||||
type = "document";
|
||||
@ -1042,31 +1196,31 @@ QUnit.jsDump = (function() {
|
||||
ret += ' ' + name;
|
||||
ret += '(';
|
||||
|
||||
ret = [ ret, this.parse( fn, 'functionArgs' ), '){'].join('');
|
||||
return join( ret, this.parse(fn,'functionCode'), '}' );
|
||||
ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join('');
|
||||
return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' );
|
||||
},
|
||||
array: array,
|
||||
nodelist: array,
|
||||
arguments: array,
|
||||
object:function( map ) {
|
||||
var ret = [ ];
|
||||
this.up();
|
||||
QUnit.jsDump.up();
|
||||
for ( var key in map )
|
||||
ret.push( this.parse(key,'key') + ': ' + this.parse(map[key]) );
|
||||
this.down();
|
||||
ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(map[key]) );
|
||||
QUnit.jsDump.down();
|
||||
return join( '{', ret, '}' );
|
||||
},
|
||||
node:function( node ) {
|
||||
var open = this.HTML ? '<' : '<',
|
||||
close = this.HTML ? '>' : '>';
|
||||
var open = QUnit.jsDump.HTML ? '<' : '<',
|
||||
close = QUnit.jsDump.HTML ? '>' : '>';
|
||||
|
||||
var tag = node.nodeName.toLowerCase(),
|
||||
ret = open + tag;
|
||||
|
||||
for ( var a in this.DOMAttrs ) {
|
||||
var val = node[this.DOMAttrs[a]];
|
||||
for ( var a in QUnit.jsDump.DOMAttrs ) {
|
||||
var val = node[QUnit.jsDump.DOMAttrs[a]];
|
||||
if ( val )
|
||||
ret += ' ' + a + '=' + this.parse( val, 'attribute' );
|
||||
ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' );
|
||||
}
|
||||
return ret + close + open + '/' + tag + close;
|
||||
},
|
||||
@ -1094,8 +1248,8 @@ QUnit.jsDump = (function() {
|
||||
'class':'className'
|
||||
},
|
||||
HTML:false,//if true, entities are escaped ( <, >, \t, space and \n )
|
||||
indentChar:' ',//indentation unit
|
||||
multiline:false //if true, items in a collection, are separated by a \n, else just a space.
|
||||
indentChar:' ',//indentation unit
|
||||
multiline:true //if true, items in a collection, are separated by a \n, else just a space.
|
||||
};
|
||||
|
||||
return jsDump;
|
||||
@ -1255,7 +1409,7 @@ QUnit.diff = (function() {
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
})(this);
|
||||
})(this);
|
Loading…
Reference in New Issue
Block a user