File tree Expand file tree Collapse file tree 5 files changed +174
-1
lines changed Expand file tree Collapse file tree 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.
127127| [ no-test-prefixes] [ ] | Disallow using ` f ` & ` x ` prefixes to define focused/skipped tests | ![ recommended] [ ] | ![ fixable-green] [ ] |
128128| [ no-test-return-statement] [ ] | Disallow explicitly returning from tests | | |
129129| [ no-truthy-falsy] [ ] | Disallow using ` toBeTruthy() ` & ` toBeFalsy() ` | | |
130+ | [ no-try-expect] [ ] | Prevent ` catch ` assertions in tests | | |
130131| [ prefer-expect-assertions] [ ] | Suggest using ` expect.assertions() ` OR ` expect.hasAssertions() ` | | |
131132| [ prefer-spy-on] [ ] | Suggest using ` jest.spyOn() ` | | ![ fixable-green] [ ] |
132133| [ prefer-strict-equal] [ ] | Suggest using ` toStrictEqual() ` | | ![ fixable-green] [ ] |
@@ -177,6 +178,7 @@ https://github.com/dangreenisrael/eslint-plugin-jest-formatting
177178[ no-test-prefixes ] : docs/rules/no-test-prefixes.md
178179[ no-test-return-statement ] : docs/rules/no-test-return-statement.md
179180[ no-truthy-falsy ] : docs/rules/no-truthy-falsy.md
181+ [ no-try-expect ] : docs/rules/no-try-expect.md
180182[ prefer-called-with ] : docs/rules/prefer-called-with.md
181183[ prefer-expect-assertions ] : docs/rules/prefer-expect-assertions.md
182184[ 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';
33import { rules } from '../' ;
44
55const ruleNames = Object . keys ( rules ) ;
6- const numberOfRules = 35 ;
6+ const numberOfRules = 36 ;
77
88describe ( 'rules' , ( ) => {
99 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