@@ -887,15 +887,9 @@ module.exports = function(suites, context, mocha) {
887
887
suite . pending = Boolean ( opts . pending ) ;
888
888
suite . file = opts . file ;
889
889
suites . unshift ( suite ) ;
890
- // I should be pilloried for the following.
891
890
if ( opts . isOnly ) {
892
- if ( suite . parent && suite . parent . onlyTests ) {
893
- suite . onlyTests = suite . parent . onlyTests === suite . parent . tests ? suite . tests : [ ] ;
894
- } else {
895
- suite . onlyTests = suite . tests ;
896
- }
897
- } else {
898
- suite . onlyTests = suite . parent && suite . parent . onlyTests === suite . parent . tests ? suite . tests : [ ] ;
891
+ suite . parent . _onlySuites = suite . parent . _onlySuites . concat ( suite ) ;
892
+ mocha . options . hasOnly = true ;
899
893
}
900
894
if ( typeof opts . fn === 'function' ) {
901
895
opts . fn . call ( suite ) ;
@@ -916,12 +910,7 @@ module.exports = function(suites, context, mocha) {
916
910
* @returns {* }
917
911
*/
918
912
only : function ( mocha , test ) {
919
- var suite = test . parent ;
920
- if ( suite . onlyTests === suite . tests ) {
921
- suite . onlyTests = [ test ] ;
922
- } else {
923
- suite . onlyTests = ( suite . onlyTests || [ ] ) . concat ( test ) ;
924
- }
913
+ test . parent . _onlyTests = test . parent . _onlyTests . concat ( test ) ;
925
914
mocha . options . hasOnly = true ;
926
915
return test ;
927
916
} ,
@@ -4417,6 +4406,7 @@ var debug = require('debug')('mocha:runner');
4417
4406
var Runnable = require ( './runnable' ) ;
4418
4407
var filter = utils . filter ;
4419
4408
var indexOf = utils . indexOf ;
4409
+ var some = utils . some ;
4420
4410
var keys = utils . keys ;
4421
4411
var stackFilter = utils . stackTraceFilter ( ) ;
4422
4412
var stringify = utils . stringify ;
@@ -5253,12 +5243,38 @@ Runner.prototype.abort = function() {
5253
5243
* @api private
5254
5244
*/
5255
5245
function filterOnly ( suite ) {
5256
- // If it has `only` tests, run only those
5257
- suite . tests = suite . onlyTests ? suite . onlyTests : [ ] ;
5258
- // Filter the nested suites
5259
- suite . suites = filter ( suite . suites , filterOnly ) ;
5246
+ if ( suite . _onlyTests . length ) {
5247
+ // If the suite contains `only` tests, run those and ignore any nested suites.
5248
+ suite . tests = suite . _onlyTests ;
5249
+ suite . suites = [ ] ;
5250
+ } else {
5251
+ // Otherwise, do not run any of the tests in this suite.
5252
+ suite . tests = [ ] ;
5253
+ suite . _onlySuites . forEach ( function ( onlySuite ) {
5254
+ // If there are other `only` tests/suites nested in the current `only` suite, then filter the current suite.
5255
+ // Otherwise, all of the tests on this `only` suite should be run, so don't filter it.
5256
+ if ( hasOnly ( onlySuite ) ) {
5257
+ filterOnly ( suite ) ;
5258
+ }
5259
+ } ) ;
5260
+ // Run the `only` suites, as well as any other suites that have `only` tests/suites as descendants.
5261
+ suite . suites = filter ( suite . suites , function ( childSuite ) {
5262
+ return indexOf ( suite . _onlySuites , childSuite ) !== - 1 || filterOnly ( childSuite ) ;
5263
+ } ) ;
5264
+ }
5260
5265
// Keep the suite only if there is something to run
5261
- return suite . suites . length || suite . tests . length ;
5266
+ return suite . tests . length || suite . suites . length ;
5267
+ }
5268
+
5269
+ /**
5270
+ * Determines whether a suite has an `only` test or suite as a descendant.
5271
+ *
5272
+ * @param {Array } suite
5273
+ * @returns {Boolean }
5274
+ * @api private
5275
+ */
5276
+ function hasOnly ( suite ) {
5277
+ return suite . _onlyTests . length || suite . _onlySuites . length || some ( suite . suites , hasOnly ) ;
5262
5278
}
5263
5279
5264
5280
/**
@@ -5392,6 +5408,8 @@ function Suite(title, parentContext) {
5392
5408
this . _slow = 75 ;
5393
5409
this . _bail = false ;
5394
5410
this . _retries = - 1 ;
5411
+ this . _onlyTests = [ ] ;
5412
+ this . _onlySuites = [ ] ;
5395
5413
this . delayed = false ;
5396
5414
}
5397
5415
@@ -5961,6 +5979,23 @@ exports.filter = function(arr, fn) {
5961
5979
return ret ;
5962
5980
} ;
5963
5981
5982
+ /**
5983
+ * Array#some (<=IE8)
5984
+ *
5985
+ * @api private
5986
+ * @param {Array } arr
5987
+ * @param {Function } fn
5988
+ * @return {Array }
5989
+ */
5990
+ exports . some = function ( arr , fn ) {
5991
+ for ( var i = 0 , l = arr . length ; i < l ; i ++ ) {
5992
+ if ( fn ( arr [ i ] ) ) {
5993
+ return true ;
5994
+ }
5995
+ }
5996
+ return false ;
5997
+ } ;
5998
+
5964
5999
/**
5965
6000
* Object.keys (<=IE8)
5966
6001
*
0 commit comments