@@ -51,7 +51,9 @@ describe('codeSearch', () => {
5151 const result = await searchPromise
5252 expect ( result [ 0 ] . type ) . toBe ( 'json' )
5353 const value = asCodeSearchResult ( result [ 0 ] )
54+ expect ( value . stdout ) . toContain ( 'Found 3 matches' )
5455 expect ( value . stdout ) . toContain ( 'file1.ts:' )
56+ expect ( value . stdout ) . toContain ( ' Line 1: import foo from "bar"' )
5557 expect ( value . stdout ) . toContain ( 'file2.ts:' )
5658 } )
5759 } )
@@ -81,6 +83,8 @@ describe('codeSearch', () => {
8183 expect ( result [ 0 ] . type ) . toBe ( 'json' )
8284 const value = asCodeSearchResult ( result [ 0 ] )
8385
86+ expect ( value . stdout ) . toContain ( 'Found 2 matches' )
87+
8488 // Should contain match lines
8589 expect ( value . stdout ) . toContain ( 'import { env } from "./config"' )
8690 expect ( value . stdout ) . toContain ( 'import env from "process"' )
@@ -104,7 +108,11 @@ describe('codeSearch', () => {
104108 createRgJsonContext ( 'app.ts' , 1 , 'import React from "react"' ) ,
105109 createRgJsonContext ( 'app.ts' , 2 , '' ) ,
106110 createRgJsonMatch ( 'app.ts' , 3 , 'export const main = () => {}' ) ,
107- createRgJsonContext ( 'utils.ts' , 8 , 'function validateInput(x: string) {' ) ,
111+ createRgJsonContext (
112+ 'utils.ts' ,
113+ 8 ,
114+ 'function validateInput(x: string) {' ,
115+ ) ,
108116 createRgJsonContext ( 'utils.ts' , 9 , ' return x.length > 0' ) ,
109117 createRgJsonMatch ( 'utils.ts' , 10 , 'export function helper() {}' ) ,
110118 ] . join ( '\n' )
@@ -343,6 +351,28 @@ describe('codeSearch', () => {
343351 }
344352 } )
345353
354+ it ( 'should not report truncation when matches exactly equal maxResults' , async ( ) => {
355+ const searchPromise = codeSearch ( {
356+ projectPath : '/test/project' ,
357+ pattern : 'test' ,
358+ maxResults : 2 ,
359+ } )
360+
361+ const output = [
362+ createRgJsonMatch ( 'file.ts' , 1 , 'test 1' ) ,
363+ createRgJsonMatch ( 'file.ts' , 2 , 'test 2' ) ,
364+ ] . join ( '\n' )
365+
366+ mockProcess . stdout . emit ( 'data' , Buffer . from ( output ) )
367+ mockProcess . emit ( 'close' , 0 )
368+
369+ const result = await searchPromise
370+ const value = asCodeSearchResult ( result [ 0 ] )
371+
372+ expect ( value . stdout ) . toContain ( 'Found 2 matches' )
373+ expect ( value . stdout ) . not . toContain ( 'Results limited' )
374+ } )
375+
346376 it ( 'should respect globalMaxResults with context lines' , async ( ) => {
347377 const searchPromise = codeSearch ( {
348378 projectPath : '/test/project' ,
@@ -447,8 +477,7 @@ describe('codeSearch', () => {
447477 const result = await searchPromise
448478 const value = asCodeSearchResult ( result [ 0 ] )
449479
450- // formatCodeSearchOutput returns 'No results' for empty input
451- expect ( value . stdout ) . toBe ( 'No results' )
480+ expect ( value . stdout ) . toBe ( 'Found 0 matches' )
452481 } )
453482 } )
454483
@@ -544,7 +573,13 @@ describe('codeSearch', () => {
544573 // Generate matches with long content to quickly exceed output size
545574 const matches : string [ ] = [ ]
546575 for ( let i = 0 ; i < 20 ; i ++ ) {
547- matches . push ( createRgJsonMatch ( 'file.ts' , i , `test line ${ i } with some content that is quite long to fill up the buffer quickly` ) )
576+ matches . push (
577+ createRgJsonMatch (
578+ 'file.ts' ,
579+ i ,
580+ `test line ${ i } with some content that is quite long to fill up the buffer quickly` ,
581+ ) ,
582+ )
548583 }
549584 const output = matches . join ( '\n' )
550585
@@ -559,8 +594,8 @@ describe('codeSearch', () => {
559594 const matchCount = ( value . stdout ! . match ( / t e s t l i n e \d + / g) || [ ] ) . length
560595 expect ( matchCount ) . toBeLessThan ( 20 )
561596 // Should indicate truncation happened
562- const hasTruncationMessage =
563- value . stdout ! . includes ( 'truncated' ) ||
597+ const hasTruncationMessage =
598+ value . stdout ! . includes ( 'truncated' ) ||
564599 value . stdout ! . includes ( 'limit reached' ) ||
565600 value . stdout ! . includes ( 'Output size limit' )
566601 expect ( hasTruncationMessage ) . toBe ( true )
@@ -616,7 +651,7 @@ describe('codeSearch', () => {
616651 expect ( result [ 0 ] . type ) . toBe ( 'json' )
617652 const value = asCodeSearchResult ( result [ 0 ] )
618653 expect ( value . stdout ) . toContain ( 'file.ts:' )
619-
654+
620655 // Verify the args passed to spawn include the glob flag correctly
621656 expect ( mockSpawn ) . toHaveBeenCalled ( )
622657 const spawnArgs = mockSpawn . mock . calls [ 0 ] ! [ 1 ] as string [ ]
@@ -631,7 +666,11 @@ describe('codeSearch', () => {
631666 flags : '-g *.ts -g *.tsx' ,
632667 } )
633668
634- const output = createRgJsonMatch ( 'file.tsx' , 1 , 'import React from "react"' )
669+ const output = createRgJsonMatch (
670+ 'file.tsx' ,
671+ 1 ,
672+ 'import React from "react"' ,
673+ )
635674
636675 mockProcess . stdout . emit ( 'data' , Buffer . from ( output ) )
637676 mockProcess . emit ( 'close' , 0 )
@@ -640,11 +679,13 @@ describe('codeSearch', () => {
640679 expect ( result [ 0 ] . type ) . toBe ( 'json' )
641680 const value = asCodeSearchResult ( result [ 0 ] )
642681 expect ( value . stdout ) . toContain ( 'file.tsx:' )
643-
682+
644683 // Verify both glob patterns are passed correctly
645684 const spawnArgs = mockSpawn . mock . calls [ 0 ] ! [ 1 ] as string [ ]
646685 // Should have two -g flags, each followed by its pattern
647- const gFlagIndices = spawnArgs . map ( ( arg , i ) => arg === '-g' ? i : - 1 ) . filter ( i => i !== - 1 )
686+ const gFlagIndices = spawnArgs
687+ . map ( ( arg , i ) => ( arg === '-g' ? i : - 1 ) )
688+ . filter ( ( i ) => i !== - 1 )
648689 expect ( gFlagIndices . length ) . toBe ( 2 )
649690 expect ( spawnArgs [ gFlagIndices [ 0 ] ! + 1 ] ) . toBe ( '*.ts' )
650691 expect ( spawnArgs [ gFlagIndices [ 1 ] ! + 1 ] ) . toBe ( '*.tsx' )
@@ -657,7 +698,11 @@ describe('codeSearch', () => {
657698 flags : "-g 'authentication.knowledge.md'" ,
658699 } )
659700
660- const output = createRgJsonMatch ( 'authentication.knowledge.md' , 5 , 'auth content' )
701+ const output = createRgJsonMatch (
702+ 'authentication.knowledge.md' ,
703+ 5 ,
704+ 'auth content' ,
705+ )
661706
662707 mockProcess . stdout . emit ( 'data' , Buffer . from ( output ) )
663708 mockProcess . emit ( 'close' , 0 )
@@ -721,23 +766,27 @@ describe('codeSearch', () => {
721766 flags : '-g *.ts -i -g *.tsx' ,
722767 } )
723768
724- const output = createRgJsonMatch ( 'file.tsx' , 1 , 'import React from "react"' )
769+ const output = createRgJsonMatch (
770+ 'file.tsx' ,
771+ 1 ,
772+ 'import React from "react"' ,
773+ )
725774
726775 mockProcess . stdout . emit ( 'data' , Buffer . from ( output ) )
727776 mockProcess . emit ( 'close' , 0 )
728777
729778 const result = await searchPromise
730-
779+
731780 // Verify flags are preserved in order without deduplication
732781 const spawnArgs = mockSpawn . mock . calls [ 0 ] ! [ 1 ] as string [ ]
733782 const flagsSection = spawnArgs . slice ( 0 , spawnArgs . indexOf ( '--' ) )
734783 expect ( flagsSection ) . toContain ( '-g' )
735784 expect ( flagsSection ) . toContain ( '*.ts' )
736785 expect ( flagsSection ) . toContain ( '-i' )
737786 expect ( flagsSection ) . toContain ( '*.tsx' )
738-
787+
739788 // Count -g flags - should be 2, not deduplicated to 1
740- const gCount = flagsSection . filter ( arg => arg === '-g' ) . length
789+ const gCount = flagsSection . filter ( ( arg ) => arg === '-g' ) . length
741790 expect ( gCount ) . toBe ( 2 )
742791 } )
743792 } )
0 commit comments