@@ -325,6 +325,42 @@ describe('OAuth account application operations', () => {
325325 } )
326326
327327 it ( 'claims a tokenless QuickBooks account before deleting local credentials' , async ( ) => {
328+ const linkedCredential = {
329+ ...firstCredential ,
330+ providerId : 'quickbooks' ,
331+ accountId : 'account-1' ,
332+ }
333+ queueTableRows ( account , [
334+ {
335+ id : 'account-1' ,
336+ providerId : 'quickbooks' ,
337+ accessToken : null ,
338+ refreshToken : null ,
339+ oauthConfig : 'encrypted-config' ,
340+ updatedAt : new Date ( '2026-08-01T00:00:00.000Z' ) ,
341+ } ,
342+ ] )
343+ queueTableRows ( credential , [ linkedCredential ] )
344+ dbChainMockFns . returning . mockResolvedValueOnce ( [ { id : 'account-1' } ] )
345+ mocks . deleteCredential . mockResolvedValueOnce ( true )
346+
347+ await expect (
348+ disconnectOAuthUseCase . execute ( {
349+ principal : { kind : 'session' , userId : 'user-1' , sessionId : 'session-1' } ,
350+ input : { provider : 'quickbooks' , accountId : 'account-1' } ,
351+ } )
352+ ) . resolves . toMatchObject ( { success : true , credentials : [ linkedCredential ] } )
353+
354+ expect ( mocks . revokeQuickBooksToken ) . not . toHaveBeenCalled ( )
355+ expect ( dbChainMockFns . update ) . toHaveBeenCalledWith ( account )
356+ expect ( mocks . deleteCredential ) . toHaveBeenCalledWith ( {
357+ credential : linkedCredential ,
358+ reason : 'oauth_disconnect' ,
359+ } )
360+ expect ( dbChainMockFns . delete ) . toHaveBeenCalledWith ( account )
361+ } )
362+
363+ it ( 'skips tokenless QuickBooks cleanup when a reconnect wins the account claim' , async ( ) => {
328364 queueTableRows ( account , [
329365 {
330366 id : 'account-1' ,
0 commit comments