@@ -33,8 +33,12 @@ describe("GhostInlineCompletionProvider - Request Deduplication", () => {
3333 // Helper to call provideInlineCompletionItems and advance timers
3434 async function provideWithDebounce ( doc : vscode . TextDocument , pos : vscode . Position ) {
3535 const promise = provider . provideInlineCompletionItems_Internal ( doc , pos , { } as any , { } as any )
36- await vi . advanceTimersByTimeAsync ( 300 ) // Advance past debounce delay
37- return promise
36+ // Wait a tick to let the promise chain set up
37+ await Promise . resolve ( )
38+ // Advance timers past debounce delay
39+ await vi . advanceTimersByTimeAsync ( 300 )
40+ // Wait for the completion to finish
41+ return await promise
3842 }
3943
4044 beforeEach ( ( ) => {
@@ -49,9 +53,16 @@ describe("GhostInlineCompletionProvider - Request Deduplication", () => {
4953
5054 mockContextProvider = {
5155 getIde : vi . fn ( ) . mockReturnValue ( mockIde ) ,
52- getFormattedContext : vi . fn ( ) . mockResolvedValue ( "" ) ,
53- getFimFormattedContext : vi . fn ( ) . mockResolvedValue ( { prefix : "" } ) ,
54- getFimCompiledPrefix : vi . fn ( ) . mockResolvedValue ( "" ) ,
56+ getProcessedSnippets : vi . fn ( ) . mockResolvedValue ( {
57+ filepathUri : "file:///test.ts" ,
58+ helper : {
59+ lang : { name : "typescript" , singleLineComment : "//" } ,
60+ prunedPrefix : "" ,
61+ prunedSuffix : "" ,
62+ } ,
63+ snippetsWithUris : [ ] ,
64+ workspaceDirs : [ ] ,
65+ } ) ,
5566 }
5667
5768 mockModel = {
@@ -93,17 +104,25 @@ describe("GhostInlineCompletionProvider - Request Deduplication", () => {
93104 let callCount = 0
94105 vi . mocked ( mockModel . generateResponse ) . mockImplementation ( async ( _sys , _user , onChunk ) => {
95106 callCount ++
96- onChunk ( { type : "text" , text : "test suggestion" } )
107+ onChunk ( { type : "text" , text : "<COMPLETION> test suggestion</COMPLETION> " } )
97108 return mockResponse
98109 } )
99110
100111 const document = new MockTextDocument ( vscode . Uri . file ( "/test/file.ts" ) , "const x = \nconst y = 2" )
101112 const position = new vscode . Position ( 0 , 10 )
102113
103- // Make two identical requests quickly
104- const promise1 = provideWithDebounce ( document , position )
105- const promise2 = provideWithDebounce ( document , position )
114+ // Make two identical requests - the second should reuse the first's pending request
115+ const promise1 = provider . provideInlineCompletionItems_Internal ( document , position , { } as any , { } as any )
116+
117+ // Wait a tick to let the first request's debounce timer start
118+ await Promise . resolve ( )
119+
120+ const promise2 = provider . provideInlineCompletionItems_Internal ( document , position , { } as any , { } as any )
106121
122+ // Advance timers to trigger the debounce
123+ await vi . advanceTimersByTimeAsync ( 300 )
124+
125+ // Wait for both promises to complete
107126 await Promise . all ( [ promise1 , promise2 ] )
108127
109128 // Should only call the API once due to deduplication
@@ -122,20 +141,26 @@ describe("GhostInlineCompletionProvider - Request Deduplication", () => {
122141 let callCount = 0
123142 vi . mocked ( mockModel . generateResponse ) . mockImplementation ( async ( _sys , _user , onChunk ) => {
124143 callCount ++
125- onChunk ( { type : "text" , text : "function test() {}" } )
144+ onChunk ( { type : "text" , text : "<COMPLETION> function test() {}</COMPLETION> " } )
126145 return mockResponse
127146 } )
128147
129148 const document = new MockTextDocument ( vscode . Uri . file ( "/test/file.ts" ) , "const x = f\nconst y = 2" )
130149 const position1 = new vscode . Position ( 0 , 11 )
131- const position2 = new vscode . Position ( 0 , 12 ) // User typed one more character
132150
133151 // Start first request
134- const promise1 = provideWithDebounce ( document , position1 )
152+ const promise1 = provider . provideInlineCompletionItems_Internal ( document , position1 , { } as any , { } as any )
153+
154+ // Wait a tick
155+ await Promise . resolve ( )
135156
157+ // User types ahead - new document with one more character
136158 const document2 = new MockTextDocument ( vscode . Uri . file ( "/test/file.ts" ) , "const x = fu\nconst y = 2" )
159+ const position2 = new vscode . Position ( 0 , 12 )
160+ const promise2 = provider . provideInlineCompletionItems_Internal ( document2 , position2 , { } as any , { } as any )
137161
138- const promise2 = provideWithDebounce ( document2 , position2 )
162+ // Advance timers
163+ await vi . advanceTimersByTimeAsync ( 300 )
139164
140165 await Promise . all ( [ promise1 , promise2 ] )
141166
@@ -156,19 +181,25 @@ describe("GhostInlineCompletionProvider - Request Deduplication", () => {
156181
157182 vi . mocked ( mockModel . generateResponse ) . mockImplementation ( async ( _sys , _user , onChunk ) => {
158183 callCount ++
159- onChunk ( { type : "text" , text : "test suggestion" } )
184+ onChunk ( { type : "text" , text : "<COMPLETION> test suggestion</COMPLETION> " } )
160185 return mockResponse
161186 } )
162187
163188 const document1 = new MockTextDocument ( vscode . Uri . file ( "/test/file.ts" ) , "const x = f\nconst y = 2" )
164- const document2 = new MockTextDocument ( vscode . Uri . file ( "/test/file.ts" ) , "const x = g\nconst y = 2" )
165-
166189 const position = new vscode . Position ( 0 , 11 )
167190
168191 // Start first request
169- const promise1 = provideWithDebounce ( document1 , position )
192+ const promise1 = provider . provideInlineCompletionItems_Internal ( document1 , position , { } as any , { } as any )
193+
194+ // Wait a tick
195+ await Promise . resolve ( )
196+
197+ // User changes to different prefix - this should cancel the first request
198+ const document2 = new MockTextDocument ( vscode . Uri . file ( "/test/file.ts" ) , "const x = g\nconst y = 2" )
199+ const promise2 = provider . provideInlineCompletionItems_Internal ( document2 , position , { } as any , { } as any )
170200
171- const promise2 = provideWithDebounce ( document2 , position )
201+ // Advance timers
202+ await vi . advanceTimersByTimeAsync ( 300 )
172203
173204 await Promise . all ( [ promise1 , promise2 ] )
174205
0 commit comments