1
- import { ESLintUtils , TSESTree } from '@typescript-eslint/experimental-utils' ;
2
- import { getDocsUrl , ASYNC_UTILS , LIBRARY_MODULES } from '../utils ' ;
1
+ import { ASTUtils , TSESTree } from '@typescript-eslint/experimental-utils' ;
2
+ import { createTestingLibraryRule } from '../create-testing-library-rule ' ;
3
3
import {
4
4
findClosestCallExpressionNode ,
5
5
isMemberExpression ,
@@ -9,10 +9,9 @@ export const RULE_NAME = 'no-wait-for-snapshot';
9
9
export type MessageIds = 'noWaitForSnapshot' ;
10
10
type Options = [ ] ;
11
11
12
- const ASYNC_UTILS_REGEXP = new RegExp ( `^(${ ASYNC_UTILS . join ( '|' ) } )$` ) ;
13
12
const SNAPSHOT_REGEXP = / ^ ( t o M a t c h S n a p s h o t | t o M a t c h I n l i n e S n a p s h o t ) $ / ;
14
13
15
- export default ESLintUtils . RuleCreator ( getDocsUrl ) < Options , MessageIds > ( {
14
+ export default createTestingLibraryRule < Options , MessageIds > ( {
16
15
name : RULE_NAME ,
17
16
meta : {
18
17
type : 'problem' ,
@@ -31,102 +30,40 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
31
30
} ,
32
31
defaultOptions : [ ] ,
33
32
34
- create ( context ) {
35
- const asyncUtilsUsage : Array < {
36
- node : TSESTree . Identifier | TSESTree . MemberExpression ;
37
- name : string ;
38
- } > = [ ] ;
39
- const importedAsyncUtils : string [ ] = [ ] ;
40
- const snapshotUsage : TSESTree . Identifier [ ] = [ ] ;
41
-
42
- return {
43
- 'ImportDeclaration > ImportSpecifier,ImportNamespaceSpecifier' (
44
- node : TSESTree . Node
45
- ) {
46
- const parent = node . parent as TSESTree . ImportDeclaration ;
47
-
48
- if ( ! LIBRARY_MODULES . includes ( parent . source . value . toString ( ) ) ) {
49
- return ;
50
- }
51
-
52
- let name ;
53
- if ( node . type === 'ImportSpecifier' ) {
54
- name = node . imported . name ;
33
+ create ( context , _ , helpers ) {
34
+ function getClosestAsyncUtil ( node : TSESTree . Node ) {
35
+ let n = node ;
36
+ do {
37
+ const callExpression = findClosestCallExpressionNode ( n ) ;
38
+ if (
39
+ ASTUtils . isIdentifier ( callExpression . callee ) &&
40
+ helpers . isNodeComingFromTestingLibrary ( callExpression . callee ) &&
41
+ helpers . isAsyncUtil ( callExpression . callee )
42
+ ) {
43
+ return callExpression . callee ;
55
44
}
56
-
57
- if ( node . type === 'ImportNamespaceSpecifier' ) {
58
- name = node . local . name ;
45
+ if (
46
+ isMemberExpression ( callExpression . callee ) &&
47
+ ASTUtils . isIdentifier ( callExpression . callee . property ) &&
48
+ helpers . isNodeComingFromTestingLibrary ( callExpression . callee )
49
+ ) {
50
+ return callExpression . callee . property ;
59
51
}
52
+ n = findClosestCallExpressionNode ( callExpression . parent ) ;
53
+ } while ( n !== null ) ;
54
+ return null ;
55
+ }
60
56
61
- importedAsyncUtils . push ( name ) ;
62
- } ,
63
- [ `CallExpression > Identifier[name=${ ASYNC_UTILS_REGEXP } ]` ] (
64
- node : TSESTree . Identifier
65
- ) {
66
- asyncUtilsUsage . push ( { node, name : node . name } ) ;
67
- } ,
68
- [ `CallExpression > MemberExpression > Identifier[name=${ ASYNC_UTILS_REGEXP } ]` ] (
69
- node : TSESTree . Identifier
70
- ) {
71
- const memberExpression = node . parent as TSESTree . MemberExpression ;
72
- const identifier = memberExpression . object as TSESTree . Identifier ;
73
- const memberExpressionName = identifier . name ;
74
-
75
- asyncUtilsUsage . push ( {
76
- node : memberExpression ,
77
- name : memberExpressionName ,
78
- } ) ;
79
- } ,
57
+ return {
80
58
[ `Identifier[name=${ SNAPSHOT_REGEXP } ]` ] ( node : TSESTree . Identifier ) {
81
- snapshotUsage . push ( node ) ;
82
- } ,
83
- 'Program:exit' ( ) {
84
- const testingLibraryUtilUsage = asyncUtilsUsage . filter ( ( usage ) => {
85
- if ( isMemberExpression ( usage . node ) ) {
86
- const object = usage . node . object as TSESTree . Identifier ;
87
-
88
- return importedAsyncUtils . includes ( object . name ) ;
89
- }
90
-
91
- return importedAsyncUtils . includes ( usage . name ) ;
92
- } ) ;
93
-
94
- function getClosestAsyncUtil (
95
- asyncUtilUsage : {
96
- node : TSESTree . Identifier | TSESTree . MemberExpression ;
97
- name : string ;
98
- } ,
99
- node : TSESTree . Node
100
- ) {
101
- let callExpression = findClosestCallExpressionNode ( node ) ;
102
- while ( callExpression != null ) {
103
- if ( callExpression . callee === asyncUtilUsage . node )
104
- return asyncUtilUsage ;
105
- callExpression = findClosestCallExpressionNode (
106
- callExpression . parent
107
- ) ;
108
- }
109
- return null ;
59
+ const closestAsyncUtil = getClosestAsyncUtil ( node ) ;
60
+ if ( closestAsyncUtil === null ) {
61
+ return ;
110
62
}
111
-
112
- snapshotUsage . forEach ( ( node ) => {
113
- testingLibraryUtilUsage . forEach ( ( asyncUtilUsage ) => {
114
- const closestAsyncUtil = getClosestAsyncUtil ( asyncUtilUsage , node ) ;
115
- if ( closestAsyncUtil != null ) {
116
- let name ;
117
- if ( isMemberExpression ( closestAsyncUtil . node ) ) {
118
- name = ( closestAsyncUtil . node . property as TSESTree . Identifier )
119
- . name ;
120
- } else {
121
- name = closestAsyncUtil . name ;
122
- }
123
- context . report ( {
124
- node,
125
- messageId : 'noWaitForSnapshot' ,
126
- data : { name } ,
127
- } ) ;
128
- }
129
- } ) ;
63
+ context . report ( {
64
+ node,
65
+ messageId : 'noWaitForSnapshot' ,
66
+ data : { name : closestAsyncUtil . name } ,
130
67
} ) ;
131
68
} ,
132
69
} ;
0 commit comments