@@ -149,12 +149,21 @@ describe('Tests for selecting rules', () => {
149
149
expect ( ruleNamesFor ( selection7 , 'stubEngine2' ) ) . toEqual ( [ ] )
150
150
} ) ;
151
151
152
- it ( 'When multiple selectors are provided, then they act as a union' , async ( ) => {
153
- const selection : RuleSelection = await codeAnalyzer . selectRules ( [
154
- 'Security' , // a tag
155
- 'stubEngine2' , // an engine name
156
- 'stub1RuleD' // a rule name
157
- ] ) ;
152
+ it . each ( [
153
+ {
154
+ case : 'multiple selectors are provided' ,
155
+ selectors : [
156
+ 'Security' , // a tag
157
+ 'stubEngine2' , // an engine name
158
+ 'stub1RuleD' // a rule name
159
+ ]
160
+ } ,
161
+ {
162
+ case : 'using a comma to join two rule selectors' ,
163
+ selectors : [ 'Security,stubEngine2,stub1RuleD' ]
164
+ }
165
+ ] ) ( 'When $case, then it acts like a union' , async ( { selectors} ) => {
166
+ const selection : RuleSelection = await codeAnalyzer . selectRules ( selectors ) ;
158
167
159
168
expect ( selection . getEngineNames ( ) ) . toEqual ( [ 'stubEngine1' , 'stubEngine2' ] ) ;
160
169
expect ( ruleNamesFor ( selection , 'stubEngine1' ) ) . toEqual ( [ 'stub1RuleB' , 'stub1RuleD' ] ) ;
@@ -164,14 +173,76 @@ describe('Tests for selecting rules', () => {
164
173
expect ( await codeAnalyzer . selectRules ( [ 'all' , 'Performance' , 'DoesNotExist' ] ) ) . toEqual ( await codeAnalyzer . selectRules ( [ 'all' ] ) ) ;
165
174
} ) ;
166
175
167
- it ( 'When colons are used and multiple selectors are provided then we get correct union and intersection behavior' , async ( ) => {
168
- const selection : RuleSelection = await codeAnalyzer . selectRules ( [ 'Recommended:Performance' , 'stubEngine2:2' , 'stubEngine2:DoesNotExist' ] ) ;
176
+ it . each ( [
177
+ {
178
+ selector : 'Recommended:Performance,2' , // Equivalent to "(Recommended:Performance),2", or "(Recommended,2):(Performance,2)"
179
+ engines : [ 'stubEngine1' , 'stubEngine2' ] ,
180
+ stubEngine1Rules : [ 'stub1RuleB' , 'stub1RuleC' ] ,
181
+ stubEngine2Rules : [ 'stub2RuleC' ]
182
+ } ,
183
+ {
184
+ selector : 'Recommended,3:Performance' , // Equivalent to "(Recommended,4):Performance", or "(Recommended:Performance),(4:Performance)"
185
+ engines : [ 'stubEngine1' ] ,
186
+ stubEngine1Rules : [ 'stub1RuleC' , 'stub1RuleE' ] ,
187
+ stubEngine2Rules : [ ]
188
+ }
189
+ ] ) ( 'In the absence of parentheses, colons and commas are resolved from left to right. Case: $selector' , async ( { selector, engines, stubEngine1Rules, stubEngine2Rules} ) => {
190
+ const selection : RuleSelection = await codeAnalyzer . selectRules ( [ selector ] ) ;
191
+
192
+ expect ( selection . getEngineNames ( ) ) . toEqual ( engines ) ;
193
+ expect ( ruleNamesFor ( selection , 'stubEngine1' ) ) . toEqual ( stubEngine1Rules ) ;
194
+ expect ( ruleNamesFor ( selection , 'stubEngine2' ) ) . toEqual ( stubEngine2Rules ) ;
195
+ } ) ;
196
+
197
+ it . each ( [
198
+ {
199
+ case : 'colons are used and multiple selectors are provided' ,
200
+ selectors : [ 'Recommended:Performance' , 'stubEngine2:2' , 'stubEngine2:DoesNotExist' ]
201
+ } ,
202
+ {
203
+ case : 'colons and commas are nested via parentheses' ,
204
+ selectors : [ '(Recommended:Performance),(stubEngine2:2),(stubEngine2:DoesNotExist)' ]
205
+ }
206
+ ] ) ( 'When $case, then we get correct union and intersection behavior' , async ( { selectors} ) => {
207
+ const selection : RuleSelection = await codeAnalyzer . selectRules ( selectors ) ;
169
208
170
209
expect ( selection . getEngineNames ( ) ) . toEqual ( [ 'stubEngine1' , 'stubEngine2' ] ) ;
171
210
expect ( ruleNamesFor ( selection , 'stubEngine1' ) ) . toEqual ( [ 'stub1RuleC' ] ) ;
172
211
expect ( ruleNamesFor ( selection , 'stubEngine2' ) ) . toEqual ( [ 'stub2RuleC' ] ) ;
173
212
} ) ;
174
213
214
+ it ( 'Parentheses cannot be empty' , async ( ) => {
215
+ await expect ( codeAnalyzer . selectRules ( [ '()' ] ) ) . rejects . toThrow ( 'empty' ) ;
216
+ } ) ;
217
+
218
+ it ( 'Redundant parentheses are accepted' , async ( ) => {
219
+ const selection : RuleSelection = await codeAnalyzer . selectRules ( [ '((((((((stub1RuleC))))))))' ] ) ;
220
+
221
+ expect ( selection . getEngineNames ( ) ) . toEqual ( [ 'stubEngine1' ] ) ;
222
+ expect ( ruleNamesFor ( selection , 'stubEngine1' ) ) . toEqual ( [ 'stub1RuleC' ] ) ;
223
+ } )
224
+
225
+ it . each ( [
226
+ { selector : 'a,b)' } ,
227
+ { selector : '(a,b' } ,
228
+ { selector : '((a,b)' } ,
229
+ { selector : '(a),b)' } ,
230
+ { selector : ')a,b)' } ,
231
+ { selector : 'a,b(' }
232
+ ] ) ( 'When parentheses are unbalanced, an error is thrown. Case: $selector' , async ( { selector} ) => {
233
+ await expect ( codeAnalyzer . selectRules ( [ selector ] ) ) . rejects . toThrow ( 'looks incorrect' ) ;
234
+ } ) ;
235
+
236
+ it . each ( [
237
+ { selector : '2(a,b)' } ,
238
+ { selector : '(a,b)2' } ,
239
+ { selector : '2(a:b)' } ,
240
+ { selector : '(a:b)2' }
241
+ ] ) ( 'When parentheses are not accompanied by valid joiners, an error is thrown. Case: $selector' , async ( { selector} ) => {
242
+ await expect ( codeAnalyzer . selectRules ( [ selector ] ) ) . rejects . toThrow ( 'looks incorrect' ) ;
243
+ } ) ;
244
+
245
+
175
246
it ( 'When selecting rules based on severity names instead of severity number, then we correctly return the rules' , async ( ) => {
176
247
const selection : RuleSelection = await codeAnalyzer . selectRules ( [ 'High' , 'Recommended:Low' ] ) ;
177
248
0 commit comments