UNPKG

quodolores

Version:

Monorepo for the Firebase JavaScript SDK

200 lines (179 loc) 6.3 kB
/** * @license * Copyright 2019 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 { createNetworkRequestEntry } from '../resources/network_request'; import { Trace } from '../resources/trace'; import '../../test/setup'; 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< [PerformanceNavigationTiming[], PerformanceEntry[], (number | undefined)?], void >; let clock: SinonFakeTimers; setupApi(self); 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(); expect(apiGetInstanceSpy).not.to.be.called; }); it('sets up network request collection', () => { getIidStub.returns(MOCK_ID); setupOobResources(); clock.tick(1); expect(apiGetInstanceSpy).to.be.called; expect(getEntriesByTypeStub).to.be.calledWith('resource'); expect(setupObserverStub).to.be.calledWithExactly( 'resource', createNetworkRequestEntry ); }); it('sets up page load trace collection', () => { getIidStub.returns(MOCK_ID); setupOobResources(); 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( [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(); clock.tick(1); expect(api.onFirstInputDelay).to.be.called; expect(createOobTraceStub).not.to.be.called; clock.tick(5000); expect(createOobTraceStub).to.be.calledWithExactly( [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(); clock.tick(1); firstInputDelayCallback(FIRST_INPUT_DELAY); expect(createOobTraceStub).to.be.calledWithExactly( [NAVIGATION_PERFORMANCE_ENTRY], [PAINT_PERFORMANCE_ENTRY], FIRST_INPUT_DELAY ); }); it('sets up user timing traces', () => { getIidStub.returns(MOCK_ID); setupOobResources(); clock.tick(1); expect(apiGetInstanceSpy).to.be.called; expect(getEntriesByTypeStub).to.be.calledWith('measure'); expect(setupObserverStub).to.be.calledWith('measure'); }); }); });