Skip to content

Commit ac054b4

Browse files
committed
feat: soft-rename valid-describe-name to valid-describe-callback
1 parent 9a5aeec commit ac054b4

File tree

8 files changed

+414
-103
lines changed

8 files changed

+414
-103
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ installations requiring long-term consistency.
189189
| [prefer-todo](docs/rules/prefer-todo.md) | Suggest using `test.todo` | | ![fixable][] |
190190
| [require-to-throw-message](docs/rules/require-to-throw-message.md) | Require a message for `toThrow()` | | |
191191
| [require-top-level-describe](docs/rules/require-top-level-describe.md) | Require test cases and hooks to be inside a `describe` block | | |
192-
| [valid-describe](docs/rules/valid-describe.md) | Enforce valid `describe()` callback | ![recommended][] | |
192+
| [valid-describe-callback](docs/rules/valid-describe-callback.md) | Enforce valid `describe()` callback | ![recommended][] | |
193193
| [valid-expect](docs/rules/valid-expect.md) | Enforce valid `expect()` usage | ![recommended][] | |
194194
| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | Enforce having return statement when testing with promises | ![recommended][] | |
195195
| [valid-title](docs/rules/valid-title.md) | Enforce valid titles | ![recommended][] | ![fixable][] |

docs/rules/valid-describe-callback.md

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Enforce valid `describe()` callback (`valid-describe-callback`)
2+
3+
Using an improper `describe()` callback function can lead to unexpected test
4+
errors.
5+
6+
## Rule Details
7+
8+
This rule validates that the second parameter of a `describe()` function is a
9+
callback function. This callback function:
10+
11+
- should not be
12+
[async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)
13+
- should not contain any parameters
14+
- should not contain any `return` statements
15+
16+
The following `describe` function aliases are also validated:
17+
18+
- `describe`
19+
- `describe.only`
20+
- `describe.skip`
21+
- `fdescribe`
22+
- `xdescribe`
23+
24+
The following patterns are considered warnings:
25+
26+
```js
27+
// Async callback functions are not allowed
28+
describe('myFunction()', async () => {
29+
// ...
30+
});
31+
32+
// Callback function parameters are not allowed
33+
describe('myFunction()', done => {
34+
// ...
35+
});
36+
37+
//
38+
describe('myFunction', () => {
39+
// No return statements are allowed in block of a callback function
40+
return Promise.resolve().then(() => {
41+
it('breaks', () => {
42+
throw new Error('Fail');
43+
});
44+
});
45+
});
46+
47+
// Returning a value from a describe block is not allowed
48+
describe('myFunction', () =>
49+
it('returns a truthy value', () => {
50+
expect(myFunction()).toBeTruthy();
51+
}));
52+
```
53+
54+
The following patterns are not considered warnings:
55+
56+
```js
57+
describe('myFunction()', () => {
58+
it('returns a truthy value', () => {
59+
expect(myFunction()).toBeTruthy();
60+
});
61+
});
62+
```

docs/rules/valid-describe.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Enforce valid `describe()` callback (`valid-describe`)
22

3+
## Deprecated
4+
5+
This rule has been deprecated in favor of
6+
[`valid-describe-callback`](valid-describe-callback.md).
7+
38
Using an improper `describe()` callback function can lead to unexpected test
49
errors.
510

src/__tests__/__snapshots__/rules.test.ts.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Object {
4848
"jest/require-to-throw-message": "error",
4949
"jest/require-top-level-describe": "error",
5050
"jest/unbound-method": "error",
51-
"jest/valid-describe": "error",
51+
"jest/valid-describe-callback": "error",
5252
"jest/valid-expect": "error",
5353
"jest/valid-expect-in-promise": "error",
5454
"jest/valid-title": "error",

src/__tests__/rules.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { existsSync } from 'fs';
22
import { resolve } from 'path';
33
import plugin from '../';
44

5-
const numberOfRules = 49;
5+
const numberOfRules = 50;
66
const ruleNames = Object.keys(plugin.rules);
77
const deprecatedRules = Object.entries(plugin.rules)
88
.filter(([, rule]) => rule.meta.deprecated)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
import { TSESLint } from '@typescript-eslint/experimental-utils';
2+
import dedent from 'dedent';
3+
import resolveFrom from 'resolve-from';
4+
import rule from '../valid-describe-callback';
5+
6+
const ruleTester = new TSESLint.RuleTester({
7+
parser: resolveFrom(require.resolve('eslint'), 'espree'),
8+
parserOptions: {
9+
ecmaVersion: 2017,
10+
},
11+
});
12+
13+
ruleTester.run('valid-describe-callback', rule, {
14+
valid: [
15+
'describe.each([1, 2, 3])("%s", (a, b) => {});',
16+
'describe("foo", function() {})',
17+
'describe("foo", () => {})',
18+
'describe(`foo`, () => {})',
19+
'xdescribe("foo", () => {})',
20+
'fdescribe("foo", () => {})',
21+
'describe.only("foo", () => {})',
22+
'describe.skip("foo", () => {})',
23+
dedent`
24+
describe('foo', () => {
25+
it('bar', () => {
26+
return Promise.resolve(42).then(value => {
27+
expect(value).toBe(42)
28+
})
29+
})
30+
})
31+
`,
32+
dedent`
33+
describe('foo', () => {
34+
it('bar', async () => {
35+
expect(await Promise.resolve(42)).toBe(42)
36+
})
37+
})
38+
`,
39+
dedent`
40+
if (hasOwnProperty(obj, key)) {
41+
}
42+
`,
43+
dedent`
44+
describe.each\`
45+
foo | foe
46+
${1} | ${2}
47+
\`('$something', ({ foo, foe }) => {});
48+
`,
49+
],
50+
invalid: [
51+
{
52+
code: 'describe.each()()',
53+
errors: [{ messageId: 'nameAndCallback', line: 1, column: 1 }],
54+
},
55+
{
56+
code: 'describe["each"]()()',
57+
errors: [{ messageId: 'nameAndCallback', line: 1, column: 1 }],
58+
},
59+
{
60+
code: 'describe.each(() => {})()',
61+
errors: [{ messageId: 'nameAndCallback', line: 1, column: 1 }],
62+
},
63+
{
64+
code: 'describe.each(() => {})("foo")',
65+
errors: [{ messageId: 'nameAndCallback', line: 1, column: 25 }],
66+
},
67+
{
68+
code: 'describe.each()(() => {})',
69+
errors: [{ messageId: 'nameAndCallback', line: 1, column: 17 }],
70+
},
71+
{
72+
code: 'describe["each"]()(() => {})',
73+
errors: [{ messageId: 'nameAndCallback', line: 1, column: 20 }],
74+
},
75+
{
76+
code: 'describe.each("foo")(() => {})',
77+
errors: [{ messageId: 'nameAndCallback', line: 1, column: 22 }],
78+
},
79+
{
80+
code: 'describe.only.each("foo")(() => {})',
81+
errors: [{ messageId: 'nameAndCallback', line: 1, column: 27 }],
82+
},
83+
{
84+
code: 'describe(() => {})',
85+
errors: [{ messageId: 'nameAndCallback', line: 1, column: 10 }],
86+
},
87+
{
88+
code: 'describe("foo")',
89+
errors: [{ messageId: 'nameAndCallback', line: 1, column: 10 }],
90+
},
91+
{
92+
code: 'describe("foo", "foo2")',
93+
errors: [
94+
{ messageId: 'secondArgumentMustBeFunction', line: 1, column: 10 },
95+
],
96+
},
97+
{
98+
code: 'describe()',
99+
errors: [{ messageId: 'nameAndCallback', line: 1, column: 1 }],
100+
},
101+
{
102+
code: 'describe("foo", async () => {})',
103+
errors: [{ messageId: 'noAsyncDescribeCallback', line: 1, column: 17 }],
104+
},
105+
{
106+
code: 'describe("foo", async function () {})',
107+
errors: [{ messageId: 'noAsyncDescribeCallback', line: 1, column: 17 }],
108+
},
109+
{
110+
code: 'xdescribe("foo", async function () {})',
111+
errors: [{ messageId: 'noAsyncDescribeCallback', line: 1, column: 18 }],
112+
},
113+
{
114+
code: 'fdescribe("foo", async function () {})',
115+
errors: [{ messageId: 'noAsyncDescribeCallback', line: 1, column: 18 }],
116+
},
117+
{
118+
code: 'describe.only("foo", async function () {})',
119+
errors: [{ messageId: 'noAsyncDescribeCallback', line: 1, column: 22 }],
120+
},
121+
{
122+
code: 'describe.skip("foo", async function () {})',
123+
errors: [{ messageId: 'noAsyncDescribeCallback', line: 1, column: 22 }],
124+
},
125+
{
126+
code: dedent`
127+
describe('sample case', () => {
128+
it('works', () => {
129+
expect(true).toEqual(true);
130+
});
131+
describe('async', async () => {
132+
await new Promise(setImmediate);
133+
it('breaks', () => {
134+
throw new Error('Fail');
135+
});
136+
});
137+
});
138+
`,
139+
errors: [{ messageId: 'noAsyncDescribeCallback', line: 5, column: 21 }],
140+
},
141+
{
142+
code: dedent`
143+
describe('foo', function () {
144+
return Promise.resolve().then(() => {
145+
it('breaks', () => {
146+
throw new Error('Fail')
147+
})
148+
})
149+
})
150+
`,
151+
errors: [{ messageId: 'unexpectedReturnInDescribe', line: 2, column: 3 }],
152+
},
153+
{
154+
code: dedent`
155+
describe('foo', () => {
156+
return Promise.resolve().then(() => {
157+
it('breaks', () => {
158+
throw new Error('Fail')
159+
})
160+
})
161+
describe('nested', () => {
162+
return Promise.resolve().then(() => {
163+
it('breaks', () => {
164+
throw new Error('Fail')
165+
})
166+
})
167+
})
168+
})
169+
`,
170+
errors: [
171+
{ messageId: 'unexpectedReturnInDescribe', line: 2, column: 3 },
172+
{ messageId: 'unexpectedReturnInDescribe', line: 8, column: 5 },
173+
],
174+
},
175+
{
176+
code: dedent`
177+
describe('foo', async () => {
178+
await something()
179+
it('does something')
180+
describe('nested', () => {
181+
return Promise.resolve().then(() => {
182+
it('breaks', () => {
183+
throw new Error('Fail')
184+
})
185+
})
186+
})
187+
})
188+
`,
189+
errors: [
190+
{ messageId: 'noAsyncDescribeCallback', line: 1, column: 17 },
191+
{ messageId: 'unexpectedReturnInDescribe', line: 5, column: 5 },
192+
],
193+
},
194+
{
195+
code: dedent`
196+
describe('foo', () =>
197+
test('bar', () => {})
198+
)
199+
`,
200+
errors: [
201+
{ messageId: 'unexpectedReturnInDescribe', line: 1, column: 17 },
202+
],
203+
},
204+
{
205+
code: 'describe("foo", done => {})',
206+
errors: [
207+
{ messageId: 'unexpectedDescribeArgument', line: 1, column: 17 },
208+
],
209+
},
210+
{
211+
code: 'describe("foo", function (done) {})',
212+
errors: [
213+
{ messageId: 'unexpectedDescribeArgument', line: 1, column: 27 },
214+
],
215+
},
216+
{
217+
code: 'describe("foo", function (one, two, three) {})',
218+
errors: [
219+
{ messageId: 'unexpectedDescribeArgument', line: 1, column: 27 },
220+
],
221+
},
222+
{
223+
code: 'describe("foo", async function (done) {})',
224+
errors: [
225+
{ messageId: 'noAsyncDescribeCallback', line: 1, column: 17 },
226+
{ messageId: 'unexpectedDescribeArgument', line: 1, column: 33 },
227+
],
228+
},
229+
],
230+
});

0 commit comments

Comments
 (0)