Skip to content

Commit

Permalink
let child suites run if parent is exclusive; closes #2378 (#2387)
Browse files Browse the repository at this point in the history
- includes some more refactoring of interface code into `lib/interfaces/common.js` for DRY (still more work to be done here)
- unfortunately said refactoring contains hellish logic which addresses this issue (someone should make a flowchart of this for lolz)
- original PR did not address `exports` interface; this doesn't either
- may need more coverage against `qunit` interface
  • Loading branch information
boneskull authored Jul 26, 2016
1 parent fb6ef8f commit 9ea2011
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 55 deletions.
30 changes: 16 additions & 14 deletions lib/interfaces/bdd.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* Module dependencies.
*/

var Suite = require('../suite');
var Test = require('../test');

/**
Expand All @@ -26,7 +25,7 @@ module.exports = function(suite) {
var suites = [suite];

suite.on('pre-require', function(context, file, mocha) {
var common = require('./common')(suites, context);
var common = require('./common')(suites, context, mocha);

context.before = common.before;
context.after = common.after;
Expand All @@ -40,32 +39,35 @@ module.exports = function(suite) {
*/

context.describe = context.context = function(title, fn) {
var suite = Suite.create(suites[0], title);
suite.file = file;
suites.unshift(suite);
fn.call(suite);
suites.shift();
return suite;
return common.suite.create({
title: title,
file: file,
fn: fn
});
};

/**
* Pending describe.
*/

context.xdescribe = context.xcontext = context.describe.skip = function(title, fn) {
var suite = Suite.create(suites[0], title);
suite.pending = true;
suites.unshift(suite);
fn.call(suite);
suites.shift();
return common.suite.skip({
title: title,
file: file,
fn: fn
});
};

/**
* Exclusive suite.
*/

context.describe.only = function(title, fn) {
return common.suite.only(mocha, context.describe(title, fn));
return common.suite.only({
title: title,
file: file,
fn: fn
});
};

/**
Expand Down
69 changes: 60 additions & 9 deletions lib/interfaces/common.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
'use strict';

var Suite = require('../suite');

/**
* Functions common to more than one interface.
*
* @param {Suite[]} suites
* @param {Context} context
* @param {Mocha} mocha
* @return {Object} An object containing common functions.
*/
module.exports = function(suites, context) {
module.exports = function(suites, context, mocha) {
return {
/**
* This is only present if flag --delay is passed into Mocha. It triggers
Expand Down Expand Up @@ -64,15 +67,60 @@ module.exports = function(suites, context) {

suite: {
/**
* Exclusive suite.
* Create an exclusive Suite; convenience function
* See docstring for create() below.
*
* @param {Object} mocha
* @param {Function} suite
* @param {Object} opts
* @returns {Suite}
*/

only: function(mocha, suite) {
suite.isOnly = true;
only: function only(opts) {
mocha.options.hasOnly = true;
opts.isOnly = true;
return this.create(opts);
},

/**
* Create a Suite, but skip it; convenience function
* See docstring for create() below.
*
* @param {Object} opts
* @returns {Suite}
*/
skip: function skip(opts) {
opts.pending = true;
return this.create(opts);
},

/**
* Creates a suite.
* @param {Object} opts Options
* @param {string} opts.title Title of Suite
* @param {Function} [opts.fn] Suite Function (not always applicable)
* @param {boolean} [opts.pending] Is Suite pending?
* @param {string} [opts.file] Filepath where this Suite resides
* @param {boolean} [opts.isOnly] Is Suite exclusive?
* @returns {Suite}
*/
create: function create(opts) {
var suite = Suite.create(suites[0], opts.title);
suite.pending = Boolean(opts.pending);
suite.file = opts.file;
suites.unshift(suite);
// I should be pilloried for the following.
if (opts.isOnly) {
if (suite.parent && suite.parent.onlyTests) {
suite.onlyTests = suite.parent.onlyTests === suite.parent.tests ? suite.tests : [];
} else {
suite.onlyTests = suite.tests;
}
} else {
suite.onlyTests = suite.parent && suite.parent.onlyTests === suite.parent.tests ? suite.tests : [];
}
if (typeof opts.fn === 'function') {
opts.fn.call(suite);
suites.shift();
}

return suite;
}
},
Expand All @@ -88,8 +136,11 @@ module.exports = function(suites, context) {
*/
only: function(mocha, test) {
var suite = test.parent;
suite.isOnly = true;
suite.onlyTests = (suite.onlyTests || []).concat(test);
if (suite.onlyTests === suite.tests) {
suite.onlyTests = [test];
} else {
suite.onlyTests = (suite.onlyTests || []).concat(test);
}
mocha.options.hasOnly = true;
return test;
},
Expand Down
23 changes: 14 additions & 9 deletions lib/interfaces/qunit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* Module dependencies.
*/

var Suite = require('../suite');
var Test = require('../test');

/**
Expand Down Expand Up @@ -34,7 +33,7 @@ module.exports = function(suite) {
var suites = [suite];

suite.on('pre-require', function(context, file, mocha) {
var common = require('./common')(suites, context);
var common = require('./common')(suites, context, mocha);

context.before = common.before;
context.after = common.after;
Expand All @@ -49,18 +48,24 @@ module.exports = function(suite) {
if (suites.length > 1) {
suites.shift();
}
var suite = Suite.create(suites[0], title);
suite.file = file;
suites.unshift(suite);
return suite;
return common.suite.create({
title: title,
file: file
});
};

/**
* Exclusive test-case.
* Exclusive Suite.
*/

context.suite.only = function(title, fn) {
return common.suite.only(mocha, context.suite(title, fn));
context.suite.only = function(title) {
if (suites.length > 1) {
suites.shift();
}
return common.suite.only({
title: title,
file: file
});
};

/**
Expand Down
30 changes: 16 additions & 14 deletions lib/interfaces/tdd.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* Module dependencies.
*/

var Suite = require('../suite');
var Test = require('../test');

/**
Expand Down Expand Up @@ -34,7 +33,7 @@ module.exports = function(suite) {
var suites = [suite];

suite.on('pre-require', function(context, file, mocha) {
var common = require('./common')(suites, context);
var common = require('./common')(suites, context, mocha);

context.setup = common.beforeEach;
context.teardown = common.afterEach;
Expand All @@ -47,30 +46,33 @@ module.exports = function(suite) {
* nested suites and/or tests.
*/
context.suite = function(title, fn) {
var suite = Suite.create(suites[0], title);
suite.file = file;
suites.unshift(suite);
fn.call(suite);
suites.shift();
return suite;
return common.suite.create({
title: title,
file: file,
fn: fn
});
};

/**
* Pending suite.
*/
context.suite.skip = function(title, fn) {
var suite = Suite.create(suites[0], title);
suite.pending = true;
suites.unshift(suite);
fn.call(suite);
suites.shift();
return common.suite.skip({
title: title,
file: file,
fn: fn
});
};

/**
* Exclusive test-case.
*/
context.suite.only = function(title, fn) {
return common.suite.only(mocha, context.suite(title, fn));
return common.suite.only({
title: title,
file: file,
fn: fn
});
};

/**
Expand Down
6 changes: 1 addition & 5 deletions lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -847,13 +847,9 @@ Runner.prototype.abort = function() {
*/
function filterOnly(suite) {
// If it has `only` tests, run only those
if (suite.onlyTests) {
suite.tests = suite.onlyTests;
}
suite.tests = suite.onlyTests ? suite.onlyTests : [];
// Filter the nested suites
suite.suites = filter(suite.suites, filterOnly);
// Don't run tests from suites that are not marked as `only`
suite.tests = suite.isOnly ? suite.tests : [];
// Keep the suite only if there is something to run
return suite.suites.length || suite.tests.length;
}
Expand Down
52 changes: 51 additions & 1 deletion test/integration/fixtures/options/only/bdd.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,54 @@ describe('should not run this suite', function() {
it('should not run this test', function() {
(true).should.equal(false);
});
});
});

describe.only('should run this suite too', function() {
describe('should run this nested suite', function () {
it('should run this test', function() {});

it('should run this test', function() {});

it('should run this test', function() {});
});
});

describe.only('should run this suite, even', function() {
describe('should run this nested suite, even', function () {
describe('should run this doubly-nested suite!', function () {
it('should run this test', function() {});

it('should run this test', function() {});

it('should run this test', function() {});
});
});
});


describe('should run this suite with an exclusive test', function() {
it.only('should run this test', function () {});

describe('should not run this nested suite', function () {
describe.only('should not run this doubly-nested suite', function () {
it('should not run this test', function() {});

it('should not run this test', function() {});

it('should not run this test', function() {});
});
});
});

describe('should run this suite with an exclusive test (reverse order)', function() {
describe('should not run this nested suite', function () {
describe.only('should not run this doubly-nested suite', function () {
it('should not run this test', function() {});

it('should not run this test', function() {});

it('should not run this test', function() {});
});
});
it.only('should run this test', function () {});
});
14 changes: 13 additions & 1 deletion test/integration/fixtures/options/only/tdd.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,16 @@ suite('should not run this suite', function() {
test('should not run this test', function() {
(true).should.equal(false);
});
});
});

suite.only('should run this suite too', function() {
suite('should run this nested suite', function () {
test('should run this test', function() {});

test('should run this test', function() {});

test('should run this test', function() {});

test('should run this test', function() {});
});
});
4 changes: 2 additions & 2 deletions test/integration/only.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('.only()', function() {
run('options/only/bdd.js', ['--ui', 'bdd'], function(err, res) {
assert(!err);
assert.equal(res.stats.pending, 0);
assert.equal(res.stats.passes, 3);
assert.equal(res.stats.passes, 11);
assert.equal(res.stats.failures, 0);
assert.equal(res.code, 0);
done();
Expand All @@ -17,7 +17,7 @@ describe('.only()', function() {
run('options/only/tdd.js', ['--ui', 'tdd'], function(err, res) {
assert(!err);
assert.equal(res.stats.pending, 0);
assert.equal(res.stats.passes, 4);
assert.equal(res.stats.passes, 8);
assert.equal(res.stats.failures, 0);
assert.equal(res.code, 0);
done();
Expand Down

0 comments on commit 9ea2011

Please sign in to comment.