mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
Updates us to version 4.0 of Jasmine and fixes some errors that were the result of us depending upon deprecated APIs. We need to do this both to stay up to date and because it was going to break eventually, because one of the Bazel packages was logging a deprecation warning that version 4.0 was required. There were also some cases where the state of `ngDevMode` had started leaking out between tests. PR Close #45558
325 lines
11 KiB
TypeScript
325 lines
11 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google LLC All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
|
|
import {ApplicationRef, PLATFORM_ID} from '@angular/core';
|
|
import {fakeAsync, flushMicrotasks, TestBed, tick} from '@angular/core/testing';
|
|
import {Subject} from 'rxjs';
|
|
import {filter, take} from 'rxjs/operators';
|
|
|
|
import {ServiceWorkerModule, SwRegistrationOptions} from '../src/module';
|
|
import {SwUpdate} from '../src/update';
|
|
|
|
|
|
describe('ServiceWorkerModule', () => {
|
|
// Skip environments that don't support the minimum APIs needed to run these SW tests.
|
|
if ((typeof navigator === 'undefined') || (typeof navigator.serviceWorker === 'undefined')) {
|
|
// Jasmine will throw if there are no tests.
|
|
it('should pass', () => {});
|
|
return;
|
|
}
|
|
|
|
let swRegisterSpy: jasmine.Spy;
|
|
|
|
const untilStable = () => {
|
|
const appRef: ApplicationRef = TestBed.inject(ApplicationRef);
|
|
return appRef.isStable.pipe(filter(Boolean), take(1)).toPromise();
|
|
};
|
|
|
|
beforeEach(
|
|
() => swRegisterSpy =
|
|
spyOn(navigator.serviceWorker, 'register').and.returnValue(Promise.resolve(null as any)));
|
|
|
|
describe('register()', () => {
|
|
const configTestBed = async (opts: SwRegistrationOptions) => {
|
|
TestBed.configureTestingModule({
|
|
imports: [ServiceWorkerModule.register('sw.js', opts)],
|
|
providers: [{provide: PLATFORM_ID, useValue: 'browser'}],
|
|
});
|
|
|
|
await untilStable();
|
|
};
|
|
|
|
it('sets the registration options', async () => {
|
|
await configTestBed({enabled: true, scope: 'foo'});
|
|
|
|
expect(TestBed.inject(SwRegistrationOptions)).toEqual({enabled: true, scope: 'foo'});
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: 'foo'});
|
|
});
|
|
|
|
it('can disable the SW', async () => {
|
|
await configTestBed({enabled: false});
|
|
|
|
expect(TestBed.inject(SwUpdate).isEnabled).toBe(false);
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('can enable the SW', async () => {
|
|
await configTestBed({enabled: true});
|
|
|
|
expect(TestBed.inject(SwUpdate).isEnabled).toBe(true);
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
});
|
|
|
|
it('defaults to enabling the SW', async () => {
|
|
await configTestBed({});
|
|
|
|
expect(TestBed.inject(SwUpdate).isEnabled).toBe(true);
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
});
|
|
|
|
it('catches and a logs registration errors', async () => {
|
|
const consoleErrorSpy = spyOn(console, 'error');
|
|
swRegisterSpy.and.returnValue(Promise.reject('no reason'));
|
|
|
|
await configTestBed({enabled: true, scope: 'foo'});
|
|
expect(consoleErrorSpy)
|
|
.toHaveBeenCalledWith('Service worker registration failed with:', 'no reason');
|
|
});
|
|
});
|
|
|
|
describe('SwRegistrationOptions', () => {
|
|
const configTestBed =
|
|
(providerOpts: SwRegistrationOptions, staticOpts?: SwRegistrationOptions) => {
|
|
TestBed.configureTestingModule({
|
|
imports: [ServiceWorkerModule.register('sw.js', staticOpts || {scope: 'static'})],
|
|
providers: [
|
|
{provide: PLATFORM_ID, useValue: 'browser'},
|
|
{provide: SwRegistrationOptions, useFactory: () => providerOpts},
|
|
],
|
|
});
|
|
};
|
|
|
|
it('sets the registration options (and overwrites those set via `.register()`', async () => {
|
|
configTestBed({enabled: true, scope: 'provider'});
|
|
await untilStable();
|
|
|
|
expect(TestBed.inject(SwRegistrationOptions)).toEqual({enabled: true, scope: 'provider'});
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: 'provider'});
|
|
});
|
|
|
|
it('can disable the SW', async () => {
|
|
configTestBed({enabled: false}, {enabled: true});
|
|
await untilStable();
|
|
|
|
expect(TestBed.inject(SwUpdate).isEnabled).toBe(false);
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('can enable the SW', async () => {
|
|
configTestBed({enabled: true}, {enabled: false});
|
|
await untilStable();
|
|
|
|
expect(TestBed.inject(SwUpdate).isEnabled).toBe(true);
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
});
|
|
|
|
it('defaults to enabling the SW', async () => {
|
|
configTestBed({}, {enabled: false});
|
|
await untilStable();
|
|
|
|
expect(TestBed.inject(SwUpdate).isEnabled).toBe(true);
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
});
|
|
|
|
describe('registrationStrategy', () => {
|
|
const configTestBedWithMockedStability =
|
|
(strategy?: SwRegistrationOptions['registrationStrategy']) => {
|
|
const isStableSub = new Subject<boolean>();
|
|
|
|
TestBed.configureTestingModule({
|
|
imports: [ServiceWorkerModule.register('sw.js')],
|
|
providers: [
|
|
{provide: ApplicationRef, useValue: {isStable: isStableSub.asObservable()}},
|
|
{provide: PLATFORM_ID, useValue: 'browser'},
|
|
{
|
|
provide: SwRegistrationOptions,
|
|
useFactory: () => ({registrationStrategy: strategy})
|
|
},
|
|
],
|
|
});
|
|
|
|
// Dummy `inject()` call to initialize the test "app".
|
|
TestBed.inject(ApplicationRef);
|
|
|
|
return isStableSub;
|
|
};
|
|
|
|
it('defaults to registering the SW when the app stabilizes (under 30s)', fakeAsync(() => {
|
|
const isStableSub = configTestBedWithMockedStability();
|
|
|
|
isStableSub.next(false);
|
|
isStableSub.next(false);
|
|
|
|
tick();
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
tick(20000);
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
isStableSub.next(true);
|
|
|
|
tick();
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
}));
|
|
|
|
it('defaults to registering the SW after 30s if the app does not stabilize sooner',
|
|
fakeAsync(() => {
|
|
const isStableSub = configTestBedWithMockedStability();
|
|
|
|
tick(29999);
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
tick(1);
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
}));
|
|
|
|
it('registers the SW when the app stabilizes with `registerWhenStable:<timeout>`',
|
|
fakeAsync(() => {
|
|
const isStableSub = configTestBedWithMockedStability('registerWhenStable:1000');
|
|
|
|
isStableSub.next(false);
|
|
isStableSub.next(false);
|
|
|
|
tick();
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
tick(500);
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
isStableSub.next(true);
|
|
|
|
tick();
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
}));
|
|
|
|
it('registers the SW after `timeout` if the app does not stabilize with `registerWhenStable:<timeout>`',
|
|
fakeAsync(() => {
|
|
configTestBedWithMockedStability('registerWhenStable:1000');
|
|
|
|
tick(999);
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
tick(1);
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
}));
|
|
|
|
it('registers the SW asap (asynchronously) before the app stabilizes with `registerWhenStable:0`',
|
|
fakeAsync(() => {
|
|
const isStableSub = configTestBedWithMockedStability('registerWhenStable:0');
|
|
|
|
// Create a microtask.
|
|
Promise.resolve();
|
|
|
|
flushMicrotasks();
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
tick(0);
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
}));
|
|
|
|
it('registers the SW only when the app stabilizes with `registerWhenStable:`',
|
|
fakeAsync(() => {
|
|
const isStableSub = configTestBedWithMockedStability('registerWhenStable:');
|
|
|
|
isStableSub.next(false);
|
|
isStableSub.next(false);
|
|
|
|
tick();
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
tick(60000);
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
isStableSub.next(true);
|
|
|
|
tick();
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
}));
|
|
|
|
it('registers the SW only when the app stabilizes with `registerWhenStable`',
|
|
fakeAsync(() => {
|
|
const isStableSub = configTestBedWithMockedStability('registerWhenStable');
|
|
|
|
isStableSub.next(false);
|
|
isStableSub.next(false);
|
|
|
|
tick();
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
tick(60000);
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
isStableSub.next(true);
|
|
|
|
tick();
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
}));
|
|
|
|
it('registers the SW immediatelly (synchronously) with `registerImmediately`', () => {
|
|
configTestBedWithMockedStability('registerImmediately');
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
});
|
|
|
|
it('registers the SW after the specified delay with `registerWithDelay:<delay>`',
|
|
fakeAsync(() => {
|
|
configTestBedWithMockedStability('registerWithDelay:100000');
|
|
|
|
tick(99999);
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
tick(1);
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
}));
|
|
|
|
it('registers the SW asap (asynchronously) with `registerWithDelay:`', fakeAsync(() => {
|
|
configTestBedWithMockedStability('registerWithDelay:');
|
|
|
|
// Create a microtask.
|
|
Promise.resolve();
|
|
|
|
flushMicrotasks();
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
tick(0);
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
}));
|
|
|
|
it('registers the SW asap (asynchronously) with `registerWithDelay`', fakeAsync(() => {
|
|
configTestBedWithMockedStability('registerWithDelay');
|
|
|
|
// Create a microtask.
|
|
Promise.resolve();
|
|
|
|
flushMicrotasks();
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
tick(0);
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
}));
|
|
|
|
it('registers the SW on first emitted value with observable factory function',
|
|
fakeAsync(() => {
|
|
const registerSub = new Subject<void>();
|
|
const isStableSub = configTestBedWithMockedStability(() => registerSub.asObservable());
|
|
|
|
isStableSub.next(true);
|
|
tick();
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
|
|
registerSub.next();
|
|
expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined});
|
|
}));
|
|
|
|
it('throws an error with unknown strategy', () => {
|
|
expect(() => configTestBedWithMockedStability('registerYesterday'))
|
|
.toThrowError('Unknown ServiceWorker registration strategy: registerYesterday');
|
|
expect(swRegisterSpy).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|
|
});
|