1+ /**
2+ * Tests for handling missing suggestedFix in Findings
3+ * Bug: TypeError when finding.suggestedFix is undefined
4+ */
5+
6+ import { ConsoleReporter } from '../../src/reporters/ConsoleReporter.js' ;
7+ import { Finding } from '../../src/types.js' ;
8+
9+ describe ( 'Finding without suggestedFix' , ( ) => {
10+ it ( 'should not crash when finding has suggestedFix' , ( ) => {
11+ const reporter = new ConsoleReporter ( ) ;
12+
13+ // Security findings may not have autoFixable suggestedFix
14+ const finding : Finding = {
15+ id : 'deps-security-test' ,
16+ domain : 'deps' ,
17+ title : 'Security vulnerability found' ,
18+ description : 'Test security finding without autoFix' ,
19+ evidence : {
20+ file : 'package.json' ,
21+ snippet : '"lodash": "4.17.0"' ,
22+ metrics : {
23+ cve : 'CVE-2021-23337' ,
24+ severity : 'high'
25+ }
26+ } ,
27+ severity : 'high' ,
28+ confidence : 'high' ,
29+ impact : {
30+ type : 'security' ,
31+ estimate : 'CVE-2021-23337' ,
32+ confidence : 'high'
33+ } ,
34+ suggestedFix : {
35+ type : 'modify' ,
36+ file : 'package.json' ,
37+ description : 'Update lodash to 4.17.21 or later' ,
38+ autoFixable : false
39+ } ,
40+ autoFixSafe : false
41+ } ;
42+
43+ // This should not throw TypeError
44+ expect ( ( ) => {
45+ const output = reporter . format ( {
46+ timestamp : new Date ( ) . toISOString ( ) ,
47+ path : '/test' ,
48+ version : '0.1.0' ,
49+ findings : [ finding ] ,
50+ topFindings : [ finding ] ,
51+ quickWins : [ ] ,
52+ manualReview : [ ] ,
53+ baseline : {
54+ projectType : 'nodejs' ,
55+ hasPackageJson : true ,
56+ hasDockerfile : false ,
57+ hasCi : true ,
58+ dependencyCount : 10
59+ } ,
60+ totalSavings : { timeSeconds : 0 , sizeMB : 0 , percentImprovement : 0 } ,
61+ score : 50
62+ } ) ;
63+ expect ( output ) . toBeDefined ( ) ;
64+ } ) . not . toThrow ( ) ;
65+ } ) ;
66+
67+ it ( 'should filter quickWins without crashing' , ( ) => {
68+ // Simulate the quickWins filter from analyze.ts
69+ const findings : Finding [ ] = [
70+ {
71+ id : 'test-1' ,
72+ domain : 'deps' ,
73+ title : 'Finding with autoFix' ,
74+ description : 'Test' ,
75+ evidence : { file : 'test.js' , snippet : 'test' } ,
76+ severity : 'low' ,
77+ confidence : 'high' ,
78+ impact : { type : 'size' , estimate : '1KB' , confidence : 'high' } ,
79+ suggestedFix : { type : 'modify' , file : 'test.js' , description : 'Fix' , autoFixable : true } ,
80+ autoFixSafe : true
81+ } ,
82+ {
83+ id : 'test-2' ,
84+ domain : 'deps' ,
85+ title : 'Finding without autoFix' ,
86+ description : 'Test' ,
87+ evidence : { file : 'test.js' , snippet : 'test' } ,
88+ severity : 'medium' ,
89+ confidence : 'high' ,
90+ impact : { type : 'time' , estimate : '1s' , confidence : 'high' } ,
91+ suggestedFix : { type : 'modify' , file : 'test.js' , description : 'Manual fix required' , autoFixable : false } ,
92+ autoFixSafe : false
93+ } ,
94+ {
95+ id : 'test-3' ,
96+ domain : 'deps' ,
97+ title : 'Security finding (no autoFix)' ,
98+ description : 'Test' ,
99+ evidence : { file : 'test.js' , snippet : 'test' } ,
100+ severity : 'high' ,
101+ confidence : 'high' ,
102+ impact : { type : 'security' , estimate : 'CVE-test' , confidence : 'high' } ,
103+ suggestedFix : { type : 'modify' , file : 'test.js' , description : 'Update package' , autoFixable : false } ,
104+ autoFixSafe : false
105+ }
106+ ] ;
107+
108+ // This should not throw TypeError - using optional chaining
109+ const quickWins = findings . filter ( f => f . suggestedFix ?. autoFixable && f . confidence === 'high' ) ;
110+
111+ // Only test-1 has autoFixable: true && confidence: high
112+ expect ( quickWins . length ) . toBe ( 1 ) ;
113+ expect ( quickWins [ 0 ] . id ) . toBe ( 'test-1' ) ;
114+ } ) ;
115+
116+ it ( 'should handle findings list in ConsoleReporter' , ( ) => {
117+ const reporter = new ConsoleReporter ( ) ;
118+
119+ const findings : Finding [ ] = [
120+ {
121+ id : 'test-1' ,
122+ domain : 'deps' ,
123+ title : 'Auto-fixable finding' ,
124+ description : 'Test' ,
125+ evidence : { file : 'test.js' , snippet : 'test' } ,
126+ severity : 'low' ,
127+ confidence : 'high' ,
128+ impact : { type : 'size' , estimate : '1KB' , confidence : 'high' } ,
129+ suggestedFix : { type : 'modify' , file : 'test.js' , description : 'Fix' , autoFixable : true } ,
130+ autoFixSafe : true
131+ } ,
132+ {
133+ id : 'test-2' ,
134+ domain : 'deps' ,
135+ title : 'Manual fix finding' ,
136+ description : 'Test' ,
137+ evidence : { file : 'test.js' , snippet : 'test' } ,
138+ severity : 'medium' ,
139+ confidence : 'medium' ,
140+ impact : { type : 'time' , estimate : '1s' , confidence : 'medium' } ,
141+ suggestedFix : { type : 'modify' , file : 'test.js' , description : 'Manual fix' , autoFixable : false } ,
142+ autoFixSafe : false
143+ }
144+ ] ;
145+
146+ expect ( ( ) => {
147+ const output = reporter . format ( {
148+ timestamp : new Date ( ) . toISOString ( ) ,
149+ path : '/test' ,
150+ version : '0.1.0' ,
151+ score : 75 ,
152+ findings,
153+ topFindings : findings ,
154+ quickWins : [ findings [ 0 ] ] ,
155+ manualReview : [ findings [ 1 ] ] ,
156+ baseline : {
157+ projectType : 'nodejs' ,
158+ hasPackageJson : true ,
159+ hasDockerfile : false ,
160+ hasCi : true ,
161+ dependencyCount : 2
162+ } ,
163+ totalSavings : { timeSeconds : 1 , sizeMB : 0 , percentImprovement : 10 }
164+ } ) ;
165+ expect ( output ) . toContain ( 'Auto-fixable finding' ) ;
166+ expect ( output ) . toContain ( 'Manual fix finding' ) ;
167+ } ) . not . toThrow ( ) ;
168+ } ) ;
169+ } ) ;
0 commit comments