UNPKG

voluptasmollitia

Version:
245 lines (199 loc) 7.92 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 { expect, use } from 'chai'; import * as sinon from 'sinon'; import * as sinonChai from 'sinon-chai'; import { testAuth } from '../../../test/helpers/mock_auth'; import { AuthEvent, AuthEventConsumer, AuthEventError, AuthEventType } from '../../model/popup_redirect'; import { AuthErrorCode } from '../errors'; import { AuthEventManager } from './auth_event_manager'; use(sinonChai); describe('core/auth/auth_event_manager', () => { let manager: AuthEventManager; function makeConsumer( filter: AuthEventType | AuthEventType[] ): sinon.SinonStubbedInstance<AuthEventConsumer> { const stub = sinon.stub({ filter: Array.isArray(filter) ? filter : [filter], onAuthEvent: () => {}, onError: () => {}, eventId: null }); return stub; } function makeEvent(type: AuthEventType, eventId = 'event'): AuthEvent { return { type, eventId } as AuthEvent; } beforeEach(async () => { manager = new AuthEventManager(await testAuth()); }); it('multiple consumers may be registered for one event type', () => { const a = makeConsumer(AuthEventType.LINK_VIA_POPUP); const b = makeConsumer(AuthEventType.LINK_VIA_POPUP); const evt = makeEvent(AuthEventType.LINK_VIA_POPUP); manager.registerConsumer(a); manager.registerConsumer(b); manager.onEvent(evt); expect(a.onAuthEvent).to.have.been.calledWith(evt); expect(b.onAuthEvent).to.have.been.calledWith(evt); }); it('can unregister listeners', () => { const a = makeConsumer(AuthEventType.LINK_VIA_POPUP); const b = makeConsumer(AuthEventType.LINK_VIA_POPUP); const evt = makeEvent(AuthEventType.LINK_VIA_POPUP); manager.registerConsumer(a); manager.registerConsumer(b); manager.unregisterConsumer(a); manager.onEvent(evt); expect(a.onAuthEvent).not.to.have.been.calledWith(evt); expect(b.onAuthEvent).to.have.been.calledWith(evt); }); it('does not call the consumer if filter does not match', () => { const consumer = makeConsumer(AuthEventType.REAUTH_VIA_POPUP); manager.registerConsumer(consumer); manager.onEvent(makeEvent(AuthEventType.REAUTH_VIA_REDIRECT)); expect(consumer.onAuthEvent).not.to.have.been.called; }); it('does not call through if eventId does not match', () => { const consumer = makeConsumer(AuthEventType.REAUTH_VIA_POPUP); consumer.eventId = 'not-event-id'; manager.registerConsumer(consumer); manager.onEvent(makeEvent(AuthEventType.REAUTH_VIA_POPUP, 'event-id')); expect(consumer.onAuthEvent).not.to.have.been.called; }); it('does call through if eventId is null', () => { const consumer = makeConsumer(AuthEventType.REAUTH_VIA_POPUP); consumer.eventId = null; manager.registerConsumer(consumer); manager.onEvent(makeEvent(AuthEventType.REAUTH_VIA_POPUP, 'event-id')); expect(consumer.onAuthEvent).to.have.been.called; }); it('converts errors into FirebaseError if the type matches', () => { const consumer = makeConsumer(AuthEventType.REAUTH_VIA_POPUP); manager.registerConsumer(consumer); const event = makeEvent(AuthEventType.REAUTH_VIA_POPUP); event.error = { code: `auth/${AuthErrorCode.INVALID_APP_CREDENTIAL}`, message: 'foo', name: 'name' }; manager.onEvent(event); const error = consumer.onError.getCall(0).args[0]; expect(error.code).to.eq(`auth/${AuthErrorCode.INVALID_APP_CREDENTIAL}`); }); it('converts random errors into FirebaseError with internal error', () => { const consumer = makeConsumer(AuthEventType.REAUTH_VIA_POPUP); manager.registerConsumer(consumer); const event = makeEvent(AuthEventType.REAUTH_VIA_POPUP); event.error = { message: 'foo', name: 'name' } as AuthEventError; manager.onEvent(event); const error = consumer.onError.getCall(0).args[0]; expect(error.code).to.eq(`auth/${AuthErrorCode.INTERNAL_ERROR}`); }); context('redirect consumers', () => { let consumer: AuthEventConsumer; beforeEach(() => { consumer = makeConsumer([ AuthEventType.SIGN_IN_VIA_REDIRECT, AuthEventType.LINK_VIA_REDIRECT, AuthEventType.REAUTH_VIA_REDIRECT, AuthEventType.UNKNOWN ]); }); it('redirect events are queued until the future', () => { const event = makeEvent(AuthEventType.REAUTH_VIA_REDIRECT); expect(manager.onEvent(event)).to.be.true; manager.registerConsumer(consumer); expect(consumer.onAuthEvent).to.have.been.calledWith(event); }); it('queued redirects only work for the first new consumer', () => { const event = makeEvent(AuthEventType.REAUTH_VIA_REDIRECT); expect(manager.onEvent(event)).to.be.true; manager.registerConsumer(consumer); expect(consumer.onAuthEvent).to.have.been.calledWith(event); const consumerB = makeConsumer(AuthEventType.REAUTH_VIA_REDIRECT); manager.registerConsumer(consumerB); expect(consumerB.onAuthEvent).not.to.have.been.called; }); it('does not queue a redirect event if it was handled immediately', () => { const event = makeEvent(AuthEventType.REAUTH_VIA_REDIRECT); manager.registerConsumer(consumer); expect(manager.onEvent(event)).to.be.true; expect(consumer.onAuthEvent).to.have.been.calledWith(event); const consumerB = makeConsumer(AuthEventType.REAUTH_VIA_REDIRECT); manager.registerConsumer(consumerB); expect(consumerB.onAuthEvent).not.to.have.been.called; }); it('queues unknown events', () => { const event = makeEvent(AuthEventType.UNKNOWN); event.error = { code: 'auth/no-auth-event' } as AuthEventError; expect(manager.onEvent(event)).to.be.true; manager.registerConsumer(consumer); expect(consumer.onAuthEvent).to.have.been.calledWith(event); }); }); context('caching', () => { let clock: sinon.SinonFakeTimers; beforeEach(() => { clock = sinon.useFakeTimers(); }); afterEach(() => { sinon.restore(); }); it('only runs the event once for the consumer', () => { const consumer = makeConsumer(AuthEventType.LINK_VIA_POPUP); const evt = makeEvent(AuthEventType.LINK_VIA_POPUP); manager.registerConsumer(consumer); manager.onEvent(evt); manager.onEvent(evt); expect(consumer.onAuthEvent).to.have.been.calledOnce; }); it('clears the cache after ten minutes', () => { const consumer = makeConsumer(AuthEventType.LINK_VIA_POPUP); const evt = makeEvent(AuthEventType.LINK_VIA_POPUP); manager.registerConsumer(consumer); manager.onEvent(evt); clock.tick(11 * 60 * 1000); manager.onEvent(evt); expect(consumer.onAuthEvent).to.have.been.calledTwice; }); it('also caches stored redirects', () => { const consumer = makeConsumer([ AuthEventType.SIGN_IN_VIA_REDIRECT, AuthEventType.LINK_VIA_REDIRECT, AuthEventType.REAUTH_VIA_REDIRECT, AuthEventType.UNKNOWN ]); const event = makeEvent(AuthEventType.REAUTH_VIA_REDIRECT); manager.onEvent(event); manager.registerConsumer(consumer); manager.onEvent(event); expect(consumer.onAuthEvent).to.have.been.calledOnce; }); }); });