@@ -3,7 +3,7 @@ const assert = require('node:assert');
3
3
const {
4
4
isCommaToken,
5
5
} = require ( '@eslint-community/eslint-utils' ) ;
6
- const { methodCallSelector } = require ( '../../rules/selectors /index.js' ) ;
6
+ const { isMethodCall } = require ( '../../rules/ast /index.js' ) ;
7
7
8
8
const MESSAGE_ID_DISALLOWED_PROPERTY = 'disallow-property' ;
9
9
const MESSAGE_ID_NO_SINGLE_CODE_OBJECT = 'use-string' ;
@@ -15,38 +15,19 @@ const messages = {
15
15
} ;
16
16
17
17
// Top-level `test.snapshot({invalid: []})`
18
- const snapshotTestCallSelector = [
19
- 'Program > ExpressionStatement.body > .expression' ,
18
+ const isTestSnapshot = node =>
20
19
// `test.snapshot()`
21
- methodCallSelector ( {
20
+ isMethodCall ( node , {
22
21
argumentsLength : 1 ,
23
22
object : 'test' ,
24
23
method : 'snapshot' ,
25
- } ) ,
26
- ] . join ( '' ) ;
27
-
28
- const propertySelector = [
29
- snapshotTestCallSelector ,
30
- ' > ObjectExpression.arguments:first-child' ,
31
- /*
32
- ```
33
- test.snapshot({
34
- invalid: [], <- Property
24
+ optionalCall : false ,
25
+ optionalMember : false ,
35
26
} )
36
- ```
37
- */
38
- ' > Property.properties' ,
39
- '[computed!=true]' ,
40
- '[method!=true]' ,
41
- '[shorthand!=true]' ,
42
- '[kind="init"]' ,
43
- '[key.type="Identifier"]' ,
44
- '[key.name="invalid"]' ,
45
-
46
- ' > ArrayExpression.value' ,
47
- ' > ObjectExpression.elements' ,
48
- ' > Property.properties[computed!=true][key.type="Identifier"]' ,
49
- ] . join ( '' ) ;
27
+ && node . parent . type === 'ExpressionStatement'
28
+ && node . parent . expression === node
29
+ && node . parent . parent . type === 'Program'
30
+ && node . parent . parent . body . includes ( node . parent ) ;
50
31
51
32
function * removeObjectProperty ( node , fixer , sourceCode ) {
52
33
yield fixer . remove ( node ) ;
@@ -73,71 +54,123 @@ function getFixMarkComment(snapshotTestCall, sourceCode) {
73
54
}
74
55
}
75
56
76
- module . exports = {
77
- create ( context ) {
78
- const { sourceCode} = context ;
57
+ function checkFixMark ( node , context ) {
58
+ const comment = getFixMarkComment ( node , context . sourceCode ) ;
79
59
80
- return {
81
- [ snapshotTestCallSelector ] ( snapshotTestCall ) {
82
- const comment = getFixMarkComment ( snapshotTestCall , sourceCode ) ;
60
+ if ( ! comment ) {
61
+ return ;
62
+ }
83
63
84
- if ( ! comment ) {
85
- return ;
86
- }
64
+ context . report ( {
65
+ node : comment ,
66
+ messageId : MESSAGE_ID_REMOVE_FIX_MARK_COMMENT ,
67
+ } ) ;
68
+ }
69
+
70
+ function checkInvalidCases ( node , context ) {
71
+ const testCasesNode = node . arguments [ 0 ] ;
72
+ if ( testCasesNode ?. type !== 'ObjectExpression' ) {
73
+ return ;
74
+ }
87
75
76
+ /*
77
+ ```
78
+ test.snapshot({
79
+ invalid: [], <- Property
80
+ })
81
+ ```
82
+ */
83
+ const invalidCasesNode = testCasesNode . properties . find ( node =>
84
+ node . type === 'Property'
85
+ && ! node . computed
86
+ && ! node . method
87
+ && ! node . shorthand
88
+ && node . kind === 'init'
89
+ && node . key . type === 'Identifier'
90
+ && node . key . name === 'invalid'
91
+ && node . value . type === 'ArrayExpression' ,
92
+ ) ;
93
+
94
+ if ( ! invalidCasesNode ) {
95
+ return ;
96
+ }
97
+
98
+ for ( const testCaseNode of invalidCasesNode . value . elements ) {
99
+ if ( testCaseNode ?. type !== 'ObjectExpression' ) {
100
+ continue ;
101
+ }
102
+
103
+ for ( const propertyNode of testCaseNode . properties ) {
104
+ if ( propertyNode . computed || propertyNode . key . type !== 'Identifier' ) {
105
+ continue ;
106
+ }
107
+
108
+ checkTestCaseProperty ( propertyNode , context ) ;
109
+ }
110
+ }
111
+ }
112
+
113
+ function checkTestCaseProperty ( propertyNode , context ) {
114
+ const { key} = propertyNode ;
115
+ const { sourceCode} = context ;
116
+
117
+ switch ( key . name ) {
118
+ case 'errors' :
119
+ case 'output' : {
120
+ const canFix = sourceCode . getCommentsInside ( propertyNode ) . length === 0 ;
121
+ const hasFixMark = Boolean ( getFixMarkComment (
122
+ propertyNode . parent . parent . parent . parent . parent ,
123
+ sourceCode ,
124
+ ) ) ;
125
+
126
+ context . report ( {
127
+ node : key ,
128
+ messageId : MESSAGE_ID_DISALLOWED_PROPERTY ,
129
+ data : {
130
+ name : key . name ,
131
+ autoFixEnableTip : ! hasFixMark && canFix
132
+ ? ' Put /* fix */ before `test.snapshot()` to enable auto-fix.'
133
+ : '' ,
134
+ } ,
135
+ fix : hasFixMark && canFix
136
+ ? fixer => removeObjectProperty ( propertyNode , fixer , sourceCode )
137
+ : undefined
138
+ ,
139
+ } ) ;
140
+ break ;
141
+ }
142
+
143
+ case 'code' : {
144
+ const testCase = propertyNode . parent ;
145
+ if ( testCase . properties . length === 1 ) {
146
+ const commentsCount = sourceCode . getCommentsInside ( testCase ) . length
147
+ - sourceCode . getCommentsInside ( propertyNode ) . length ;
88
148
context . report ( {
89
- node : comment ,
90
- messageId : MESSAGE_ID_REMOVE_FIX_MARK_COMMENT ,
149
+ node : testCase ,
150
+ messageId : MESSAGE_ID_NO_SINGLE_CODE_OBJECT ,
151
+ fix : commentsCount === 0
152
+ ? fixer => fixer . replaceText ( testCase , sourceCode . getText ( propertyNode . value ) )
153
+ : undefined ,
91
154
} ) ;
92
- } ,
93
- [ propertySelector ] ( propertyNode ) {
94
- const { key} = propertyNode ;
95
-
96
- switch ( key . name ) {
97
- case 'errors' :
98
- case 'output' : {
99
- const canFix = sourceCode . getCommentsInside ( propertyNode ) . length === 0 ;
100
- const hasFixMark = Boolean ( getFixMarkComment (
101
- propertyNode . parent . parent . parent . parent . parent ,
102
- sourceCode ,
103
- ) ) ;
104
-
105
- context . report ( {
106
- node : key ,
107
- messageId : MESSAGE_ID_DISALLOWED_PROPERTY ,
108
- data : {
109
- name : key . name ,
110
- autoFixEnableTip : ! hasFixMark && canFix
111
- ? ' Put /* fix */ before `test.snapshot()` to enable auto-fix.'
112
- : '' ,
113
- } ,
114
- fix : hasFixMark && canFix
115
- ? fixer => removeObjectProperty ( propertyNode , fixer , sourceCode )
116
- : undefined
117
- ,
118
- } ) ;
119
- break ;
120
- }
121
-
122
- case 'code' : {
123
- const testCase = propertyNode . parent ;
124
- if ( testCase . properties . length === 1 ) {
125
- const commentsCount = sourceCode . getCommentsInside ( testCase ) . length
126
- - sourceCode . getCommentsInside ( propertyNode ) . length ;
127
- context . report ( {
128
- node : testCase ,
129
- messageId : MESSAGE_ID_NO_SINGLE_CODE_OBJECT ,
130
- fix : commentsCount === 0
131
- ? fixer => fixer . replaceText ( testCase , sourceCode . getText ( propertyNode . value ) )
132
- : undefined ,
133
- } ) ;
134
- }
135
-
136
- break ;
137
- }
138
-
139
- // No default
155
+ }
156
+
157
+ break ;
158
+ }
159
+
160
+ // No default
161
+ }
162
+ }
163
+
164
+ module . exports = {
165
+ create ( context ) {
166
+ return {
167
+ CallExpression ( snapshotTestCall ) {
168
+ if ( ! isTestSnapshot ( snapshotTestCall ) ) {
169
+ return ;
140
170
}
171
+
172
+ checkFixMark ( snapshotTestCall , context ) ;
173
+ checkInvalidCases ( snapshotTestCall , context ) ;
141
174
} ,
142
175
} ;
143
176
} ,
0 commit comments