@@ -167,6 +167,8 @@ describe('an import keeps its lease while it runs', () => {
167167 stopped : boolean
168168 renewalsReceived : number
169169 transient : number [ ]
170+ /** How long the server takes to answer the next renewal it receives. */
171+ nextAnswerDelayMs : number
170172 }
171173 let scanMs : number
172174 let finishUpload : ( ) => void
@@ -176,7 +178,14 @@ describe('an import keeps its lease while it runs', () => {
176178
177179 beforeEach ( ( ) => {
178180 vi . useFakeTimers ( )
179- server = { leaseUntil : 0 , claimed : false , stopped : false , renewalsReceived : 0 , transient : [ ] }
181+ server = {
182+ leaseUntil : 0 ,
183+ claimed : false ,
184+ stopped : false ,
185+ renewalsReceived : 0 ,
186+ transient : [ ] ,
187+ nextAnswerDelayMs : 0 ,
188+ }
180189 scanMs = 0
181190 mocks . invoke . mockImplementation ( async ( request : { operation : string } ) => {
182191 if ( request . operation !== 'manifest' )
@@ -195,10 +204,14 @@ describe('an import keeps its lease while it runs', () => {
195204 mocks . json . mockImplementation ( async ( contract : unknown ) => {
196205 if ( contract !== renewDesktopToolLeaseContract ) return { folder : { id : 'created-folder' } }
197206 server . renewalsReceived += 1
207+ const delayMs = server . nextAnswerDelayMs
208+ server . nextAnswerDelayMs = 0
198209 const transient = server . transient . shift ( )
210+ const refused = server . stopped || ! server . claimed || ! leaseLive ( )
211+ if ( ! transient && ! refused ) server . leaseUntil = Date . now ( ) + LEASE_MS
212+ await sleep ( delayMs )
199213 if ( transient ) return answer ( transient )
200- if ( server . stopped || ! server . claimed || ! leaseLive ( ) ) return answer ( 410 )
201- server . leaseUntil = Date . now ( ) + LEASE_MS
214+ if ( refused ) return answer ( 410 )
202215 return { renewed : true }
203216 } )
204217 } )
@@ -220,6 +233,18 @@ describe('an import keeps its lease while it runs', () => {
220233 expect ( leaseLive ( ) ) . toBe ( false )
221234 } )
222235
236+ it ( 'a refusal of a renewal sent before the claim does not stop it, however late it arrives' , async ( ) => {
237+ // The first renewal goes out before the desktop claims the call; its 410 arrives only after
238+ // the manifest confirmed the claim.
239+ server . nextAnswerDelayMs = 5_000
240+ scanMs = 1_000
241+ const run = executeNativeFileTool ( 'tool' , 'import_local_files' )
242+ await vi . advanceTimersByTimeAsync ( 90_000 )
243+ expect ( leaseLive ( ) ) . toBe ( true )
244+ finishUpload ( )
245+ await run
246+ } )
247+
223248 it ( 'stops renewing once the server refuses the claimed call' , async ( ) => {
224249 const run = executeNativeFileTool ( 'tool' , 'import_local_files' )
225250 await vi . advanceTimersByTimeAsync ( 1_000 )
0 commit comments