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

Support function calls as custom names (to stop false warnings) #336

Merged
Merged
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
60 changes: 44 additions & 16 deletions README.md
Expand Up @@ -29,23 +29,51 @@ Then add a reference to this plugin and selected rules in your eslint config:

This plugin supports the following settings, which are used by multiple rules:

* `additionalCustomNames`: This allows rules to check additional function names when looking for suites or test cases. This might be used with a custom Mocha extension, such as [`ember-mocha`](https://github.com/switchfly/ember-mocha)
**Example:**

```json
{
"rules": {
"mocha/no-skipped-tests": "error",
"mocha/no-exclusive-tests": "error"
},
"settings": {
"mocha/additionalCustomNames": [
{ "name": "describeModule", "type": "suite", "interfaces": [ "BDD" ] },
{ "name": "testModule", "type": "testCase", "interfaces": [ "TDD" ] }
]
* `additionalCustomNames`: This allows rules to check additional function names when looking for suites or test cases. This might be used with a custom Mocha extension, such as [`ember-mocha`](https://github.com/switchfly/ember-mocha) or [`mocha-each`](https://github.com/ryym/mocha-each).

**Example:**

```json
{
"rules": {
"mocha/no-skipped-tests": "error",
"mocha/no-exclusive-tests": "error"
},
"settings": {
"mocha/additionalCustomNames": [
{ "name": "describeModule", "type": "suite", "interfaces": [ "BDD" ] },
{ "name": "testModule", "type": "testCase", "interfaces": [ "TDD" ] }
]
}
}
}
```
```

The `name` property can be in any of the following forms:
* A plain name e.g. `describeModule`, which allows:

```javascript
describeModule("example", function() { ... });
```

* A dotted name, e.g. `describe.modifier`, which allows:

```javascript
describe.modifier("example", function() { ... });
```

* A name with parentheses, e.g. `forEach().describe`, which allows:

```javascript
forEach([ 1, 2, 3 ])
.describe("example", function(n) { ... });
```

* Any combination of the above, e.g. `forEach().describeModule.modifier`, which allows:

```javascript
forEach([ 1, 2, 3 ])
.describeModule.modifier("example", function(n) { ... });
```

## Configs

Expand Down
3 changes: 3 additions & 0 deletions lib/util/ast.js
Expand Up @@ -31,6 +31,9 @@ function getNodeName(node) {
if (node.type === 'ThisExpression') {
return 'this';
}
if (node.type === 'CallExpression') {
return `${getNodeName(node.callee)}()`;
}
if (node.type === 'MemberExpression') {
return `${getNodeName(node.object)}.${getPropertyName(node.property)}`;
}
Expand Down
62 changes: 62 additions & 0 deletions test/rules/max-top-level-suites.js
Expand Up @@ -68,6 +68,40 @@ ruleTester.run('max-top-level-suites', rules['max-top-level-suites'], {
sourceType: 'module',
ecmaVersion: 2015
}
},
{
code: [
'describe.foo("", function () {',
' describe("", function () {});',
' describe("", function () {});',
'});'
].join('\n'),
parserOptions: {
sourceType: 'module',
ecmaVersion: 2015
},
settings: {
mocha: {
additionalCustomNames: [ { name: 'describe.foo', type: 'suite', interfaces: [ 'BDD' ] } ]
}
}
},
{
code: [
'describe.foo("bar")("", function () {',
' describe("", function () {});',
' describe("", function () {});',
'});'
].join('\n'),
parserOptions: {
sourceType: 'module',
ecmaVersion: 2015
},
settings: {
mocha: {
additionalCustomNames: [ { name: 'describe.foo()', type: 'suite', interfaces: [ 'BDD' ] } ]
}
}
}
],

Expand Down Expand Up @@ -211,6 +245,34 @@ ruleTester.run('max-top-level-suites', rules['max-top-level-suites'], {
errors: [
{ message: 'The number of top-level suites is more than 1.' }
]
}, {
code: 'describe.foo("bar")("this is a test", function () { });' +
'context.foo("this is a different test", function () { });',
settings: {
mocha: {
additionalCustomNames: [
{ name: 'describe.foo()', type: 'suite', interfaces: [ 'BDD' ] },
{ name: 'context.foo', type: 'suite', interfaces: [ 'BDD' ] }
]
}
},
errors: [
{ message: 'The number of top-level suites is more than 1.' }
]
}, {
code: 'forEach([ 1, 2, 3 ]).describe("this is a test", function () { });' +
'context.foo("this is a different test", function () { });',
settings: {
mocha: {
additionalCustomNames: [
{ name: 'forEach().describe', type: 'suite', interfaces: [ 'BDD' ] },
{ name: 'context.foo', type: 'suite', interfaces: [ 'BDD' ] }
]
}
},
errors: [
{ message: 'The number of top-level suites is more than 1.' }
]
}
]
});
34 changes: 34 additions & 0 deletions test/rules/no-async-describe.js
Expand Up @@ -72,6 +72,40 @@ ruleTester.run('no-async-describe', rule, {
line: 1,
column: 19
} ]
},
{
code: 'describe.foo("bar")("hello", async () => {})',
output: 'describe.foo("bar")("hello", () => {})',
settings: {
mocha: {
additionalCustomNames: [
{ name: 'describe.foo()', type: 'suite', interfaces: [ 'BDD' ] }
]
}
},
parserOptions: { ecmaVersion: 8 },
errors: [ {
message: 'Unexpected async function in describe.foo()()',
line: 1,
column: 30
} ]
},
{
code: 'forEach([ 1, 2, 3 ]).describe.foo("hello", async () => {})',
output: 'forEach([ 1, 2, 3 ]).describe.foo("hello", () => {})',
settings: {
mocha: {
additionalCustomNames: [
{ name: 'forEach().describe.foo', type: 'suite', interfaces: [ 'BDD' ] }
]
}
},
parserOptions: { ecmaVersion: 8 },
errors: [ {
message: 'Unexpected async function in forEach().describe.foo()',
line: 1,
column: 44
} ]
}
]
});
17 changes: 17 additions & 0 deletions test/rules/no-exclusive-tests.js
Expand Up @@ -38,6 +38,14 @@ ruleTester.run('no-exclusive-tests', rules['no-exclusive-tests'], {
additionalCustomNames: [ { name: 'a.b.c', type: 'testCase', interfaces: [ 'BDD' ] } ]
}
}
},
{
code: 'a.b().c.skip()',
settings: {
mocha: {
additionalCustomNames: [ { name: 'a.b().c', type: 'testCase', interfaces: [ 'BDD' ] } ]
}
}
}
],

Expand Down Expand Up @@ -175,6 +183,15 @@ ruleTester.run('no-exclusive-tests', rules['no-exclusive-tests'], {
}
},
errors: [ { message: expectedErrorMessage, column: 9, line: 1 } ]
},
{
code: 'foo("bar").it.only()',
settings: {
mocha: {
additionalCustomNames: [ { name: 'foo().it', type: 'testCase', interfaces: [ 'BDD' ] } ]
}
},
errors: [ { message: expectedErrorMessage, column: 15, line: 1 } ]
}
]
});
114 changes: 114 additions & 0 deletions test/rules/no-sibling-hooks.js
Expand Up @@ -98,6 +98,72 @@ ruleTester.run('no-sibling-hooks', rules['no-sibling-hooks'], {
additionalCustomNames: [ { name: 'foo', type: 'suite', interfaces: [ 'BDD' ] } ]
}
}
}, {
code: [
'describe(function() {',
' before(function() {});',
' describe.foo(function() {',
' before(function() {});',
' });',
'});'
].join('\n'),
settings: {
mocha: {
additionalCustomNames: [ { name: 'describe.foo', type: 'suite', interfaces: [ 'BDD' ] } ]
}
}
}, {
code: [
'describe(function() {',
' before(function() {});',
' describe.foo()(function() {',
' before(function() {});',
' });',
'});'
].join('\n'),
settings: {
mocha: {
additionalCustomNames: [ { name: 'describe.foo()', type: 'suite', interfaces: [ 'BDD' ] } ]
}
}
}, {
code: [
'describe(function() {',
' before(function() {});',
' forEach([ 1, 2, 3 ]).describe(function() {',
' before(function() {});',
' });',
' forEach([ 1, 2, 3 ]).context(function() {',
' before(function() {});',
' });',
' forEach([ 1, 2, 3 ]).describe.only(function() {',
' before(function() {});',
' });',
' forEach([ 1, 2, 3 ]).describe.skip(function() {',
' before(function() {});',
' });',
' forEach([ 1, 2, 3 ]).describe.foo(function() {',
' before(function() {});',
' });',
' forEach([ 1, 2, 3 ]).describe.bar([ 9, 8, 7 ])(function() {',
' before(function() {});',
' });',
' deep.forEach({ a: [ 1, 2, 3 ], b: [ 4, 5, 6 ] }).describe(function() {',
' before(function() {});',
' });',
'});'
].join('\n'),
settings: {
mocha: {
additionalCustomNames: [
{ name: 'forEach().describe', type: 'suite', interfaces: [ 'BDD' ] },
{ name: 'forEach().context', type: 'suite', interfaces: [ 'BDD' ] },
{ name: 'forEach().describe.foo', type: 'suite', interfaces: [ 'BDD' ] },
{ name: 'forEach().describe.bar()', type: 'suite', interfaces: [ 'BDD' ] },
{ name: 'deep.forEach().describe', type: 'suite', interfaces: [ 'BDD' ] }
]
}
}
}
],

Expand Down Expand Up @@ -172,6 +238,54 @@ ruleTester.run('no-sibling-hooks', rules['no-sibling-hooks'], {
}
},
errors: [ { message: 'Unexpected use of duplicate Mocha `before` hook', column: 5, line: 6 } ]
}, {
code: [
'describe.foo(function() {',
' before(function() {});',
' describe.foo(function() {',
' before(function() {});',
' });',
' before(function() {});',
'});'
].join('\n'),
settings: {
mocha: {
additionalCustomNames: [ { name: 'describe.foo', type: 'suite', interfaces: [ 'BDD' ] } ]
}
},
errors: [ { message: 'Unexpected use of duplicate Mocha `before` hook', column: 5, line: 6 } ]
}, {
code: [
'describe.foo()(function() {',
' before(function() {});',
' describe.foo()(function() {',
' before(function() {});',
' });',
' before(function() {});',
'});'
].join('\n'),
settings: {
mocha: {
additionalCustomNames: [ { name: 'describe.foo()', type: 'suite', interfaces: [ 'BDD' ] } ]
}
},
errors: [ { message: 'Unexpected use of duplicate Mocha `before` hook', column: 5, line: 6 } ]
}, {
code: [
'forEach([ 1, 2, 3 ]).describe(function() {',
' before(function() {});',
' forEach([ 4, 5, 6 ]).describe(function() {',
' before(function() {});',
' });',
' before(function() {});',
'});'
].join('\n'),
settings: {
mocha: {
additionalCustomNames: [ { name: 'forEach().describe', type: 'suite', interfaces: [ 'BDD' ] } ]
}
},
errors: [ { message: 'Unexpected use of duplicate Mocha `before` hook', column: 5, line: 6 } ]
}
]

Expand Down
9 changes: 9 additions & 0 deletions test/rules/no-skipped-tests.js
Expand Up @@ -139,6 +139,15 @@ ruleTester.run('no-skipped-tests', rules['no-skipped-tests'], {
}
},
errors: [ { message: expectedErrorMessage, column: 1, line: 1 } ]
},
{
code: 'custom("bar").it.skip()',
settings: {
mocha: {
additionalCustomNames: [ { name: 'custom().it', type: 'testCase', interfaces: [ 'BDD' ] } ]
}
},
errors: [ { message: expectedErrorMessage, column: 18, line: 1 } ]
}
]

Expand Down