@@ -12,6 +12,7 @@ import {
1212 resetOauthClientForTesting ,
1313 clearCachedCredentialFile ,
1414 clearOauthClientCache ,
15+ authEvents ,
1516} from './oauth2.js' ;
1617import { UserAccountManager } from '../utils/userAccountManager.js' ;
1718import { OAuth2Client , Compute , GoogleAuth } from 'google-auth-library' ;
@@ -109,13 +110,18 @@ describe('oauth2', () => {
109110 const mockGetAccessToken = vi
110111 . fn ( )
111112 . mockResolvedValue ( { token : 'mock-access-token' } ) ;
113+ let tokensListener : ( ( tokens : Credentials ) => void ) | undefined ;
112114 const mockOAuth2Client = {
113115 generateAuthUrl : mockGenerateAuthUrl ,
114116 getToken : mockGetToken ,
115117 setCredentials : mockSetCredentials ,
116118 getAccessToken : mockGetAccessToken ,
117119 credentials : mockTokens ,
118- on : vi . fn ( ) ,
120+ on : vi . fn ( ( event , listener ) => {
121+ if ( event === 'tokens' ) {
122+ tokensListener = listener ;
123+ }
124+ } ) ,
119125 } as unknown as OAuth2Client ;
120126 vi . mocked ( OAuth2Client ) . mockImplementation ( ( ) => mockOAuth2Client ) ;
121127
@@ -195,6 +201,11 @@ describe('oauth2', () => {
195201 } ) ;
196202 expect ( mockSetCredentials ) . toHaveBeenCalledWith ( mockTokens ) ;
197203
204+ // Manually trigger the 'tokens' event listener
205+ if ( tokensListener ) {
206+ await tokensListener ( mockTokens ) ;
207+ }
208+
198209 // Verify Google Account was cached
199210 const googleAccountPath = path . join (
200211 tempHomeDir ,
@@ -215,6 +226,45 @@ describe('oauth2', () => {
215226 ) ;
216227 } ) ;
217228
229+ it ( 'should clear credentials file' , async ( ) => {
230+ // Setup initial state with files
231+ const credsPath = path . join ( tempHomeDir , GEMINI_DIR , 'oauth_creds.json' ) ;
232+
233+ await fs . promises . mkdir ( path . dirname ( credsPath ) , { recursive : true } ) ;
234+ await fs . promises . writeFile ( credsPath , '{}' ) ;
235+
236+ await clearCachedCredentialFile ( ) ;
237+
238+ expect ( fs . existsSync ( credsPath ) ) . toBe ( false ) ;
239+ } ) ;
240+
241+ it ( 'should emit post_auth event when loading cached credentials' , async ( ) => {
242+ const cachedCreds = { refresh_token : 'cached-token' } ;
243+ const credsPath = path . join ( tempHomeDir , GEMINI_DIR , 'oauth_creds.json' ) ;
244+ await fs . promises . mkdir ( path . dirname ( credsPath ) , { recursive : true } ) ;
245+ await fs . promises . writeFile ( credsPath , JSON . stringify ( cachedCreds ) ) ;
246+
247+ const mockClient = {
248+ setCredentials : vi . fn ( ) ,
249+ getAccessToken : vi . fn ( ) . mockResolvedValue ( { token : 'test-token' } ) ,
250+ getTokenInfo : vi . fn ( ) . mockResolvedValue ( { } ) ,
251+ on : vi . fn ( ) ,
252+ } ;
253+ vi . mocked ( OAuth2Client ) . mockImplementation (
254+ ( ) => mockClient as unknown as OAuth2Client ,
255+ ) ;
256+
257+ const eventPromise = new Promise < void > ( ( resolve ) => {
258+ authEvents . once ( 'post_auth' , ( creds ) => {
259+ expect ( creds . refresh_token ) . toBe ( 'cached-token' ) ;
260+ resolve ( ) ;
261+ } ) ;
262+ } ) ;
263+
264+ await getOauthClient ( AuthType . LOGIN_WITH_GOOGLE , mockConfig ) ;
265+ await eventPromise ;
266+ } ) ;
267+
218268 it ( 'should perform login with user code' , async ( ) => {
219269 const mockConfigWithNoBrowser = {
220270 getNoBrowser : ( ) => true ,
0 commit comments