@@ -240,4 +240,53 @@ describe('dav composable', () => {
240240 await waitRefLoaded ( isLoading )
241241 expect ( abort ) . toBeCalledTimes ( 1 )
242242 } )
243+
244+ it ( 'a superseded (aborted) load does not clear the loading state of the newer load' , async ( ) => {
245+ // Each getDirectoryContents call stays pending until resolved manually,
246+ // and rejects with an AbortError when its signal is aborted — mirroring a
247+ // real DAV request that is cancelled on fast navigation.
248+ const pending : Array < { resolve : ( ) => void } > = [ ]
249+ const client = {
250+ stat : vi . fn ( ( v ) => ( { data : { path : v } } ) ) ,
251+ getDirectoryContents : vi . fn ( ( _path , opts ) => new Promise ( ( resolve , reject ) => {
252+ opts . signal ?. addEventListener ( 'abort' , ( ) => {
253+ const error = new Error ( 'aborted' )
254+ error . name = 'AbortError'
255+ reject ( error )
256+ } )
257+ pending . push ( { resolve : ( ) => resolve ( { data : [ ] } ) } )
258+ } ) ) ,
259+ }
260+ nextcloudFiles . getClient . mockImplementationOnce ( ( ) => client )
261+ nextcloudFiles . resultToNode . mockImplementation ( ( v ) => v )
262+
263+ const view = ref < 'files' | 'recent' | 'favorites' > ( 'files' )
264+ const path = ref ( '/' )
265+ const { loadFiles, isLoading } = useDAVFiles ( view , path )
266+
267+ // Load A is in flight
268+ loadFiles ( )
269+ await nextTick ( )
270+ expect ( pending ) . toHaveLength ( 1 )
271+ expect ( isLoading . value ) . toBe ( true )
272+
273+ // Load B supersedes A: navigating aborts A and starts B loading
274+ path . value = '/subdir/'
275+ await nextTick ( )
276+ expect ( pending ) . toHaveLength ( 2 )
277+
278+ // Let A's aborted request reject and run its catch/finally
279+ await nextTick ( )
280+ await nextTick ( )
281+
282+ // Regression: A's finally must not flip isLoading to false while B is
283+ // still loading — otherwise the FilePicker sees isLoading=false with a
284+ // null folder and confirms an empty selection ("No nodes selected").
285+ expect ( isLoading . value ) . toBe ( true )
286+
287+ // Completing B settles the loading state
288+ pending [ 1 ] . resolve ( )
289+ await waitRefLoaded ( isLoading )
290+ expect ( isLoading . value ) . toBe ( false )
291+ } )
243292} )
0 commit comments