Skip to content

Commit 4f36728

Browse files
committed
adding unit test
1 parent 263f07b commit 4f36728

File tree

1 file changed

+113
-1
lines changed

1 file changed

+113
-1
lines changed

packages/auth/src/core/auth/auth_impl.test.ts

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@ import { mockEndpointWithParams } from '../../../test/helpers/api/helper';
4747
import { Endpoint, RecaptchaClientType, RecaptchaVersion } from '../../api';
4848
import * as mockFetch from '../../../test/helpers/mock_fetch';
4949
import { AuthErrorCode } from '../errors';
50+
import * as exchangeTokenModule from '../strategies/exhange_token';
5051
import {
5152
FirebaseToken,
52-
PasswordValidationStatus
53+
PasswordValidationStatus,
54+
TokenRefreshHandler
5355
} from '../../model/public_types';
5456
import { PasswordPolicyImpl } from './password_policy_impl';
5557
import { PersistenceUserManager } from '../persistence/persistence_user_manager';
@@ -302,6 +304,116 @@ describe('core/auth/auth_impl', () => {
302304
});
303305
});
304306

307+
describe('#setTokenRefreshHandler', () => {
308+
it('sets the tokenRefreshHandler on the auth object', () => {
309+
const handler: TokenRefreshHandler = {
310+
refreshIdpToken: async () => ({ idToken: 'a', idpConfigId: 'b' })
311+
};
312+
auth.setTokenRefreshHandler(handler);
313+
expect((auth as any).tokenRefreshHandler).to.eq(handler);
314+
});
315+
316+
describe('#getFirebaseAccessToken', () => {
317+
let exchangeTokenStub: sinon.SinonStub;
318+
let mockToken: FirebaseToken;
319+
let expiredMockToken: FirebaseToken;
320+
let tokenRefreshHandler: TokenRefreshHandler;
321+
const tokenKey = `firebase:persistence-token:${FAKE_APP.options.apiKey!}:${
322+
FAKE_APP.name
323+
}`;
324+
325+
beforeEach(() => {
326+
exchangeTokenStub = sinon.stub(exchangeTokenModule, 'exchangeToken').resolves();
327+
328+
mockToken = {
329+
token: 'test-token',
330+
expirationTime: Date.now() + 300000 // 5 minutes from now
331+
};
332+
expiredMockToken = {
333+
token: 'expired-test-token',
334+
expirationTime: Date.now() - 1000 // 1 second ago
335+
};
336+
tokenRefreshHandler = {
337+
refreshIdpToken: sinon.stub().resolves({
338+
idToken: 'new-id-token',
339+
idpConfigId: 'test-idp'
340+
})
341+
};
342+
// Reset cached token and persistence before each test
343+
(auth as any).firebaseToken = null;
344+
persistenceStub._get.withArgs(tokenKey).resolves(null);
345+
});
346+
347+
afterEach(() => {
348+
sinon.restore();
349+
});
350+
351+
it('should return the existing token if it is valid', async () => {
352+
persistenceStub._get.withArgs(tokenKey).resolves(mockToken as any);
353+
const token = await auth.getFirebaseAccessToken();
354+
expect(token).to.eql(mockToken);
355+
expect(exchangeTokenStub).not.to.have.been.called;
356+
});
357+
358+
it('should return null if the token is expired and no token refresh handler is set', async () => {
359+
persistenceStub._get.withArgs(tokenKey).resolves(expiredMockToken as any);
360+
const token = await auth.getFirebaseAccessToken();
361+
expect(token).to.be.null;
362+
expect(exchangeTokenStub).not.to.have.been.called;
363+
});
364+
365+
it('should refresh the token if it is expired and a token refresh handler is set', async () => {
366+
persistenceStub._get.withArgs(tokenKey).resolves(expiredMockToken as any);
367+
auth.setTokenRefreshHandler(tokenRefreshHandler);
368+
369+
exchangeTokenStub.callsFake(async () => {
370+
// When exchangeToken is called, simulate that the new token is persisted.
371+
persistenceStub._get.withArgs(tokenKey).resolves(mockToken as any);
372+
});
373+
374+
const token = await auth.getFirebaseAccessToken();
375+
376+
expect(tokenRefreshHandler.refreshIdpToken).to.have.been.calledOnce;
377+
expect(exchangeTokenStub).to.have.been.calledWith(auth, 'test-idp', 'new-id-token');
378+
expect(token).to.eql(mockToken);
379+
});
380+
381+
it('should force refresh the token when forceRefresh is true', async () => {
382+
persistenceStub._get.withArgs(tokenKey).resolves(mockToken as any);
383+
auth.setTokenRefreshHandler(tokenRefreshHandler);
384+
385+
exchangeTokenStub.callsFake(async () => {
386+
persistenceStub._get.withArgs(tokenKey).resolves(mockToken as any);
387+
});
388+
389+
await auth.getFirebaseAccessToken(true);
390+
391+
expect(tokenRefreshHandler.refreshIdpToken).to.have.been.calledOnce;
392+
expect(exchangeTokenStub).to.have.been.calledWith(auth, 'test-idp', 'new-id-token');
393+
});
394+
395+
it('should return null and log an error if token refresh fails', async () => {
396+
const consoleErrorStub = sinon.stub(console, 'error');
397+
persistenceStub._get.withArgs(tokenKey).resolves(expiredMockToken as any);
398+
(tokenRefreshHandler.refreshIdpToken as sinon.SinonStub).rejects(new Error('refresh failed'));
399+
auth.setTokenRefreshHandler(tokenRefreshHandler);
400+
const token = await auth.getFirebaseAccessToken();
401+
expect(token).to.be.null;
402+
expect(consoleErrorStub).to.have.been.calledWith('Token refresh failed:', sinon.match.instanceOf(Error));
403+
});
404+
405+
it('should return null and log an error if the refreshed token is invalid', async () => {
406+
const consoleErrorStub = sinon.stub(console, 'error');
407+
persistenceStub._get.withArgs(tokenKey).resolves(expiredMockToken as any);
408+
(tokenRefreshHandler.refreshIdpToken as sinon.SinonStub).resolves({ idToken: 'new-id-token' }); // Missing idpConfigId
409+
auth.setTokenRefreshHandler(tokenRefreshHandler);
410+
const token = await auth.getFirebaseAccessToken();
411+
expect(token).to.be.null;
412+
expect(consoleErrorStub).to.have.been.calledWith('Token refresh failed:', sinon.match.instanceOf(FirebaseError));
413+
});
414+
});
415+
416+
305417
describe('#signOut', () => {
306418
it('sets currentUser to null, calls remove', async () => {
307419
await auth._updateCurrentUser(testUser(auth, 'test'));

0 commit comments

Comments
 (0)