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
+ import { ASYNC_UTILS } from '../utils' ;
3
4
import {
4
5
findClosestCallExpressionNode ,
5
6
isMemberExpression ,
@@ -9,10 +10,9 @@ export const RULE_NAME = 'no-wait-for-snapshot';
9
10
export type MessageIds = 'noWaitForSnapshot' ;
10
11
type Options = [ ] ;
11
12
12
- const ASYNC_UTILS_REGEXP = new RegExp ( `^(${ ASYNC_UTILS . join ( '|' ) } )$` ) ;
13
13
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
14
15
- export default ESLintUtils . RuleCreator ( getDocsUrl ) < Options , MessageIds > ( {
15
+ export default createTestingLibraryRule < Options , MessageIds > ( {
16
16
name : RULE_NAME ,
17
17
meta : {
18
18
type : 'problem' ,
@@ -31,102 +31,40 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
31
31
} ,
32
32
defaultOptions : [ ] ,
33
33
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 ;
34
+ create ( context , _ , helpers ) {
35
+ function getClosestAsyncUtil ( node : TSESTree . Node ) {
36
+ let n = node ;
37
+ do {
38
+ const callExpression = findClosestCallExpressionNode ( n ) ;
39
+ if (
40
+ ASTUtils . isIdentifier ( callExpression . callee ) &&
41
+ helpers . isNodeComingFromTestingLibrary ( callExpression . callee ) &&
42
+ ASYNC_UTILS . includes ( callExpression . callee . name )
43
+ ) {
44
+ return callExpression . callee ;
55
45
}
56
-
57
- if ( node . type === 'ImportNamespaceSpecifier' ) {
58
- name = node . local . name ;
46
+ if (
47
+ isMemberExpression ( callExpression . callee ) &&
48
+ ASTUtils . isIdentifier ( callExpression . callee . property ) &&
49
+ helpers . isNodeComingFromTestingLibrary ( callExpression . callee )
50
+ ) {
51
+ return callExpression . callee . property ;
59
52
}
53
+ n = findClosestCallExpressionNode ( callExpression . parent ) ;
54
+ } while ( n !== null ) ;
55
+ return null ;
56
+ }
60
57
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
- } ,
58
+ return {
80
59
[ `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 ;
60
+ const closestAsyncUtil = getClosestAsyncUtil ( node ) ;
61
+ if ( closestAsyncUtil === null ) {
62
+ return ;
110
63
}
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
- } ) ;
64
+ context . report ( {
65
+ node,
66
+ messageId : 'noWaitForSnapshot' ,
67
+ data : { name : closestAsyncUtil . name } ,
130
68
} ) ;
131
69
} ,
132
70
} ;
0 commit comments