33import { Command } from 'commander' ;
44import { spawn } from 'child_process' ;
55import { ValidationServer } from '../server/validation/index.js' ;
6- import { ComplianceReport } from '../types.js' ;
6+ import { ComplianceReport , HttpTrace } from '../types.js' ;
7+ import { displayTraces } from '../middleware/http-trace.js' ;
78
89const program = new Command ( ) ;
910
@@ -82,23 +83,21 @@ async function runSingleTest(
8283
8384 // Run the client
8485 const clientProcess = spawn ( executable , args , {
85- stdio : verbose ? 'inherit' : 'pipe' ,
86+ stdio : 'pipe' ,
8687 shell : true ,
8788 timeout
8889 } ) ;
8990
90- // Capture stdout/stderr when not in verbose mode
91- if ( ! verbose ) {
92- if ( clientProcess . stdout ) {
93- clientProcess . stdout . on ( 'data' , ( data ) => {
94- clientStdout += data . toString ( ) ;
95- } ) ;
96- }
97- if ( clientProcess . stderr ) {
98- clientProcess . stderr . on ( 'data' , ( data ) => {
99- clientStderr += data . toString ( ) ;
100- } ) ;
101- }
91+ // Capture stdout/stderr
92+ if ( clientProcess . stdout ) {
93+ clientProcess . stdout . on ( 'data' , ( data ) => {
94+ clientStdout += data . toString ( ) ;
95+ } ) ;
96+ }
97+ if ( clientProcess . stderr ) {
98+ clientProcess . stderr . on ( 'data' , ( data ) => {
99+ clientStderr += data . toString ( ) ;
100+ } ) ;
102101 }
103102
104103 // Wait for client to finish
@@ -146,8 +145,8 @@ async function runSingleTest(
146145 if ( options . json ) {
147146 console . log ( JSON . stringify ( report , null , 2 ) ) ;
148147 } else {
149- const clientOutput = verbose ? { stdout : clientStdout , stderr : clientStderr } : null ;
150- printCompactReport ( report , verbose ? behavior : null , verbose ? authServerTrace : null , clientOutput ) ;
148+ const clientOutput = { stdout : clientStdout , stderr : clientStderr } ;
149+ printCompactReport ( report , verbose ? behavior : null , verbose ? authServerTrace : undefined , clientOutput ) ;
151150 }
152151
153152 // Stop server
@@ -164,60 +163,7 @@ async function runSingleTest(
164163 }
165164}
166165
167- function printHttpTrace ( traces : any [ ] , label : string ) {
168- console . log ( `\n ====== ${ label } ======` ) ;
169- traces . forEach ( ( trace : any , index : number ) => {
170- console . log ( `\n --- Request #${ index + 1 } ---` ) ;
171-
172- // Request line
173- console . log ( ` ${ trace . method } ${ trace . url } HTTP/1.1` ) ;
174-
175- // Request headers
176- if ( trace . headers ) {
177- Object . entries ( trace . headers ) . forEach ( ( [ key , value ] ) => {
178- console . log ( ` ${ key } : ${ value } ` ) ;
179- } ) ;
180- }
181-
182- // Request body
183- if ( trace . body ) {
184- console . log ( '' ) ;
185- const bodyStr = typeof trace . body === 'string' ? trace . body : JSON . stringify ( trace . body ) ;
186- console . log ( ` ${ bodyStr } ` ) ;
187- }
188-
189- // Response
190- if ( trace . response ) {
191- console . log ( `\n HTTP/1.1 ${ trace . response . status } ${ getStatusText ( trace . response . status ) } ` ) ;
192-
193- // Response headers
194- if ( trace . response . headers ) {
195- Object . entries ( trace . response . headers ) . forEach ( ( [ key , value ] ) => {
196- console . log ( ` ${ key } : ${ value } ` ) ;
197- } ) ;
198- }
199-
200- // Response body
201- if ( trace . response . body ) {
202- console . log ( '' ) ;
203- const bodyStr = typeof trace . response . body === 'string'
204- ? trace . response . body
205- : JSON . stringify ( trace . response . body ) ;
206-
207- // Truncate very long responses
208- if ( bodyStr . length > 1000 ) {
209- console . log ( ` ${ bodyStr . substring ( 0 , 1000 ) } ... [truncated]` ) ;
210- } else {
211- console . log ( ` ${ bodyStr } ` ) ;
212- }
213- }
214- }
215- console . log ( '' ) ;
216- } ) ;
217- console . log ( ' ========================\n' ) ;
218- }
219-
220- function printCompactReport ( report : ComplianceReport , behavior ?: any , authServerTrace ?: any [ ] , clientOutput ?: { stdout : string , stderr : string } ) {
166+ function printCompactReport ( report : ComplianceReport , behavior ?: any , authServerTrace ?: HttpTrace [ ] , clientOutput ?: { stdout : string , stderr : string } ) {
221167 const passed = report . overall_result === 'PASS' ;
222168 const icon = passed ? '✅' : '❌' ;
223169
@@ -239,80 +185,7 @@ function printCompactReport(report: ComplianceReport, behavior?: any, authServer
239185
240186 // Show HTTP trace and detailed behavior in verbose mode
241187 if ( behavior ) {
242- // Collect all traces and interleave them by timestamp
243- const allTraces : any [ ] = [ ] ;
244-
245- // Add validation server traces with source label
246- if ( behavior . httpTrace && behavior . httpTrace . length > 0 ) {
247- behavior . httpTrace . forEach ( ( trace : any ) => {
248- allTraces . push ( { ...trace , source : 'VALIDATION' } ) ;
249- } ) ;
250- }
251-
252- // Add auth server traces with source label
253- if ( authServerTrace && authServerTrace . length > 0 ) {
254- authServerTrace . forEach ( ( trace : any ) => {
255- allTraces . push ( { ...trace , source : 'AUTH' } ) ;
256- } ) ;
257- }
258-
259- // Sort all traces by timestamp for interleaved view
260- if ( allTraces . length > 0 ) {
261- allTraces . sort ( ( a , b ) => new Date ( a . timestamp ) . getTime ( ) - new Date ( b . timestamp ) . getTime ( ) ) ;
262-
263- // Print interleaved traces
264- console . log ( '\n ====== INTERLEAVED HTTP TRACE ======' ) ;
265- allTraces . forEach ( ( trace : any , index : number ) => {
266- console . log ( `\n --- [${ trace . source } ] Request #${ index + 1 } ---` ) ;
267- console . log ( ` Timestamp: ${ trace . timestamp } ` ) ;
268-
269- // Request line
270- console . log ( ` ${ trace . method } ${ trace . url } HTTP/1.1` ) ;
271-
272- // Request headers
273- if ( trace . headers ) {
274- Object . entries ( trace . headers ) . forEach ( ( [ key , value ] ) => {
275- console . log ( ` ${ key } : ${ value } ` ) ;
276- } ) ;
277- }
278-
279- // Request body
280- if ( trace . body ) {
281- console . log ( '' ) ;
282- const bodyStr = typeof trace . body === 'string' ? trace . body : JSON . stringify ( trace . body ) ;
283- console . log ( ` ${ bodyStr } ` ) ;
284- }
285-
286- // Response
287- if ( trace . response ) {
288- console . log ( `\n HTTP/1.1 ${ trace . response . status } ${ getStatusText ( trace . response . status ) } ` ) ;
289-
290- // Response headers
291- if ( trace . response . headers ) {
292- Object . entries ( trace . response . headers ) . forEach ( ( [ key , value ] ) => {
293- console . log ( ` ${ key } : ${ value } ` ) ;
294- } ) ;
295- }
296-
297- // Response body
298- if ( trace . response . body ) {
299- console . log ( '' ) ;
300- const bodyStr = typeof trace . response . body === 'string'
301- ? trace . response . body
302- : JSON . stringify ( trace . response . body ) ;
303-
304- // Truncate very long responses
305- if ( bodyStr . length > 1000 ) {
306- console . log ( ` ${ bodyStr . substring ( 0 , 1000 ) } ... [truncated]` ) ;
307- } else {
308- console . log ( ` ${ bodyStr } ` ) ;
309- }
310- }
311- }
312- console . log ( '' ) ;
313- } ) ;
314- console . log ( ' ========================\n' ) ;
315- }
188+ displayTraces ( behavior . httpTrace , authServerTrace || [ ] )
316189
317190 // Show other behavior details
318191 console . log ( ' Client Behavior Summary:' ) ;
@@ -329,7 +202,7 @@ function printCompactReport(report: ComplianceReport, behavior?: any, authServer
329202 console . log ( ' ' + clientOutput . stdout . split ( '\n' ) . join ( '\n ' ) ) ;
330203 console . log ( ' ========================\n' ) ;
331204 }
332-
205+
333206 if ( clientOutput . stderr ) {
334207 console . log ( '\n ====== CLIENT STDERR ======' ) ;
335208 console . log ( ' ' + clientOutput . stderr . split ( '\n' ) . join ( '\n ' ) ) ;
@@ -338,20 +211,6 @@ function printCompactReport(report: ComplianceReport, behavior?: any, authServer
338211 }
339212}
340213
341- function getStatusText ( status : number ) : string {
342- const statusTexts : Record < number , string> = {
343- 200 : 'OK' ,
344- 201 : 'Created' ,
345- 202 : 'Accepted' ,
346- 302 : 'Found' ,
347- 400 : 'Bad Request' ,
348- 401 : 'Unauthorized' ,
349- 403 : 'Forbidden' ,
350- 404 : 'Not Found' ,
351- 405 : 'Method Not Allowed' ,
352- 500 : 'Internal Server Error'
353- } ;
354- return statusTexts [ status ] || '' ;
355- }
214+
356215
357216program . parse ( ) ;
0 commit comments