Skip to content

Commit

Permalink
Merge pull request #336 from scottmcginness/call-expressions-no-sibli…
Browse files Browse the repository at this point in the history
…ng-hooks

Support function calls as custom names (to stop false warnings)
  • Loading branch information
lo1tuma authored Sep 20, 2023
2 parents 8eb0cc2 + 3437410 commit 4985064
Show file tree
Hide file tree
Showing 8 changed files with 328 additions and 16 deletions.
60 changes: 44 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading

0 comments on commit 4985064

Please sign in to comment.