UNPKG

voluptasmollitia

Version:
218 lines (188 loc) 7.09 kB
/** * @license * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { FirebaseError } from '@firebase/util'; import { expect, use } from 'chai'; import * as sinon from 'sinon'; import * as chaiAsPromised from 'chai-as-promised'; import { testAuth, testUser } from '../../../test/helpers/mock_auth'; import { AuthInternal } from '../../model/auth'; import { UserInternal } from '../../model/user'; import { AuthInterop } from './firebase_internal'; use(chaiAsPromised); describe('core/auth/firebase_internal', () => { let auth: AuthInternal; let authInternal: AuthInterop; beforeEach(async () => { auth = await testAuth(); authInternal = new AuthInterop(auth); }); afterEach(() => { sinon.restore(); }); context('getUid', () => { it('returns null if currentUser is undefined', () => { expect(authInternal.getUid()).to.be.null; }); it('returns the uid of the user if set', async () => { const user = testUser(auth, 'uid'); await auth._updateCurrentUser(user); expect(authInternal.getUid()).to.eq('uid'); }); it('errors if Auth is not initialized', () => { delete ((auth as unknown) as Record<string, unknown>)[ '_initializationPromise' ]; expect(() => authInternal.getUid()).to.throw( FirebaseError, 'auth/dependent-sdk-initialized-before-auth' ); }); }); context('getToken', () => { it('returns null if currentUser is undefined', async () => { expect(await authInternal.getToken()).to.be.null; }); it('returns the id token of the current user correctly', async () => { const user = testUser(auth, 'uid'); await auth._updateCurrentUser(user); user.stsTokenManager.accessToken = 'access-token'; user.stsTokenManager.refreshToken = 'refresh-token'; user.stsTokenManager.expirationTime = Date.now() + 1000 * 60 * 60 * 24; expect(await authInternal.getToken()).to.eql({ accessToken: 'access-token' }); }); it('errors if Auth is not initialized', async () => { delete ((auth as unknown) as Record<string, unknown>)[ '_initializationPromise' ]; await expect(authInternal.getToken()).to.be.rejectedWith( FirebaseError, 'auth/dependent-sdk-initialized-before-auth' ); }); }); context('token listeners', () => { let isProactiveRefresh = false; let user: UserInternal; beforeEach(async () => { user = testUser(auth, 'uid', undefined, true); await auth._updateCurrentUser(user); let i = 0; sinon.stub(user.stsTokenManager, 'getToken').callsFake(async () => { i += 1; return `new-access-token-${i}`; }); sinon .stub(user, '_startProactiveRefresh') .callsFake(() => (isProactiveRefresh = true)); sinon .stub(user, '_stopProactiveRefresh') .callsFake(() => (isProactiveRefresh = false)); }); context('addAuthTokenListener', () => { it('gets called with the token, starts proactive refresh', done => { // The listener always fires first time. Ignore that one let firstCall = true; authInternal.addAuthTokenListener(token => { if (firstCall) { firstCall = false; // eslint-disable-next-line @typescript-eslint/no-floating-promises user.getIdToken(true); return; } expect(token).to.eq('access-token'); expect(isProactiveRefresh).to.be.true; done(); }); }); it('gets called on subsequent updates', async () => { let tokenCount = 0; authInternal.addAuthTokenListener(() => { tokenCount++; }); await user.getIdToken(true); await user.getIdToken(true); await user.getIdToken(true); await user.getIdToken(true); expect(tokenCount).to.eq(5); }); it('errors if Auth is not initialized', () => { delete ((auth as unknown) as Record<string, unknown>)[ '_initializationPromise' ]; expect(() => authInternal.addAuthTokenListener(() => {})).to.throw( FirebaseError, 'auth/dependent-sdk-initialized-before-auth' ); }); }); context('removeAuthTokenListener', () => { it('listeners no longer receive token updates', async () => { let tokenCount = 0; function listener(): void { tokenCount++; } authInternal.addAuthTokenListener(listener); await user.getIdToken(true); expect(tokenCount).to.eq(2); authInternal.removeAuthTokenListener(listener); await user.getIdToken(true); await user.getIdToken(true); await user.getIdToken(true); expect(tokenCount).to.eq(2); }); it('toggles proactive refresh when listeners fall to 0', () => { function listenerA(): void {} authInternal.addAuthTokenListener(listenerA); expect(isProactiveRefresh).to.be.true; authInternal.removeAuthTokenListener(listenerA); expect(isProactiveRefresh).to.be.false; }); it('toggles proactive refresh when single listener subbed twice', () => { function listenerA(): void {} authInternal.addAuthTokenListener(listenerA); authInternal.addAuthTokenListener(listenerA); expect(isProactiveRefresh).to.be.true; authInternal.removeAuthTokenListener(listenerA); expect(isProactiveRefresh).to.be.false; }); it('toggles proactive refresh properly multiple listeners', () => { function listenerA(): void {} function listenerB(): void {} authInternal.addAuthTokenListener(listenerA); authInternal.addAuthTokenListener(listenerB); expect(isProactiveRefresh).to.be.true; authInternal.removeAuthTokenListener(listenerA); expect(isProactiveRefresh).to.be.true; authInternal.removeAuthTokenListener(listenerB); expect(isProactiveRefresh).to.be.false; authInternal.addAuthTokenListener(listenerB); expect(isProactiveRefresh).to.be.true; }); it('errors if Auth is not initialized', () => { delete ((auth as unknown) as Record<string, unknown>)[ '_initializationPromise' ]; expect(() => authInternal.removeAuthTokenListener(() => {})).to.throw( FirebaseError, 'auth/dependent-sdk-initialized-before-auth' ); }); }); }); });