Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(runner): fix '.only()' exclusive feature, #1481 #1591

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 17 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ lib-cov:

test: test-unit

test-all: test-bdd test-tdd test-qunit test-exports test-unit test-grep test-jsapi test-compilers test-sort test-glob test-requires test-reporters test-only test-failing test-regression
test-all: test-bdd test-tdd test-qunit test-exports test-unit test-grep test-jsapi test-compilers test-sort test-glob test-requires test-reporters test-global-only test-only test-failing test-regression

test-jsapi:
@node test/jsapi
Expand Down Expand Up @@ -164,6 +164,22 @@ test-only:
--ui qunit \
test/acceptance/misc/only/qunit

test-global-only:
@./bin/mocha \
--reporter $(REPORTER) \
--ui tdd \
test/acceptance/misc/global-only/tdd

@./bin/mocha \
--reporter $(REPORTER) \
--ui bdd \
test/acceptance/misc/global-only/bdd

@./bin/mocha \
--reporter $(REPORTER) \
--ui qunit \
test/acceptance/misc/global-only/qunit

test-sort:
@./bin/mocha \
--reporter $(REPORTER) \
Expand Down
13 changes: 8 additions & 5 deletions lib/interfaces/bdd.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ module.exports = function(suite){
* Exclusive suite.
*/

context.describe.only = function(title, fn){
context.describe.only = function(title, fn) {
var suite = context.describe(title, fn);
mocha.grep(suite.fullTitle());
mocha.options.hasOnly = true;
suite.isOnly = true;
return suite;
};

Expand All @@ -95,9 +96,11 @@ module.exports = function(suite){
*/

context.it.only = function(title, fn){
var test = context.it(title, fn);
var reString = '^' + escapeRe(test.fullTitle()) + '$';
mocha.grep(new RegExp(reString));
var test = context.it(title, fn)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

various places in this PR will need to be linted

, suite = test.parent;
mocha.options.hasOnly = true;
suite.isOnly = true;
suite.onlyTests = (suite.onlyTests || []).concat(test);
return test;
};

Expand Down
13 changes: 9 additions & 4 deletions lib/interfaces/qunit.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ module.exports = function(suite){

context.suite.only = function(title, fn){
var suite = context.suite(title, fn);
mocha.grep(suite.fullTitle());
mocha.options.hasOnly = true;
suite.isOnly = true;
return suite;
};

/**
Expand All @@ -83,9 +85,12 @@ module.exports = function(suite){
*/

context.test.only = function(title, fn){
var test = context.test(title, fn);
var reString = '^' + escapeRe(test.fullTitle()) + '$';
mocha.grep(new RegExp(reString));
var test = context.test(title, fn)
, suite = test.parent;
mocha.options.hasOnly = true;
suite.isOnly = true;
suite.onlyTests = (suite.onlyTests || []).concat(test);
return test;
};

context.test.skip = common.test.skip;
Expand Down
13 changes: 9 additions & 4 deletions lib/interfaces/tdd.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ module.exports = function(suite){

context.suite.only = function(title, fn){
var suite = context.suite(title, fn);
mocha.grep(suite.fullTitle());
mocha.options.hasOnly = true;
suite.isOnly = true;
return suite;
};

/**
Expand All @@ -99,9 +101,12 @@ module.exports = function(suite){
*/

context.test.only = function(title, fn){
var test = context.test(title, fn);
var reString = '^' + escapeRe(test.fullTitle()) + '$';
mocha.grep(new RegExp(reString));
var test = context.test(title, fn)
, suite = test.parent;
mocha.options.hasOnly = true;
suite.isOnly = true;
suite.onlyTests = (suite.onlyTests || []).concat(test);
return test;
};

context.test.skip = common.test.skip;
Expand Down
2 changes: 1 addition & 1 deletion lib/mocha.js
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ Mocha.prototype.run = function(fn){
var reporter = new this._reporter(runner, options);
runner.ignoreLeaks = false !== options.ignoreLeaks;
runner.fullStackTrace = options.fullStackTrace;
runner.hasOnly = options.hasOnly;
runner.asyncOnly = options.asyncOnly;
if (options.grep) runner.grep(options.grep, options.invert);
if (options.globals) runner.globals(options.globals);
Expand All @@ -441,6 +442,5 @@ Mocha.prototype.run = function(fn){
reporter.done(failures, fn);
} else fn && fn(failures);
}

return runner.run(done);
};
22 changes: 22 additions & 0 deletions lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ Runner.prototype.runSuite = function(suite, fn){
, self = this
, i = 0;


debug('run suite %s', suite.fullTitle());

if (!total) return fn();
Expand Down Expand Up @@ -606,6 +607,9 @@ Runner.prototype.run = function(fn){
var self = this,
rootSuite = this.suite;

// If there is an `only` filter
if (this.hasOnly) filterOnly(rootSuite);

fn = fn || function(){};

function uncaught(err){
Expand Down Expand Up @@ -656,6 +660,24 @@ Runner.prototype.abort = function(){
this._abort = true;
};

/**
* Filter suites based on `isOnly` logic.
*
* @param {Array} suite
* @returns {Boolean}
* @api private
*/
function filterOnly(suite) {
// If it has `only` tests, run only those
if (suite.onlyTests) suite.tests = 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;
}

/**
* Filter leaks with the given globals flagged as `ok`.
*
Expand Down
12 changes: 12 additions & 0 deletions test/acceptance/misc/global-only/bdd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Root-only test cases
it.only('#Root-Suite, should run this bdd test-case #1', function() {
(true).should.equal(true);
});

it('#Root-Suite, should not run this bdd test-case #2', function() {
(false).should.equal(true);
});

it('#Root-Suite, should not run this bdd test-case #3', function() {
(false).should.equal(true);
});
12 changes: 12 additions & 0 deletions test/acceptance/misc/global-only/qunit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Root-only test cases
test.only('#Root-Suite, should run this qunit test-case #1', function() {
(true).should.equal(true);
});

test('#Root-Suite, should not run this qunit test-case #2', function() {
(false).should.equal(true);
});

test('#Root-Suite, should not run this qunit test-case #3', function() {
(false).should.equal(true);
});
12 changes: 12 additions & 0 deletions test/acceptance/misc/global-only/tdd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Root-only test cases
test.only('#Root-Suite, should run this tdd test-case #1', function() {
(true).should.equal(true);
});

test('#Root-Suite, should not run this tdd test-case #2', function() {
(false).should.equal(true);
});

test('#Root-Suite, should not run this tdd test-case #3', function() {
(false).should.equal(true);
});
123 changes: 117 additions & 6 deletions test/acceptance/misc/only/bdd.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,125 @@
describe('should only run .only test in this bdd suite', function() {
it('should not run this test', function() {
var zero = 0;
zero.should.equal(1, 'this test should have been skipped');
(0).should.equal(1, 'this test should have been skipped');
});
it.only('should run this test', function() {
var zero = 0;
zero.should.equal(0, 'this .only test should run');
(0).should.equal(0, 'this .only test should run');
});
it('should run this test, not (includes the title of the .only test)', function() {
var zero = 0;
zero.should.equal(1, 'this test should have been skipped');
(0).should.equal(1, 'this test should have been skipped');
});
});

describe('should not run this suite', function() {
it('should not run this test', function() {
(true).should.equal(false);
});

it('should not run this test', function() {
(true).should.equal(false);
});

it('should not run this test', function() {
(true).should.equal(false);
});
});

describe.only('should run all tests in this bdd suite', function() {
it('should run this test #1', function() {
(true).should.equal(true);
});

it('should run this test #2', function() {
(1).should.equal(1);
});

it('should run this test #3', function() {
('foo').should.equal('foo');
});
});

describe('should run only suites that marked as `only`', function() {
describe.only('should run all this tdd suite', function() {
it('should run this test #1', function() {
(true).should.equal(true);
});

it('should run this test #2', function() {
(true).should.equal(true);
});
});

describe('should not run this suite', function() {
it('should run this test', function() {
(true).should.equal(false);
});
});
});

// Nested situation
describe('should not run parent tests', function() {
it('should not run this test', function() {
(true).should.equal(false);
});
describe('and not the child tests too', function() {
it('should not run this test', function() {
(true).should.equal(false);
});
describe.only('but run all the tests in this suite', function() {
it('should run this test #1', function() {
(true).should.equal(true);
});
it('should run this test #2', function() {
(true).should.equal(true);
});
});
});
});

// mark test as `only` override the suite behavior
describe.only('should run only tests that marked as `only`', function() {
it('should not run this test #1', function() {
(false).should.equal(true);
});

it.only('should run this test #2', function() {
(true).should.equal(true);
});

it('should not run this test #3', function() {
(false).should.equal(true);
});

it.only('should run this test #4', function() {
(true).should.equal(true);
});
});

describe.only('Should run only test cases that mark as only', function() {
it.only('should runt his test', function() {
(true).should.equal(true);
});

it('should not run this test', function() {
(false).should.equal(true);
});

describe('should not run this suite', function() {
it('should not run this test', function() {
(false).should.equal(true);
});
});
});

// Root Suite
it.only('#Root-Suite, should run this test-case #1', function() {
(true).should.equal(true);
});

it.only('#Root-Suite, should run this test-case #2', function() {
(true).should.equal(true);
});

it('#Root-Suite, should not run this test', function() {
(false).should.equal(true);
});