File tree 5 files changed +174
-1
lines changed
5 files changed +174
-1
lines changed Original file line number Diff line number Diff line change @@ -127,6 +127,7 @@ installations requiring long-term consistency.
127
127
| [ no-test-prefixes] [ ] | Disallow using ` f ` & ` x ` prefixes to define focused/skipped tests | ![ recommended] [ ] | ![ fixable-green] [ ] |
128
128
| [ no-test-return-statement] [ ] | Disallow explicitly returning from tests | | |
129
129
| [ no-truthy-falsy] [ ] | Disallow using ` toBeTruthy() ` & ` toBeFalsy() ` | | |
130
+ | [ no-try-expect] [ ] | Prevent ` catch ` assertions in tests | | |
130
131
| [ prefer-expect-assertions] [ ] | Suggest using ` expect.assertions() ` OR ` expect.hasAssertions() ` | | |
131
132
| [ prefer-spy-on] [ ] | Suggest using ` jest.spyOn() ` | | ![ fixable-green] [ ] |
132
133
| [ prefer-strict-equal] [ ] | Suggest using ` toStrictEqual() ` | | ![ fixable-green] [ ] |
@@ -177,6 +178,7 @@ https://github.com/dangreenisrael/eslint-plugin-jest-formatting
177
178
[ no-test-prefixes ] : docs/rules/no-test-prefixes.md
178
179
[ no-test-return-statement ] : docs/rules/no-test-return-statement.md
179
180
[ no-truthy-falsy ] : docs/rules/no-truthy-falsy.md
181
+ [ no-try-expect ] : docs/rules/no-try-expect.md
180
182
[ prefer-called-with ] : docs/rules/prefer-called-with.md
181
183
[ prefer-expect-assertions ] : docs/rules/prefer-expect-assertions.md
182
184
[ prefer-spy-on ] : docs/rules/prefer-spy-on.md
Original file line number Diff line number Diff line change
1
+ # Prevent catch assertions in tests (no-try-expect)
2
+
3
+ This rule prevents the use of ` expect ` inside ` catch ` blocks.
4
+
5
+ ## Rule Details
6
+
7
+ Expectations inside a ` catch ` block can be silently skipped. While Jest provides
8
+ an ` expect.assertions(number) ` helper, it might be cumbersome to add this to
9
+ every single test. Using ` toThrow ` concisely guarantees that an exception was
10
+ thrown, and that its contents match expectations.
11
+
12
+ The following patterns are warnings:
13
+
14
+ ``` js
15
+ it (' foo' , () => {
16
+ try {
17
+ foo (); // `foo` may be refactored to not throw exceptions, yet still appears to be tested here.
18
+ } catch (err) {
19
+ expect (err).toMatch (/ foo error/ );
20
+ }
21
+ });
22
+
23
+ it (' bar' , async () => {
24
+ try {
25
+ await foo ();
26
+ } catch (err) {
27
+ expect (err).toMatch (/ foo error/ );
28
+ }
29
+ });
30
+
31
+ it (' baz' , async () => {
32
+ try {
33
+ await foo ();
34
+ } catch (err) {
35
+ expect (err).toMatchObject ({ code: ' MODULE_NOT_FOUND' });
36
+ }
37
+ });
38
+ ```
39
+
40
+ The following patterns are not warnings:
41
+
42
+ ``` js
43
+ it (' foo' , () => {
44
+ expect (() => foo ()).toThrow (/ foo error/ );
45
+ });
46
+
47
+ it (' bar' , async () => {
48
+ await expect (fooPromise).rejects .toThrow (/ foo error/ );
49
+ });
50
+
51
+ it (' baz' , async () => {
52
+ await expect (() => foo ()).rejects .toThrow (
53
+ expect .objectContaining ({ code: ' MODULE_NOT_FOUND' }),
54
+ );
55
+ });
56
+ ```
Original file line number Diff line number Diff line change @@ -3,7 +3,7 @@ import { resolve } from 'path';
3
3
import { rules } from '../' ;
4
4
5
5
const ruleNames = Object . keys ( rules ) ;
6
- const numberOfRules = 35 ;
6
+ const numberOfRules = 36 ;
7
7
8
8
describe ( 'rules' , ( ) => {
9
9
it ( 'should have a corresponding doc for each rule' , ( ) => {
Original file line number Diff line number Diff line change
1
+ import { RuleTester } from 'eslint' ;
2
+ import rule from '../no-try-expect' ;
3
+
4
+ const ruleTester = new RuleTester ( {
5
+ parserOptions : {
6
+ ecmaVersion : 2019 ,
7
+ } ,
8
+ } ) ;
9
+
10
+ ruleTester . run ( 'no-try-catch' , rule , {
11
+ valid : [
12
+ `it('foo', () => {
13
+ expect('foo').toEqual('foo');
14
+ })` ,
15
+ `it('foo', () => {
16
+ expect('bar').toEqual('bar');
17
+ });
18
+ try {
19
+
20
+ } catch {
21
+ expect('foo').toEqual('foo');
22
+ }` ,
23
+ `it.skip('foo');
24
+ try {
25
+
26
+ } catch {
27
+ expect('foo').toEqual('foo');
28
+ }` ,
29
+ ] ,
30
+ invalid : [
31
+ {
32
+ code : `it('foo', () => {
33
+ try {
34
+
35
+ } catch (err) {
36
+ expect(err).toMatch('Error');
37
+ }
38
+ })` ,
39
+ errors : [
40
+ {
41
+ messageId : 'noTryExpect' ,
42
+ } ,
43
+ ] ,
44
+ } ,
45
+ {
46
+ code : `it('foo', async () => {
47
+ await wrapper('production', async () => {
48
+ try {
49
+
50
+ } catch (err) {
51
+ expect(err).toMatch('Error');
52
+ }
53
+ })
54
+ })` ,
55
+ errors : [
56
+ {
57
+ messageId : 'noTryExpect' ,
58
+ } ,
59
+ ] ,
60
+ } ,
61
+ ] ,
62
+ } ) ;
Original file line number Diff line number Diff line change
1
+ import { getDocsUrl , isTestCase } from './util' ;
2
+
3
+ export default {
4
+ meta : {
5
+ docs : {
6
+ description : 'Prefer using toThrow for exception tests' ,
7
+ uri : getDocsUrl ( __filename ) ,
8
+ } ,
9
+ messages : {
10
+ noTryExpect : [
11
+ 'Tests should use Jest‘s exception helpers.' ,
12
+ 'Use "expect(() => yourFunction()).toThrow()" for synchronous tests,' ,
13
+ 'or "await expect(yourFunction()).rejects.toThrow()" for async tests' ,
14
+ ] . join ( ' ' ) ,
15
+ } ,
16
+ } ,
17
+ create ( context ) {
18
+ let isTest = false ;
19
+ let catchDepth = 0 ;
20
+
21
+ function isThrowExpectCall ( node ) {
22
+ return catchDepth > 0 && node . callee . name === 'expect' ;
23
+ }
24
+
25
+ return {
26
+ CallExpression ( node ) {
27
+ if ( isTestCase ( node ) ) {
28
+ isTest = true ;
29
+ } else if ( isTest && isThrowExpectCall ( node ) ) {
30
+ context . report ( {
31
+ messageId : 'noTryExpect' ,
32
+ node,
33
+ } ) ;
34
+ }
35
+ } ,
36
+ CatchClause ( ) {
37
+ if ( isTest ) {
38
+ ++ catchDepth ;
39
+ }
40
+ } ,
41
+ 'CatchClause:exit' ( ) {
42
+ if ( isTest ) {
43
+ -- catchDepth ;
44
+ }
45
+ } ,
46
+ 'CallExpression:exit' ( node ) {
47
+ if ( isTestCase ( node ) ) {
48
+ isTest = false ;
49
+ }
50
+ } ,
51
+ } ;
52
+ } ,
53
+ } ;
You can’t perform that action at this time.
0 commit comments