@@ -53,6 +53,12 @@ function createTestSarif() {
5353 { location : { physicalLocation : { artifactLocation : { uri : 'src/db.js' } , region : { startLine : 42 } } , message : { text : 'query(...)' } } } ,
5454 ] } ] } ] ,
5555 } ,
56+ {
57+ ruleId : 'js/sql-injection' ,
58+ ruleIndex : 0 ,
59+ message : { text : 'SQL injection from request body.' } ,
60+ locations : [ { physicalLocation : { artifactLocation : { uri : 'src/api.js' } , region : { startLine : 15 , startColumn : 3 , endColumn : 40 } } } ] ,
61+ } ,
5662 {
5763 ruleId : 'js/xss' ,
5864 ruleIndex : 1 ,
@@ -170,7 +176,7 @@ describe('SARIF Tools', () => {
170176 const parsed = JSON . parse ( result . content [ 0 ] . text ) ;
171177
172178 expect ( parsed . ruleId ) . toBe ( 'js/sql-injection' ) ;
173- expect ( parsed . resultCount ) . toBe ( 1 ) ;
179+ expect ( parsed . resultCount ) . toBe ( 2 ) ;
174180 expect ( parsed . extractedSarif . runs [ 0 ] . tool . driver . rules ) . toHaveLength ( 1 ) ;
175181 } ) ;
176182
@@ -212,15 +218,44 @@ describe('SARIF Tools', () => {
212218 } ) ;
213219
214220 describe ( 'sarif_list_rules' , ( ) => {
215- it ( 'should list all rules with result counts' , async ( ) => {
221+ it ( 'should list all rules with per-rule result counts' , async ( ) => {
216222 const result = await handlers . sarif_list_rules ( { sarifPath : testSarifPath } ) ;
217223 const parsed = JSON . parse ( result . content [ 0 ] . text ) ;
218224
219225 expect ( parsed . totalRules ) . toBe ( 2 ) ;
220- expect ( parsed . totalResults ) . toBe ( 2 ) ;
226+ expect ( parsed . totalResults ) . toBe ( 3 ) ;
221227 expect ( parsed . rules [ 0 ] . ruleId ) . toBe ( 'js/sql-injection' ) ;
222- expect ( parsed . rules [ 0 ] . resultCount ) . toBe ( 1 ) ;
228+ expect ( parsed . rules [ 0 ] . resultCount ) . toBe ( 2 ) ;
223229 expect ( parsed . rules [ 1 ] . ruleId ) . toBe ( 'js/xss' ) ;
230+ expect ( parsed . rules [ 1 ] . resultCount ) . toBe ( 1 ) ;
231+ } ) ;
232+
233+ it ( 'should return resultCount 0 for rules with no results' , async ( ) => {
234+ const noResultsSarif = {
235+ version : '2.1.0' ,
236+ runs : [ {
237+ tool : {
238+ driver : {
239+ name : 'CodeQL' ,
240+ version : '2.25.1' ,
241+ rules : [
242+ { id : 'js/unused-variable' , shortDescription : { text : 'Unused variable' } } ,
243+ ] ,
244+ } ,
245+ } ,
246+ results : [ ] ,
247+ } ] ,
248+ } ;
249+ const noResultsPath = join ( testStorageDir , 'no-results.sarif' ) ;
250+ writeFileSync ( noResultsPath , JSON . stringify ( noResultsSarif ) ) ;
251+
252+ const result = await handlers . sarif_list_rules ( { sarifPath : noResultsPath } ) ;
253+ const parsed = JSON . parse ( result . content [ 0 ] . text ) ;
254+
255+ expect ( parsed . totalRules ) . toBe ( 1 ) ;
256+ expect ( parsed . totalResults ) . toBe ( 0 ) ;
257+ expect ( parsed . rules [ 0 ] . ruleId ) . toBe ( 'js/unused-variable' ) ;
258+ expect ( parsed . rules [ 0 ] . resultCount ) . toBe ( 0 ) ;
224259 } ) ;
225260 } ) ;
226261
@@ -303,7 +338,7 @@ describe('SARIF Tools', () => {
303338
304339 it ( 'should detect changed result counts' , async ( ) => {
305340 const sarifB = createTestSarif ( ) ;
306- sarifB . runs [ 0 ] . results = [ sarifB . runs [ 0 ] . results [ 0 ] ] ; // remove XSS result
341+ sarifB . runs [ 0 ] . results = sarifB . runs [ 0 ] . results . filter ( r => r . ruleId !== 'js/xss' ) ;
307342 const pathB = join ( testStorageDir , 'modified.sarif' ) ;
308343 writeFileSync ( pathB , JSON . stringify ( sarifB ) ) ;
309344
0 commit comments