@@ -18,6 +18,7 @@ vi.mock("../../../shell/logger", () => ({
1818} ) ) ;
1919
2020import { useWarmTask } from "./useWarmTask" ;
21+ import { takeWarmTaskLease } from "./warmTaskLease" ;
2122
2223interface Props {
2324 workspaceMode : WorkspaceMode ;
@@ -238,6 +239,68 @@ describe("useWarmTask", () => {
238239 expect ( mockClient . warmTask ) . toHaveBeenCalledTimes ( 2 ) ;
239240 } ) ;
240241
242+ it ( "warms only the latest image when selection changes during the debounce" , async ( ) => {
243+ const { rerender } = renderHook ( ( props : Props ) => useWarmTask ( props ) , {
244+ initialProps : { ...cloudTyping , customImageId : "image-123" } ,
245+ } ) ;
246+
247+ rerender ( { ...cloudTyping , customImageId : "image-456" } ) ;
248+ await flushDebounce ( ) ;
249+
250+ expect ( mockClient . warmTask ) . toHaveBeenCalledOnce ( ) ;
251+ expect ( mockClient . warmTask ) . toHaveBeenCalledWith ( {
252+ repository : "acme/repo" ,
253+ github_integration : 42 ,
254+ branch : "main" ,
255+ ...NULL_RUNTIME ,
256+ custom_image_id : "image-456" ,
257+ } ) ;
258+ } ) ;
259+
260+ it ( "keeps the latest image lease when warm responses complete out of order" , async ( ) => {
261+ type WarmResponse = { task_id : string ; run_id : string } ;
262+ let resolveFirstWarm ! : ( value : WarmResponse ) => void ;
263+ let resolveSecondWarm ! : ( value : WarmResponse ) => void ;
264+ const firstWarm = new Promise < WarmResponse > ( ( resolve ) => {
265+ resolveFirstWarm = resolve ;
266+ } ) ;
267+ const secondWarm = new Promise < WarmResponse > ( ( resolve ) => {
268+ resolveSecondWarm = resolve ;
269+ } ) ;
270+ mockClient . warmTask
271+ . mockReturnValueOnce ( firstWarm )
272+ . mockReturnValueOnce ( secondWarm ) ;
273+
274+ const { rerender } = renderHook ( ( props : Props ) => useWarmTask ( props ) , {
275+ initialProps : { ...cloudTyping , customImageId : "image-123" } ,
276+ } ) ;
277+ await flushDebounce ( ) ;
278+
279+ rerender ( { ...cloudTyping , customImageId : "image-456" } ) ;
280+ await flushDebounce ( ) ;
281+
282+ await act ( async ( ) => {
283+ resolveSecondWarm ( { task_id : "task-2" , run_id : "run-2" } ) ;
284+ await secondWarm ;
285+ } ) ;
286+ await act ( async ( ) => {
287+ resolveFirstWarm ( { task_id : "task-1" , run_id : "run-1" } ) ;
288+ await firstWarm ;
289+ } ) ;
290+
291+ expect (
292+ takeWarmTaskLease ( {
293+ repository : "acme/repo" ,
294+ branch : "main" ,
295+ runtimeAdapter : null ,
296+ model : null ,
297+ reasoningEffort : null ,
298+ sandboxEnvironmentId : null ,
299+ customImageId : "image-456" ,
300+ } ) ,
301+ ) . toEqual ( { taskId : "task-2" , runId : "run-2" } ) ;
302+ } ) ;
303+
241304 it ( "warms again for a new selection after a failed warm" , async ( ) => {
242305 mockClient . warmTask . mockRejectedValueOnce ( new Error ( "boom" ) ) ;
243306 const { rerender } = renderHook ( ( props : Props ) => useWarmTask ( props ) , {
0 commit comments