Skip to content

Commit

Permalink
Add no-empty-description rule. closes #302
Browse files Browse the repository at this point in the history
  • Loading branch information
pustovitDmytro committed Nov 13, 2021
1 parent 491fa7d commit 8d2376d
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 3 deletions.
1 change: 1 addition & 0 deletions docs/rules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@
||:wrench:| [prefer-arrow-callback](prefer-arrow-callback.md) | prefer arrow function callbacks (mocha-aware)
||| [valid-suite-description](valid-suite-description.md) | match suite descriptions against a pre-configured regular expression
||| [valid-test-description](valid-test-description.md) | match test descriptions against a pre-configured regular expression
|:heavy_check_mark:|| [no-empty-description](no-empty-description.md) | Disallow empty test descriptions
45 changes: 45 additions & 0 deletions docs/rules/no-empty-description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Disallow empty test descriptions (no-empty-description)

This rule enforces you to specify the suite/test descriptions for each test.

## Rule Details

This rule checks each mocha test function to have a non-empty description.

The following patterns are considered problems:

```js
it();

suite("");

test(function() { })

test.only(" ", function() { })

```

These patterns would not be considered problems:

```js
describe('foo', function () {
it('bar');
});

suite('foo', function () {
test('bar');
});
```

## Options

Example of a custom rule configuration:

```js
rules: {
"mocha/no-empty-description": [ "warn", {
testNames: ["it", "specify", "test", "mytestname"],
message: 'custom error message'
} ]
}
```
9 changes: 6 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ module.exports = {
'no-top-level-hooks': require('./lib/rules/no-top-level-hooks'),
'prefer-arrow-callback': require('./lib/rules/prefer-arrow-callback'),
'valid-suite-description': require('./lib/rules/valid-suite-description'),
'valid-test-description': require('./lib/rules/valid-test-description')
'valid-test-description': require('./lib/rules/valid-test-description'),
'no-empty-description': require('./lib/rules/no-empty-description.js')
},
configs: {
all: {
Expand Down Expand Up @@ -51,7 +52,8 @@ module.exports = {
'mocha/no-top-level-hooks': 'error',
'mocha/prefer-arrow-callback': 'error',
'mocha/valid-suite-description': 'error',
'mocha/valid-test-description': 'error'
'mocha/valid-test-description': 'error',
'mocha/no-empty-description': 'error'
}
},

Expand Down Expand Up @@ -80,7 +82,8 @@ module.exports = {
'mocha/no-top-level-hooks': 'warn',
'mocha/prefer-arrow-callback': 'off',
'mocha/valid-suite-description': 'off',
'mocha/valid-test-description': 'off'
'mocha/valid-test-description': 'off',
'no-empty-description': 'error'
}
}
}
Expand Down
82 changes: 82 additions & 0 deletions lib/rules/no-empty-description.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
'use strict';

const { getStringIfConstant } = require('eslint-utils');

const DEFAULT_TEST_NAMES = [ 'describe', 'context', 'suite', 'it', 'test', 'specify' ];
const ERROR_MESSAGE = 'Unexpected empty test description.';

function objectOptions(options = {}) {
const {
testNames = DEFAULT_TEST_NAMES,
message
} = options;

return { testNames, message };
}

module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'Disallow empty test descriptions',
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-empty-description.md'
},
messages: {
error: ERROR_MESSAGE
},
schema: [
{
type: 'object',
properties: {
testNames: {
type: 'array',
items: {
type: 'string'
}
},
message: {
type: 'string'
}
},
additionalProperties: false
}
]
},
create(context) {
const options = context.options[0];

const { testNames, message } = objectOptions(options);

function isTest(node) {
return node.callee && node.callee.name && testNames.includes(node.callee.name);
}

function isTemplateString(node) {
return [ 'TaggedTemplateExpression', 'TemplateLiteral' ].includes(node && node.type);
}

function checkDescription(mochaCallExpression) {
const description = mochaCallExpression.arguments[0];
const text = getStringIfConstant(description);

if (isTemplateString(description) && text === null) {
return true;
}

return text && text.trim().length;
}

return {
CallExpression(node) {
if (isTest(node)) {
if (!checkDescription(node)) {
context.report({
node,
message: message || ERROR_MESSAGE
});
}
}
}
};
}
};
87 changes: 87 additions & 0 deletions test/rules/no-empty-description.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
'use strict';

const RuleTester = require('eslint').RuleTester;
const rules = require('../..').rules;
const ruleTester = new RuleTester();
const defaultErrorMessage = 'Unexpected empty test description.';
const firstLine = { column: 1, line: 1 };

ruleTester.run('no-empty-description', rules['no-empty-description'], {

valid: [
'describe("some text")',
'describe.only("some text")',
'describe("some text", function() { })',

'context("some text")',
'context.only("some text")',
'context("some text", function() { })',

'it("some text")',
'it.only("some text")',
'it("some text", function() { })',

'suite("some text")',
'suite.only("some text")',
'suite("some text", function() { })',

'test("some text")',
'test.only("some text")',
'test("some text", function() { })',

'suite("some text")',
'suite.only("some text")',
'suite("some text", function() { })',

'notTest()',

{
parserOptions: { ecmaVersion: 2019 },
code: 'it(string`template`, function () {});'
},
{
parserOptions: { ecmaVersion: 2019 },
code: 'it(`template strings`, function () {});'
},
{
parserOptions: { ecmaVersion: 2019 },
code: 'it(`${foo} template strings`, function () {});'
},
{
options: [ { testNames: [ 'someFunction' ] } ],
code: 'someFunction("this is a test", function () { });'
}
],

invalid: [
{
code: 'test()',
errors: [ { message: defaultErrorMessage, ...firstLine } ],
},
{
code: 'test(function() { })',
errors: [ { message: defaultErrorMessage, ...firstLine } ],
},
{
code: 'test("", function() { })',
errors: [ { message: defaultErrorMessage, ...firstLine } ],
},
{
code: 'test(" ", function() { })',
errors: [ { message: defaultErrorMessage, ...firstLine } ],
},

{
options: [ { testNames: [ 'someFunction' ], message: 'Custom Error' } ],
code: 'someFunction(function() { })',
errors: [ { message: 'Custom Error', ...firstLine } ],
},
{
parserOptions: { ecmaVersion: 2019 },
code: 'it(` `, function () { });',
errors: [ { message: defaultErrorMessage, ...firstLine } ],
}
]

});

0 comments on commit 8d2376d

Please sign in to comment.