11const debug = require ( 'debug' ) ( 'codeceptjs:analyze' )
22const { isMainThread } = require ( 'node:worker_threads' )
3+ const { arrowRight } = require ( 'figures' )
34const container = require ( '../container' )
45const ai = require ( '../ai' )
56const colors = require ( 'chalk' )
@@ -16,10 +17,11 @@ const defaultConfig = {
1617 prompts : {
1718 clusterize : testsAndErrors => {
1819 const serializedFailedTests = testsAndErrors
19- . map ( ( { test, error } , index ) => {
20+ . map ( ( test , index ) => {
21+ if ( ! test || ! test . err ) return
2022 return `
2123 TEST #${ index + 1 } : ${ serializeTest ( test ) }
22- ERROR: ${ serializeError ( error ) . slice ( 0 , MAX_DATA_LENGTH / testsAndErrors . length ) } `
24+ ERROR: ${ serializeError ( test . err ) . slice ( 0 , MAX_DATA_LENGTH / testsAndErrors . length ) } `
2325 } )
2426 . join ( '\n\n---\n\n' )
2527
@@ -96,7 +98,7 @@ const defaultConfig = {
9698
9799 Pick one of the categories of failures and explain it.
98100
99- Common causes of failures:
101+ Common causes of failures in order of priority :
100102
101103 * Browser connection error / browser crash
102104 * Network errors (server error, timeout, etc)
@@ -118,9 +120,9 @@ const defaultConfig = {
118120 If you have suggestions for the test, write them in SUMMARY section.
119121 Inside SUMMARY write exact values, if you have suggestions, explain which information you used to suggest.
120122 Be concise, each section should not take more than one sentence.
121-
123+
122124 Response format:
123-
125+
124126 CATEGORY <category_of_failure>
125127 STEPS <step_of_failure>
126128 SUMMARY <explanation_of_failure>
@@ -141,38 +143,46 @@ const defaultConfig = {
141143module . exports = function ( config = { } ) {
142144 config = Object . assign ( defaultConfig , config )
143145
144- let failedTestsAndErrors = [ ]
146+ event . dispatcher . on ( event . all . result , async result => {
147+ if ( ! isMainThread ) return // run only on main thread
148+ if ( ! ai . isEnabled ) {
149+ console . log ( 'AI is disabled, no analysis will be performed. Run tests with --ai flag to enable it.' )
150+ return
151+ }
145152
146- event . dispatcher . on ( event . test . failed , ( test , error ) => {
147- if ( ! ai . isEnabled ) return
148- failedTestsAndErrors . push ( { test, error } )
153+ printReport ( result )
149154 } )
150155
151- event . dispatcher . on ( event . all . result , async ( ) => {
156+ event . dispatcher . on ( event . workers . result , async result => {
152157 if ( ! ai . isEnabled ) {
153158 console . log ( 'AI is disabled, no analysis will be performed. Run tests with --ai flag to enable it.' )
154159 return
155160 }
156161
162+ printReport ( result )
163+ } )
164+
165+ async function printReport ( result ) {
166+ const failedTestsAndErrors = result . tests . filter ( t => t . state === 'failed' && t . err )
167+
157168 if ( ! failedTestsAndErrors . length ) return
158- if ( ! isMainThread ) return // run only on main thread
159169
160- debug ( failedTestsAndErrors . map ( e => serializeTest ( e . test ) + '\n' + serializeError ( e . error ) ) )
170+ debug ( failedTestsAndErrors . map ( t => serializeTest ( t ) + '\n' + serializeError ( t . err ) ) )
161171
162172 console . log ( )
163173 console . log ( colors . bold . white ( '🪄 AI REPORT:' ) )
164174
165175 try {
166176 if ( failedTestsAndErrors . length >= config . clusterize ) {
167- const response = await clusterize ( )
177+ const response = await clusterize ( failedTestsAndErrors )
168178 console . log ( response )
169179 return
170180 }
171181
172182 output . plugin ( 'analyze' , `Analyzing first ${ config . analyze } failed tests...` )
173183
174184 const uniqueErrors = failedTestsAndErrors . filter ( ( item , index , array ) => {
175- return array . findIndex ( t => serializeError ( t . error ) === serializeError ( item . error ) ) === index
185+ return array . findIndex ( t => serializeError ( t . err ) === serializeError ( item . err ) ) === index
176186 } )
177187
178188 for ( let i = 0 ; i < config . analyze ; i ++ ) {
@@ -185,19 +195,20 @@ module.exports = function (config = {}) {
185195
186196 console . log ( )
187197 console . log ( '--------------------------------' )
188- console . log ( colors . bold . white ( uniqueErrors [ i ] . test . fullTitle ( ) ) )
198+ console . log ( arrowRight , colors . bold . white ( uniqueErrors [ i ] . fullTitle ( ) ) )
199+ console . log ( )
189200 console . log ( response )
190201 }
191202 } catch ( err ) {
192203 console . error ( 'Error analyzing failed tests' , err )
193204 }
194205
195- if ( ! container . plugins ( 'pageInfo' ) ) {
206+ if ( ! Object . keys ( container . plugins ( ) ) . includes ( 'pageInfo' ) ) {
196207 console . log ( 'To improve analysis, enable pageInfo plugin to get more context for failed tests.' )
197208 }
198- } )
209+ }
199210
200- async function clusterize ( ) {
211+ async function clusterize ( failedTestsAndErrors ) {
201212 const spinner = ora ( 'Clusterizing failures...' ) . start ( )
202213 const prompt = config . prompts . clusterize ( failedTestsAndErrors )
203214 try {
@@ -212,7 +223,7 @@ module.exports = function (config = {}) {
212223
213224 async function analyze ( failedTestAndError ) {
214225 const spinner = ora ( 'Analyzing failure...' ) . start ( )
215- const prompt = config . prompts . analyze ( failedTestAndError . test , failedTestAndError . error )
226+ const prompt = config . prompts . analyze ( failedTestAndError , failedTestAndError . err )
216227 try {
217228 const response = await ai . createCompletion ( prompt )
218229 spinner . stop ( )
@@ -225,6 +236,12 @@ module.exports = function (config = {}) {
225236}
226237
227238function serializeError ( error ) {
239+ if ( typeof error === 'string' ) {
240+ return error
241+ }
242+
243+ if ( ! error ) return
244+
228245 let errorMessage = 'ERROR: ' + error . message
229246
230247 if ( error . inspect ) {
0 commit comments