Skip to content

Commit

Permalink
feat(require-top-level-describe): support enforcing max num of descri…
Browse files Browse the repository at this point in the history
…bes (#912)
  • Loading branch information
G-Rath authored Sep 29, 2021
1 parent a41a40e commit 14a2d13
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 7 deletions.
28 changes: 28 additions & 0 deletions docs/rules/require-top-level-describe.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,34 @@ describe('test suite', () => {
});
```

You can also enforce a limit on the number of describes allowed at the top-level
using the `maxNumberOfTopLevelDescribes` option:

```json
{
"jest/require-top-level-describe": [
"error",
{
"maxNumberOfTopLevelDescribes": 2
}
]
}
```

Examples of **incorrect** code with the above config:

```js
describe('test suite', () => {
it('test', () => {});
});

describe('test suite', () => {});

describe('test suite', () => {});
```

This option defaults to `Infinity`, allowing any number of top-level describes.

## When Not To Use It

Don't use this rule on non-jest test files.
69 changes: 69 additions & 0 deletions src/rules/__tests__/require-top-level-describe.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,72 @@ ruleTester.run('require-top-level-describe', rule, {
},
],
});

ruleTester.run(
'require-top-level-describe (enforce number of describes)',
rule,
{
valid: [
'describe("test suite", () => { test("my test") });',
'foo()',
'describe.each([1, true])("trues", value => { it("an it", () => expect(value).toBe(true) ); });',
dedent`
describe('one', () => {});
describe('two', () => {});
describe('three', () => {});
`,
{
code: dedent`
describe('one', () => {
describe('two', () => {});
describe('three', () => {});
});
`,
options: [{ maxNumberOfTopLevelDescribes: 1 }],
},
],
invalid: [
{
code: dedent`
describe('one', () => {});
describe('two', () => {});
describe('three', () => {});
`,
options: [{ maxNumberOfTopLevelDescribes: 2 }],
errors: [{ messageId: 'tooManyDescribes', line: 3 }],
},
{
code: dedent`
describe('one', () => {
describe('one (nested)', () => {});
describe('two (nested)', () => {});
});
describe('two', () => {
describe('one (nested)', () => {});
describe('two (nested)', () => {});
describe('three (nested)', () => {});
});
describe('three', () => {
describe('one (nested)', () => {});
describe('two (nested)', () => {});
describe('three (nested)', () => {});
});
`,
options: [{ maxNumberOfTopLevelDescribes: 2 }],
errors: [{ messageId: 'tooManyDescribes', line: 10 }],
},
{
code: dedent`
describe('one', () => {});
describe('two', () => {});
describe('three', () => {});
`,
options: [{ maxNumberOfTopLevelDescribes: 1 }],
errors: [
{ messageId: 'tooManyDescribes', line: 2 },
{ messageId: 'tooManyDescribes', line: 3 },
],
},
],
},
);
49 changes: 42 additions & 7 deletions src/rules/require-top-level-describe.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { TSESTree } from '@typescript-eslint/experimental-utils';
import { createRule, isDescribeCall, isHook, isTestCaseCall } from './utils';

export default createRule({
const messages = {
tooManyDescribes:
'There should not be more than {{ max }} describe{{ s }} at the top level',
unexpectedTestCase: 'All test cases must be wrapped in a describe block.',
unexpectedHook: 'All hooks must be wrapped in a describe block.',
};

export default createRule<
[Partial<{ maxNumberOfTopLevelDescribes: number }>],
keyof typeof messages
>({
name: __filename,
meta: {
docs: {
Expand All @@ -10,22 +20,47 @@ export default createRule({
'Require test cases and hooks to be inside a `describe` block',
recommended: false,
},
messages: {
unexpectedTestCase: 'All test cases must be wrapped in a describe block.',
unexpectedHook: 'All hooks must be wrapped in a describe block.',
},
messages,
type: 'suggestion',
schema: [],
schema: [
{
type: 'object',
properties: {
maxNumberOfTopLevelDescribes: {
type: 'number',
minimum: 1,
},
},
additionalProperties: false,
},
],
},
defaultOptions: [],
defaultOptions: [{}],
create(context) {
const { maxNumberOfTopLevelDescribes = Infinity } =
context.options[0] ?? {};
let numberOfTopLevelDescribeBlocks = 0;
let numberOfDescribeBlocks = 0;

return {
CallExpression(node) {
if (isDescribeCall(node)) {
numberOfDescribeBlocks++;

if (numberOfDescribeBlocks === 1) {
numberOfTopLevelDescribeBlocks++;
if (numberOfTopLevelDescribeBlocks > maxNumberOfTopLevelDescribes) {
context.report({
node,
messageId: 'tooManyDescribes',
data: {
max: maxNumberOfTopLevelDescribes,
s: maxNumberOfTopLevelDescribes === 1 ? '' : 's',
},
});
}
}

return;
}

Expand Down

0 comments on commit 14a2d13

Please sign in to comment.