diff --git a/reporter/html.js b/reporter/html.js
index 94de44c42..3f3068aea 100644
--- a/reporter/html.js
+++ b/reporter/html.js
@@ -668,6 +668,9 @@ QUnit.testDone(function( details ) {
time.innerHTML = details.runtime + " ms";
testItem.className = bad ? "fail" : "pass";
+ if ( details.skipped ) {
+ addClass( testItem, "skipped" );
+ }
testItem.insertBefore( time, assertList );
});
diff --git a/src/core.js b/src/core.js
index 3a9bf4fb5..166446660 100644
--- a/src/core.js
+++ b/src/core.js
@@ -117,15 +117,17 @@ QUnit = {
testName: testName,
expected: expected,
async: async,
- callback: callback,
- module: config.currentModule,
- moduleTestEnvironment: config.currentModuleTestEnvironment,
- stack: sourceFromStacktrace( 2 )
+ callback: callback
});
- if ( !validTest( test ) ) {
- return;
- }
+ test.queue();
+ },
+
+ skip: function( testName ) {
+ var test = new Test({
+ testName: testName,
+ skip: true
+ });
test.queue();
},
@@ -447,7 +449,7 @@ window.onerror = function( error, filePath, linerNr ) {
} else {
QUnit.test( "global failure", extend(function() {
QUnit.pushFailure( error, filePath + ":" + linerNr );
- }, { validTest: validTest } ) );
+ }, { validTest: true } ) );
}
return false;
}
@@ -481,47 +483,6 @@ function done() {
});
}
-/** @return Boolean: true if this test should be ran */
-function validTest( test ) {
- var include,
- filter = config.filter && config.filter.toLowerCase(),
- module = config.module && config.module.toLowerCase(),
- fullName = ( test.module + ": " + test.testName ).toLowerCase();
-
- // Internally-generated tests are always valid
- if ( test.callback && test.callback.validTest === validTest ) {
- delete test.callback.validTest;
- return true;
- }
-
- if ( config.testNumber.length > 0 ) {
- if ( inArray( test.testNumber, config.testNumber ) < 0 ) {
- return false;
- }
- }
-
- if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
- return false;
- }
-
- if ( !filter ) {
- return true;
- }
-
- include = filter.charAt( 0 ) !== "!";
- if ( !include ) {
- filter = filter.slice( 1 );
- }
-
- // If the filter matches, we need to honour include
- if ( fullName.indexOf( filter ) !== -1 ) {
- return include;
- }
-
- // Otherwise, do the opposite
- return !include;
-}
-
// Doesn't support IE6 to IE9
// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
function extractStacktrace( e, offset ) {
diff --git a/src/qunit.css b/src/qunit.css
index ca8fe3893..ed53ef64c 100644
--- a/src/qunit.css
+++ b/src/qunit.css
@@ -211,6 +211,11 @@
#qunit-banner.qunit-fail { background-color: #EE5757; }
+/*** Skipped tests */
+
+#qunit-tests .skipped {
+ background-color: #EBECE9;
+}
/** Result */
diff --git a/src/test.js b/src/test.js
index 92dd8bae0..01df7cc2e 100644
--- a/src/test.js
+++ b/src/test.js
@@ -1,8 +1,18 @@
function Test( settings ) {
extend( this, settings );
- this.assert = new Assert( this );
this.assertions = [];
this.testNumber = ++Test.count;
+ this.module = config.currentModule;
+ this.moduleTestEnvironment = config.currentModuleTestEnvironment;
+ this.stack = sourceFromStacktrace( 3 );
+
+ if ( settings.skip ) {
+ this.callback = function() {};
+ this.async = false;
+ this.expected = 0;
+ } else {
+ this.assert = new Assert( this );
+ }
}
Test.count = 0;
@@ -102,6 +112,11 @@ Test.prototype = {
hooks: function( handler ) {
var hooks = [];
+ // hooks are also ignored on skipped tests
+ if ( this.skip ) {
+ return hooks;
+ }
+
if ( QUnit.objectType( config[ handler ] ) === "function" ) {
hooks.push( this.queueHook( config[ handler ], handler ) );
}
@@ -139,6 +154,7 @@ Test.prototype = {
runLoggingCallbacks( "testDone", {
name: this.testName,
module: this.module,
+ skipped: !!this.skip,
failed: bad,
passed: this.assertions.length - bad,
total: this.assertions.length,
@@ -159,6 +175,10 @@ Test.prototype = {
var bad,
test = this;
+ if ( !this.valid() ) {
+ return;
+ }
+
function run() {
// each of these can by async
@@ -250,6 +270,47 @@ Test.prototype = {
result: false,
message: message
});
+ },
+
+ /** @return Boolean: true if this test should be ran */
+ valid: function() {
+ var include,
+ filter = config.filter && config.filter.toLowerCase(),
+ module = config.module && config.module.toLowerCase(),
+ fullName = ( this.module + ": " + this.testName ).toLowerCase();
+
+ // Internally-generated tests are always valid
+ if ( this.callback && this.callback.validTest ) {
+ delete this.callback.validTest;
+ return true;
+ }
+
+ if ( config.testNumber.length > 0 ) {
+ if ( inArray( this.testNumber, config.testNumber ) < 0 ) {
+ return false;
+ }
+ }
+
+ if ( module && ( !this.module || this.module.toLowerCase() !== module ) ) {
+ return false;
+ }
+
+ if ( !filter ) {
+ return true;
+ }
+
+ include = filter.charAt( 0 ) !== "!";
+ if ( !include ) {
+ filter = filter.slice( 1 );
+ }
+
+ // If the filter matches, we need to honour include
+ if ( fullName.indexOf( filter ) !== -1 ) {
+ return include;
+ }
+
+ // Otherwise, do the opposite
+ return !include;
}
};
diff --git a/test/logs.js b/test/logs.js
index 0739cc937..92b4e7e5b 100644
--- a/test/logs.js
+++ b/test/logs.js
@@ -150,7 +150,8 @@ QUnit.test( "test2", function( assert ) {
failed: 0,
passed: 17,
total: 17,
- testNumber: 1
+ testNumber: 1,
+ skipped: false
}, "testDone context" );
assert.deepEqual( testContext, {
module: "logs1",
diff --git a/test/test.js b/test/test.js
index 627560669..02abbd1ca 100644
--- a/test/test.js
+++ b/test/test.js
@@ -438,3 +438,25 @@ QUnit.test( "mod2", function( assert ) {
assert.mod2( 2, 0, "2 % 2 == 0" );
assert.mod2( 3, 1, "3 % 2 == 1" );
});
+
+QUnit.module( "QUnit.skip", {
+ beforeEach: function( assert ) {
+
+ // skip test hooks for skipped tests
+ assert.ok( false, "skipped function" );
+ throw "Error";
+ },
+ afterEach: function( assert ) {
+ assert.ok( false, "skipped function" );
+ throw "Error";
+ }
+});
+
+QUnit.skip( "test blocks are skipped", function( assert ) {
+
+ // this test callback won't run, even with broken code
+ assert.expect( 1000 );
+ throw "Error";
+});
+
+QUnit.skip( "no function" );