@@ -59,20 +59,30 @@ async function runCommand (args: string[], deps: MsearchDeps): Promise<unknown>
5959 const restoreStdin = _testSetStdinReader ( ( ) => '' )
6060 try {
6161 await program . parseAsync ( [ 'node' , 'test' , 'msearch' , ...args ] )
62+ } catch {
63+ // Commander exitOverride throws on errors; output is already captured in stderr
6264 } finally {
6365 restoreStdin ( )
6466 process . stdout . write = origStdoutWrite
6567 process . stderr . write = origStderrWrite
6668 process . exitCode = 0
6769 }
6870
69- // Prefer stderr (error results) over stdout; parse whichever has content
71+ // The test runner may inject internal protocol bytes into stdout.
72+ // Try each chunk individually (last-to-first) to find valid JSON.
7073 const errOutput = stderrChunks . join ( '' )
71- const stdOutput = stdoutChunks . join ( '' )
72- const output = errOutput . trim ( ) . length > 0 ? errOutput : stdOutput
73- if ( output . trim ( ) . length > 0 ) {
74- try { return JSON . parse ( output . trim ( ) ) } catch { return output . trim ( ) }
74+ if ( errOutput . trim ( ) . length > 0 ) {
75+ try { return JSON . parse ( errOutput . trim ( ) ) } catch { return errOutput . trim ( ) }
76+ }
77+ // Search stdout chunks in reverse for a parseable JSON chunk
78+ for ( let i = stdoutChunks . length - 1 ; i >= 0 ; i -- ) {
79+ const chunk = stdoutChunks [ i ] ! . trim ( )
80+ if ( chunk . length > 0 && ( chunk [ 0 ] === '{' || chunk [ 0 ] === '[' ) ) {
81+ try { return JSON . parse ( chunk ) } catch { /* continue */ }
82+ }
7583 }
84+ const stdOutput = stdoutChunks . join ( '' )
85+ if ( stdOutput . trim ( ) . length > 0 ) return stdOutput . trim ( )
7686 return undefined
7787}
7888
@@ -105,7 +115,9 @@ describe('msearch command', () => {
105115 ) as Record < string , unknown >
106116
107117 assert . equal ( requests . length , 1 )
108- const responses = result . responses as unknown [ ]
118+ assert . ok ( result != null && typeof result === 'object' , `Expected object result, got: ${ JSON . stringify ( result ) } ` )
119+ assert . ok ( 'responses' in ( result as Record < string , unknown > ) , `Expected responses key in result, got: ${ JSON . stringify ( result ) } ` )
120+ const responses = ( result as Record < string , unknown > ) . responses as unknown [ ]
109121 assert . equal ( responses . length , 2 )
110122 } )
111123
@@ -129,7 +141,9 @@ describe('msearch command', () => {
129141 ) as Record < string , unknown >
130142
131143 assert . equal ( requests . length , 3 , 'Expected 3 batches of 2' )
132- assert . equal ( ( result . responses as unknown [ ] ) . length , 6 )
144+ assert . ok ( result != null && typeof result === 'object' , `Expected object result, got: ${ JSON . stringify ( result ) } ` )
145+ assert . ok ( 'responses' in ( result as Record < string , unknown > ) , `Expected responses key in result, got: ${ JSON . stringify ( result ) } ` )
146+ assert . equal ( ( ( result as Record < string , unknown > ) . responses as unknown [ ] ) . length , 6 )
133147 } )
134148
135149 it ( 'applies default index from --index to items without header.index' , async ( ) => {
0 commit comments