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

Consistent handling of --forbid-only for suites and tests #4282

Merged
merged 7 commits into from Jun 5, 2020
15 changes: 10 additions & 5 deletions lib/interfaces/common.js
Expand Up @@ -94,6 +94,9 @@ module.exports = function(suites, context, mocha) {
* @returns {Suite}
*/
only: function only(opts) {
if (mocha.options.forbidOnly) {
throw createForbiddenExclusivityError(mocha);
}
opts.isOnly = true;
return this.create(opts);
},
Expand Down Expand Up @@ -130,12 +133,14 @@ module.exports = function(suites, context, mocha) {
if (mocha.options.forbidOnly && shouldBeTested(suite)) {
arvidOtt marked this conversation as resolved.
Show resolved Hide resolved
throw createForbiddenExclusivityError(mocha);
}
suite.parent.appendOnlySuite(suite);
suite.markOnly();
}
if (suite.pending) {
if (mocha.options.forbidPending && shouldBeTested(suite)) {
throw createUnsupportedError('Pending test forbidden');
}
if (
suite.pending &&
mocha.options.forbidPending &&
shouldBeTested(suite)
) {
throw createUnsupportedError('Pending test forbidden');
}
if (typeof opts.fn === 'function') {
opts.fn.call(suite);
Expand Down
9 changes: 9 additions & 0 deletions lib/suite.js
Expand Up @@ -491,6 +491,15 @@ Suite.prototype.appendOnlySuite = function(suite) {
this._onlySuites.push(suite);
};

/**
* Marks a suite to be `only`.
*
* @private
*/
Suite.prototype.markOnly = function() {
this.parent && this.parent.appendOnlySuite(this);
};

/**
* Adds a test to the list of tests marked `only`.
*
Expand Down
35 changes: 20 additions & 15 deletions test/integration/options/forbidOnly.spec.js
Expand Up @@ -92,32 +92,37 @@ describe('--forbid-only', function() {
);
});

it('should succeed if suite marked only does not match grep', function(done) {
it('should fail if suite marked only does not match grep', function(done) {
var fixture = path.join('options', 'forbid-only', 'only-suite');
runMochaJSON(fixture, args.concat('--fgrep', 'bumble bees'), function(
err,
res
) {
if (err) {
return done(err);
}
expect(res, 'to have passed');
done();
});
var spawnOpts = {stdio: 'pipe'};
runMocha(
fixture,
args.concat('--fgrep', 'bumble bees'),
function(err, res) {
if (err) {
return done(err);
}
expect(res, 'to have failed with output', new RegExp(onlyErrorMessage));
done();
},
spawnOpts
);
});

it('should succeed if suite marked only does not match inverted grep', function(done) {
it('should fail if suite marked only does not match inverted grep', function(done) {
var fixture = path.join('options', 'forbid-only', 'only-suite');
runMochaJSON(
var spawnOpts = {stdio: 'pipe'};
runMocha(
fixture,
args.concat('--fgrep', 'suite marked with only', '--invert'),
function(err, res) {
if (err) {
return done(err);
}
expect(res, 'to have passed');
expect(res, 'to have failed with output', new RegExp(onlyErrorMessage));
done();
}
},
spawnOpts
);
});

Expand Down
23 changes: 23 additions & 0 deletions test/unit/suite.spec.js
Expand Up @@ -680,6 +680,29 @@ describe('Suite', function() {
});
});
});

describe('.markOnly()', function() {
beforeEach(function() {
sandbox = sinon.createSandbox();
arvidOtt marked this conversation as resolved.
Show resolved Hide resolved
});

afterEach(function() {
sandbox.restore();
});

it('should call appendOnlySuite on parent', function() {
var suite = new Suite('foo');
var spy = sandbox.spy();
suite.parent = {
appendOnlySuite: spy
};
suite.markOnly();

expect(spy, 'to have a call exhaustively satisfying', [suite]).and(
'was called once'
);
});
});
});

describe('Test', function() {
Expand Down