diff --git a/README.md b/README.md index 509495e..f283691 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,14 @@ This plugin ships with a default configuration for each rule: -Rule | Default | Options ----- | ------- | ------- -[no-focused-tests][] | 2 | -[no-disabled-tests][] | 1 | -[no-spec-dupes][] | 1, 'block' | ['block', 'branch'] -[no-suite-dupes][] | 1, 'block' | ['block', 'branch'] -[missing-expect][] | 0, 'expect()' | expectation function names +Rule | Default | Options +---- | ------- | ------- +[no-focused-tests][] | 2 | +[no-disabled-tests][] | 1 | +[no-spec-dupes][] | 1, 'block' | ['block', 'branch'] +[no-suite-dupes][] | 1, 'block' | ['block', 'branch'] +[no-suite-callback-args][] | 2 | +[missing-expect][] | 0, 'expect()' | expectation function names For example, the `no-focused-tests` rule is enabled by default and will cause ESLint to throw an error (with an exit code of `1`) when triggered. @@ -56,6 +57,7 @@ See [configuring rules][] for more information. [no-disabled-tests]: docs/rules/no-disabled-tests.md [no-spec-dupes]: docs/rules/no-spec-dupes.md [no-suite-dupes]: docs/rules/no-suite-dupes.md +[no-suite-callback-args]: docs/rules/no-suite-callback-args.md [missing-expect]: docs/rules/missing-expect.md [configuring rules]: http://eslint.org/docs/user-guide/configuring#configuring-rules diff --git a/docs/rules/no-suite-callback-args.md b/docs/rules/no-suite-callback-args.md new file mode 100644 index 0000000..2a1a76a --- /dev/null +++ b/docs/rules/no-suite-callback-args.md @@ -0,0 +1,66 @@ +# Enforce that a suites's callback does not contain any arguments + +Jasmine's specs takes an argument, normally called `done`, to enable +asynchronous testing. However, a suite is only a name or title, and contains +only specs, on assertions or expectations. + +Having a suite's callback take an argument and calling that in in a spec to +indicate completion of an asynchronous test is an error, and may cause +confusing errors in other parts of the code du to it's asynchronous nature + +## Rule details + +This rule triggers an **error** (is set to **2** by default) whenever it +encounters a suite's (`describe`) callback receiving an argument. + +The following patterns are considered errors: + +```js +describe('A suite', function(done) {}); + +describe('A suite', function(done) { + it('A spec', function() {}); +}); + +describe('A suite', function(done) { + it('A spec', function(done) {}); +}); + +describe('A suite', function(done) { + it('A spec', function(done) { + done(); + }); +}); + +fdescribe('A suite', function(done) {}); + +ddescribe('A suite', function(done) {}); + +xdescribe('A suite', function(done) {}); +``` + +The following patterns are not warnings: + +```js +describe('My suite', function() {}); + +describe('My suite', function() { + it('My spec', function() {}); +}); + +describe('My suite', function() { + it('My spec', function(done) {}); +}); + +describe('My suite', function() { + it('My spec', function(done) { + done(); + }); +}); + +fdescribe('My suite', function() {}); + +ddescribe('My suite', function() {}); + +xdescribe('My suite', function() {}); +``` diff --git a/index.js b/index.js index c3c4331..ea4a2fc 100644 --- a/index.js +++ b/index.js @@ -6,13 +6,15 @@ module.exports = { 'no-disabled-tests': require('./lib/rules/no-disabled-tests'), 'no-suite-dupes': require('./lib/rules/no-suite-dupes'), 'no-spec-dupes': require('./lib/rules/no-spec-dupes'), - 'missing-expect': require('./lib/rules/missing-expect') + 'missing-expect': require('./lib/rules/missing-expect'), + 'no-suite-callback-args': require('./lib/rules/no-suite-callback-args') }, rulesConfig: { 'no-focused-tests': 2, 'no-disabled-tests': 1, 'no-suite-dupes': 1, 'no-spec-dupes': 1, - 'missing-expect': 0 + 'missing-expect': 0, + 'no-suite-callback-args': 2 } }; diff --git a/lib/rules/no-suite-callback-args.js b/lib/rules/no-suite-callback-args.js new file mode 100644 index 0000000..929ba7c --- /dev/null +++ b/lib/rules/no-suite-callback-args.js @@ -0,0 +1,22 @@ +'use strict'; + +/** + * @fileoverview Enforce that a suites's callback does not contain any arguments + * @author Simen Bekkhus + */ + +var suiteRegexp = /^(f|d|x)?describe$/; + +module.exports = function(context) { + return { + CallExpression: function(node) { + if (suiteRegexp.test(node.callee.name) && node.arguments.length > 1) { + var arg = node.arguments[1]; + + if (arg.type === 'FunctionExpression' && arg.params.length) { + context.report(node, 'Unexpected argument in suite\'s callback') + } + } + } + }; +}; diff --git a/test/rules/no-suite-callback-args.js b/test/rules/no-suite-callback-args.js new file mode 100644 index 0000000..3655148 --- /dev/null +++ b/test/rules/no-suite-callback-args.js @@ -0,0 +1,77 @@ +'use strict'; + +var rule = require('../../lib/rules/no-suite-callback-args'); +var RuleTester = require('eslint').RuleTester; + +var eslintTester = new RuleTester(); + +eslintTester.run('describe-with-done', rule, { + valid: [ + 'describe("My suite", function() {});', + 'fdescribe("My suite", function() {});', + 'ddescribe("My suite", function() {});', + 'xdescribe("My suite", function() {});', + 'describe("My suite", function() {\nit("A spec", function() {});\n});', + 'describe("My suite", function() {\nit("A spec", function(done) {});\n});', + 'describe("My suite", function() {\nit("A spec", function(done) {\ndone();\n});\n });' + ], + + invalid: [ + { + code: 'describe("A suite", function(done) {});', + errors: [ + { + message: 'Unexpected argument in suite\'s callback' + } + ] + }, + { + code: 'fdescribe("A suite", function(done) {});', + errors: [ + { + message: 'Unexpected argument in suite\'s callback' + } + ] + }, + { + code: 'ddescribe("A suite", function(done) {});', + errors: [ + { + message: 'Unexpected argument in suite\'s callback' + } + ] + }, + { + code: 'xdescribe("A suite", function(done) {});', + errors: [ + { + message: 'Unexpected argument in suite\'s callback' + } + ] + }, + { + code: 'describe("A suite", function(done) {\nit("A spec", function() {});\n});', + errors: [ + { + message: 'Unexpected argument in suite\'s callback' + } + ] + }, + { + code: 'describe("A suite", function(done) {\nit("A spec", function(done) {});\n});', + errors: [ + { + message: 'Unexpected argument in suite\'s callback' + } + ] + }, + { + code: 'describe("A suite", function(done) {\nit("A spec", function(done) {\ndone();\n});\n });', + errors: [ + { + message: 'Unexpected argument in suite\'s callback' + } + ] + } + ] +});