UNPKG

quodolores

Version:

Monorepo for the Firebase JavaScript SDK

227 lines (203 loc) 7.19 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 { spy, stub, SinonSpy, SinonStub, useFakeTimers, SinonFakeTimers } from 'sinon'; import { expect } from 'chai'; import { Api, setupApi, EntryType } from './api_service'; import * as iidService from './iid_service'; import { setupOobResources } from './oob_resources_service'; import { Trace } from '../resources/trace'; import '../../test/setup'; import { PerformanceController } from '../controllers/perf'; import { FirebaseApp } from '@firebase/app-exp'; import { FirebaseInstallations } from '@firebase/installations-types'; describe('Firebase Performance > oob_resources_service', () => { const MOCK_ID = 'idasdfsffe'; const NAVIGATION_PERFORMANCE_ENTRY: PerformanceNavigationTiming = { connectEnd: 2.9499998781830072, connectStart: 2.9499998781830072, decodedBodySize: 1519, domComplete: 186.48499995470047, domContentLoadedEventEnd: 64.0499999281019, domContentLoadedEventStart: 62.440000008791685, domInteractive: 62.42000008933246, domainLookupEnd: 2.9499998781830072, domainLookupStart: 2.9499998781830072, duration: 187.7349999267608, encodedBodySize: 732, entryType: 'navigation', fetchStart: 2.9499998781830072, initiatorType: 'navigation', loadEventEnd: 187.7349999267608, loadEventStart: 187.72999988868833, name: 'https://test.firebase.com/', nextHopProtocol: 'h2', redirectCount: 0, redirectEnd: 0, redirectStart: 0, requestStart: 5.034999921917915, responseEnd: 9.305000072345138, responseStart: 8.940000087022781, secureConnectionStart: 0, startTime: 0, transferSize: 1259, type: 'reload', unloadEventEnd: 14.870000071823597, unloadEventStart: 14.870000071823597, workerStart: 0, toJSON: () => {} }; const PAINT_PERFORMANCE_ENTRY: PerformanceEntry = { duration: 0, entryType: 'paint', name: 'first-contentful-paint', startTime: 122.18499998562038, toJSON: () => {} }; let getIidStub: SinonStub<[], string | undefined>; let apiGetInstanceSpy: SinonSpy<[], Api>; let getEntriesByTypeStub: SinonStub<[EntryType], PerformanceEntry[]>; let setupObserverStub: SinonStub< [EntryType, (entry: PerformanceEntry) => void], void >; let createOobTraceStub: SinonStub< [ PerformanceController, PerformanceNavigationTiming[], PerformanceEntry[], (number | undefined)? ], void >; let clock: SinonFakeTimers; setupApi(self); const fakeFirebaseConfig = { apiKey: 'api-key', authDomain: 'project-id.firebaseapp.com', databaseURL: 'https://project-id.firebaseio.com', projectId: 'project-id', storageBucket: 'project-id.appspot.com', messagingSenderId: 'sender-id', appId: '1:111:web:a1234' }; const fakeFirebaseApp = ({ options: fakeFirebaseConfig } as unknown) as FirebaseApp; const fakeInstallations = ({} as unknown) as FirebaseInstallations; const performanceController = new PerformanceController( fakeFirebaseApp, fakeInstallations ); beforeEach(() => { getIidStub = stub(iidService, 'getIid'); apiGetInstanceSpy = spy(Api, 'getInstance'); clock = useFakeTimers(); getEntriesByTypeStub = stub(Api.prototype, 'getEntriesByType').callsFake( entry => { if (entry === 'navigation') { return [NAVIGATION_PERFORMANCE_ENTRY]; } return [PAINT_PERFORMANCE_ENTRY]; } ); setupObserverStub = stub(Api.prototype, 'setupObserver'); createOobTraceStub = stub(Trace, 'createOobTrace'); }); afterEach(() => { clock.restore(); }); describe('setupOobResources', () => { it('does not start if there is no iid', () => { getIidStub.returns(undefined); setupOobResources(performanceController); expect(apiGetInstanceSpy).not.to.be.called; }); it('sets up network request collection', () => { getIidStub.returns(MOCK_ID); setupOobResources(performanceController); clock.tick(1); expect(apiGetInstanceSpy).to.be.called; expect(getEntriesByTypeStub).to.be.calledWith('resource'); expect(setupObserverStub).to.be.calledWith('resource'); }); it('sets up page load trace collection', () => { getIidStub.returns(MOCK_ID); setupOobResources(performanceController); clock.tick(1); expect(apiGetInstanceSpy).to.be.called; expect(getEntriesByTypeStub).to.be.calledWith('navigation'); expect(getEntriesByTypeStub).to.be.calledWith('paint'); expect(createOobTraceStub).to.be.calledWithExactly( performanceController, [NAVIGATION_PERFORMANCE_ENTRY], [PAINT_PERFORMANCE_ENTRY] ); }); it('waits for first input delay if polyfill is available', () => { getIidStub.returns(MOCK_ID); const api = Api.getInstance(); //@ts-ignore Assignment to read-only property. api.onFirstInputDelay = stub(); setupOobResources(performanceController); clock.tick(1); expect(api.onFirstInputDelay).to.be.called; expect(createOobTraceStub).not.to.be.called; clock.tick(5000); expect(createOobTraceStub).to.be.calledWithExactly( performanceController, [NAVIGATION_PERFORMANCE_ENTRY], [PAINT_PERFORMANCE_ENTRY] ); }); it('logs first input delay if polyfill is available and callback is called', () => { getIidStub.returns(MOCK_ID); const api = Api.getInstance(); const FIRST_INPUT_DELAY = 123; // Underscore is to avoid compiler comlaining about variable being declared but not used. type FirstInputDelayCallback = (firstInputDelay: number) => void; let firstInputDelayCallback: FirstInputDelayCallback = (): void => {}; //@ts-ignore Assignment to read-only property. api.onFirstInputDelay = (cb: FirstInputDelayCallback) => { firstInputDelayCallback = cb; }; setupOobResources(performanceController); clock.tick(1); firstInputDelayCallback(FIRST_INPUT_DELAY); expect(createOobTraceStub).to.be.calledWithExactly( performanceController, [NAVIGATION_PERFORMANCE_ENTRY], [PAINT_PERFORMANCE_ENTRY], FIRST_INPUT_DELAY ); }); it('sets up user timing traces', () => { getIidStub.returns(MOCK_ID); setupOobResources(performanceController); clock.tick(1); expect(apiGetInstanceSpy).to.be.called; expect(getEntriesByTypeStub).to.be.calledWith('measure'); expect(setupObserverStub).to.be.calledWith('measure'); }); }); });