@@ -156,6 +156,7 @@ vi.mock("../lib/logger.js", () => ({
156156 logInfo : vi . fn ( ) ,
157157 logWarn : vi . fn ( ) ,
158158 logError : vi . fn ( ) ,
159+ maskEmail : vi . fn ( ( email : string ) => email ) ,
159160 setCorrelationId : vi . fn ( ( ) => "test-correlation-id" ) ,
160161 clearCorrelationId : vi . fn ( ) ,
161162 createLogger : vi . fn ( ( ) => ( {
@@ -333,6 +334,7 @@ const withAccountStorageTransactionMock = vi.fn(
333334 return nextRun ;
334335 } ,
335336) ;
337+ const withAccountAndFlaggedStorageTransactionMock = vi . fn ( ) ;
336338
337339const syncCodexCliSelectionMock = vi . fn ( async ( _index : number ) => { } ) ;
338340
@@ -343,6 +345,8 @@ vi.mock("../lib/storage.js", async () => {
343345 getStoragePath : ( ) => "/mock/path/accounts.json" ,
344346 loadAccounts : loadAccountsMock ,
345347 saveAccounts : saveAccountsMock ,
348+ withAccountAndFlaggedStorageTransaction :
349+ withAccountAndFlaggedStorageTransactionMock ,
346350 withAccountStorageTransaction : withAccountStorageTransactionMock ,
347351 clearAccounts : clearAccountsMock ,
348352 setStoragePath : vi . fn ( ) ,
@@ -776,6 +780,82 @@ describe("OpenAIOAuthPlugin", () => {
776780 expect . stringContaining ( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ) ,
777781 ) ;
778782 } ) ;
783+
784+ it ( "uses combined flagged persistence when verify-flagged restores from the login menu" , async ( ) => {
785+ const cliModule = await import ( "../lib/cli.js" ) ;
786+ const refreshQueueModule = await import ( "../lib/refresh-queue.js" ) ;
787+ const storageModule = await import ( "../lib/storage.js" ) ;
788+ const now = Date . now ( ) ;
789+ const flaggedStorage = {
790+ version : 1 as const ,
791+ accounts : [
792+ {
793+ refreshToken : "flagged-refresh" ,
794+ accountId : "flagged-account" ,
795+ email : "flagged@example.com" ,
796+ addedAt : now - 1_000 ,
797+ lastUsed : now - 1_000 ,
798+ flaggedAt : now - 5_000 ,
799+ } ,
800+ ] ,
801+ } ;
802+ let loadFlaggedCallCount = 0 ;
803+
804+ vi . mocked ( cliModule . promptLoginMode )
805+ . mockResolvedValueOnce ( { mode : "verify-flagged" } as never )
806+ . mockResolvedValueOnce ( { mode : "cancel" } as never ) ;
807+ vi . mocked ( refreshQueueModule . queuedRefresh ) . mockResolvedValueOnce ( {
808+ type : "success" ,
809+ access : "restored-access" ,
810+ refresh : "restored-refresh" ,
811+ expires : now + 60_000 ,
812+ } ) ;
813+ vi . mocked ( storageModule . loadFlaggedAccounts ) . mockImplementation ( async ( ) => {
814+ loadFlaggedCallCount += 1 ;
815+ return loadFlaggedCallCount <= 2
816+ ? flaggedStorage
817+ : { version : 1 , accounts : [ ] } ;
818+ } ) ;
819+ withAccountAndFlaggedStorageTransactionMock . mockImplementationOnce (
820+ async ( handler ) =>
821+ handler (
822+ {
823+ version : 3 ,
824+ accounts : mockStorage . accounts . map ( ( account ) =>
825+ cloneMockAccount ( account ) ,
826+ ) ,
827+ activeIndex : mockStorage . activeIndex ,
828+ activeIndexByFamily : { ...mockStorage . activeIndexByFamily } ,
829+ } ,
830+ async ( storage , nextFlaggedStorage ) => {
831+ await saveAccountsMock ( storage ) ;
832+ await vi . mocked ( storageModule . saveFlaggedAccounts ) (
833+ nextFlaggedStorage ,
834+ ) ;
835+ } ,
836+ flaggedStorage ,
837+ ) ,
838+ ) ;
839+
840+ const autoMethod = plugin . auth . methods [ 0 ] as unknown as {
841+ authorize : ( ) => Promise < unknown > ;
842+ } ;
843+ await autoMethod . authorize ( ) ;
844+
845+ expect ( withAccountAndFlaggedStorageTransactionMock ) . toHaveBeenCalledTimes ( 1 ) ;
846+ expect ( mockStorage . accounts ) . toEqual (
847+ expect . arrayContaining ( [
848+ expect . objectContaining ( {
849+ refreshToken : "restored-refresh" ,
850+ accessToken : "restored-access" ,
851+ } ) ,
852+ ] ) ,
853+ ) ;
854+ expect ( vi . mocked ( storageModule . saveFlaggedAccounts ) ) . toHaveBeenCalledWith ( {
855+ version : 1 ,
856+ accounts : [ ] ,
857+ } ) ;
858+ } ) ;
779859 } ) ;
780860
781861 describe ( "event handler" , ( ) => {
0 commit comments