@@ -2400,6 +2400,112 @@ describe("OpenAIOAuthPlugin", () => {
24002400 expect ( vi . mocked ( storageModule . withAccountAndFlaggedStorageTransaction ) ) . toHaveBeenCalled ( ) ;
24012401 expect ( vi . mocked ( storageModule . withFlaggedAccountsTransaction ) ) . not . toHaveBeenCalled ( ) ;
24022402 } ) ;
2403+
2404+ it ( "restores sync prune backup when sync fails after successful prune removal" , async ( ) => {
2405+ const cliModule = await import ( "../lib/cli.js" ) ;
2406+ const confirmModule = await import ( "../lib/ui/confirm.js" ) ;
2407+ const configModule = await import ( "../lib/config.js" ) ;
2408+ const storageModule = await import ( "../lib/storage.js" ) ;
2409+ const syncModule = await import ( "../lib/codex-multi-auth-sync.js" ) ;
2410+
2411+ mockStorage . accounts = [
2412+ {
2413+ accountId : "remove-me" ,
2414+ email : "remove@example.com" ,
2415+ refreshToken : "refresh-remove" ,
2416+ accessToken : "access-remove" ,
2417+ idToken : "id-remove" ,
2418+ addedAt : 1 ,
2419+ lastUsed : 1 ,
2420+ } ,
2421+ {
2422+ accountId : "keep-me" ,
2423+ email : "keep@example.com" ,
2424+ refreshToken : "refresh-keep" ,
2425+ accessToken : "access-keep" ,
2426+ idToken : "id-keep" ,
2427+ addedAt : 2 ,
2428+ lastUsed : 2 ,
2429+ } ,
2430+ ] ;
2431+ mockStorage . activeIndex = 1 ;
2432+ mockStorage . activeIndexByFamily = { codex : 1 } ;
2433+ mockFlaggedStorage . accounts = [
2434+ {
2435+ accountId : "remove-me" ,
2436+ email : "remove@example.com" ,
2437+ refreshToken : "refresh-remove" ,
2438+ accessToken : "flagged-access-remove" ,
2439+ idToken : "flagged-id-remove" ,
2440+ flaggedAt : 123 ,
2441+ addedAt : 1 ,
2442+ lastUsed : 1 ,
2443+ } ,
2444+ ] ;
2445+
2446+ const originalAccounts = cloneMockStorage ( ) ;
2447+ const originalFlagged = cloneMockFlaggedStorage ( ) ;
2448+ const { CodexMultiAuthSyncCapacityError } = syncModule ;
2449+ vi . mocked ( configModule . getSyncFromCodexMultiAuthEnabled ) . mockReturnValue ( true ) ;
2450+ vi . mocked ( cliModule . promptLoginMode )
2451+ . mockResolvedValueOnce ( { mode : "experimental-sync-now" } )
2452+ . mockResolvedValueOnce ( { mode : "cancel" } )
2453+ . mockResolvedValue ( { mode : "cancel" } ) ;
2454+ vi . mocked ( cliModule . promptCodexMultiAuthSyncPrune ) . mockResolvedValueOnce ( [ 0 ] ) ;
2455+ vi . mocked ( confirmModule . confirm ) . mockResolvedValue ( true ) ;
2456+ vi . mocked ( syncModule . previewSyncFromCodexMultiAuth )
2457+ . mockRejectedValueOnce (
2458+ new CodexMultiAuthSyncCapacityError ( {
2459+ rootDir : "/tmp/codex-source" ,
2460+ accountsPath : "/tmp/codex-source/openai-codex-accounts.json" ,
2461+ scope : "global" ,
2462+ currentCount : 2 ,
2463+ sourceCount : 1 ,
2464+ sourceDedupedTotal : 1 ,
2465+ dedupedTotal : 3 ,
2466+ maxAccounts : 2 ,
2467+ needToRemove : 1 ,
2468+ importableNewAccounts : 1 ,
2469+ skippedOverlaps : 0 ,
2470+ suggestedRemovals : [
2471+ {
2472+ index : 0 ,
2473+ email : "remove@example.com" ,
2474+ accountLabel : "Remove Me" ,
2475+ refreshToken : "refresh-remove" ,
2476+ organizationId : undefined ,
2477+ accountId : "remove-me" ,
2478+ isCurrentAccount : false ,
2479+ score : 100 ,
2480+ reason : "test removal" ,
2481+ } ,
2482+ ] ,
2483+ } ) ,
2484+ )
2485+ . mockResolvedValueOnce ( {
2486+ rootDir : "/tmp/codex-source" ,
2487+ accountsPath : "/tmp/codex-source/openai-codex-accounts.json" ,
2488+ scope : "global" ,
2489+ imported : 1 ,
2490+ skipped : 0 ,
2491+ total : 2 ,
2492+ } ) ;
2493+ vi . mocked ( syncModule . syncFromCodexMultiAuth ) . mockRejectedValueOnce (
2494+ new Error ( "sync failed after prune" ) ,
2495+ ) ;
2496+
2497+ const autoMethod = plugin . auth . methods [ 0 ] as unknown as {
2498+ authorize : ( inputs ?: Record < string , string > ) => Promise < { instructions : string } > ;
2499+ } ;
2500+
2501+ const result = await autoMethod . authorize ( ) ;
2502+ expect ( result . instructions ) . toBe ( "Authentication cancelled" ) ;
2503+ expect ( mockStorage ) . toMatchObject ( originalAccounts ) ;
2504+ expect ( mockFlaggedStorage ) . toMatchObject ( originalFlagged ) ;
2505+ expect ( vi . mocked ( storageModule . loadAccountAndFlaggedStorageSnapshot ) ) . toHaveBeenCalledTimes ( 1 ) ;
2506+ expect ( vi . mocked ( storageModule . withAccountAndFlaggedStorageTransaction ) ) . toHaveBeenCalledTimes ( 2 ) ;
2507+ expect ( vi . mocked ( syncModule . syncFromCodexMultiAuth ) ) . toHaveBeenCalledTimes ( 1 ) ;
2508+ } ) ;
24032509 } ) ;
24042510} ) ;
24052511
0 commit comments