| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. 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'; | 
					
						
							| 
									
										
										
										
											2018-11-07 22:46:22 +02:00
										 |  |  | import {TestBed, fakeAsync, flushMicrotasks, tick} from '@angular/core/testing'; | 
					
						
							|  |  |  | import {Subject} from 'rxjs'; | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  | 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')) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   let swRegisterSpy: jasmine.Spy; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-07 22:46:22 +02:00
										 |  |  |   const untilStable = () => { | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |     const appRef: ApplicationRef = TestBed.inject(ApplicationRef); | 
					
						
							| 
									
										
										
										
											2018-11-07 22:46:22 +02:00
										 |  |  |     return appRef.isStable.pipe(filter(Boolean), take(1)).toPromise(); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-04 16:54:24 +02:00
										 |  |  |   beforeEach( | 
					
						
							|  |  |  |       () => swRegisterSpy = | 
					
						
							|  |  |  |           spyOn(navigator.serviceWorker, 'register').and.returnValue(Promise.resolve())); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   describe('register()', () => { | 
					
						
							|  |  |  |     const configTestBed = async(opts: SwRegistrationOptions) => { | 
					
						
							|  |  |  |       TestBed.configureTestingModule({ | 
					
						
							|  |  |  |         imports: [ServiceWorkerModule.register('sw.js', opts)], | 
					
						
							|  |  |  |         providers: [{provide: PLATFORM_ID, useValue: 'browser'}], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-07 22:46:22 +02:00
										 |  |  |       await untilStable(); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('sets the registration options', async() => { | 
					
						
							|  |  |  |       await configTestBed({enabled: true, scope: 'foo'}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |       expect(TestBed.inject(SwRegistrationOptions)).toEqual({enabled: true, scope: 'foo'}); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  |       expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: 'foo'}); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('can disable the SW', async() => { | 
					
						
							|  |  |  |       await configTestBed({enabled: false}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |       expect(TestBed.inject(SwUpdate).isEnabled).toBe(false); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  |       expect(swRegisterSpy).not.toHaveBeenCalled(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('can enable the SW', async() => { | 
					
						
							|  |  |  |       await configTestBed({enabled: true}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |       expect(TestBed.inject(SwUpdate).isEnabled).toBe(true); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  |       expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined}); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('defaults to enabling the SW', async() => { | 
					
						
							|  |  |  |       await configTestBed({}); | 
					
						
							| 
									
										
										
										
											2018-11-07 22:46:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |       expect(TestBed.inject(SwUpdate).isEnabled).toBe(true); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  |       expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined}); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-06-04 16:54:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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'); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('SwRegistrationOptions', () => { | 
					
						
							|  |  |  |     const configTestBed = | 
					
						
							| 
									
										
										
										
											2018-11-07 22:46:22 +02:00
										 |  |  |         (providerOpts: SwRegistrationOptions, staticOpts?: SwRegistrationOptions) => { | 
					
						
							|  |  |  |           TestBed.configureTestingModule({ | 
					
						
							|  |  |  |             imports: [ServiceWorkerModule.register('sw.js', staticOpts || {scope: 'static'})], | 
					
						
							|  |  |  |             providers: [ | 
					
						
							|  |  |  |               {provide: PLATFORM_ID, useValue: 'browser'}, | 
					
						
							|  |  |  |               {provide: SwRegistrationOptions, useFactory: () => providerOpts}, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }; | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('sets the registration options (and overwrites those set via `.register()`', async() => { | 
					
						
							| 
									
										
										
										
											2018-11-07 22:46:22 +02:00
										 |  |  |       configTestBed({enabled: true, scope: 'provider'}); | 
					
						
							|  |  |  |       await untilStable(); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |       expect(TestBed.inject(SwRegistrationOptions)).toEqual({enabled: true, scope: 'provider'}); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  |       expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: 'provider'}); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('can disable the SW', async() => { | 
					
						
							| 
									
										
										
										
											2018-11-07 22:46:22 +02:00
										 |  |  |       configTestBed({enabled: false}, {enabled: true}); | 
					
						
							|  |  |  |       await untilStable(); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |       expect(TestBed.inject(SwUpdate).isEnabled).toBe(false); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  |       expect(swRegisterSpy).not.toHaveBeenCalled(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('can enable the SW', async() => { | 
					
						
							| 
									
										
										
										
											2018-11-07 22:46:22 +02:00
										 |  |  |       configTestBed({enabled: true}, {enabled: false}); | 
					
						
							|  |  |  |       await untilStable(); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |       expect(TestBed.inject(SwUpdate).isEnabled).toBe(true); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  |       expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined}); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('defaults to enabling the SW', async() => { | 
					
						
							| 
									
										
										
										
											2018-11-07 22:46:22 +02:00
										 |  |  |       configTestBed({}, {enabled: false}); | 
					
						
							|  |  |  |       await untilStable(); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |       expect(TestBed.inject(SwUpdate).isEnabled).toBe(true); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  |       expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined}); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-11-07 22:46:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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 `get()` call to initialize the test "app".
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |             TestBed.inject(ApplicationRef); | 
					
						
							| 
									
										
										
										
											2018-11-07 22:46:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return isStableSub; | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('defaults to registering the SW when the app stabilizes', fakeAsync(() => { | 
					
						
							|  |  |  |            const isStableSub = configTestBedWithMockedStability(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            isStableSub.next(false); | 
					
						
							|  |  |  |            isStableSub.next(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            expect(swRegisterSpy).not.toHaveBeenCalled(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            isStableSub.next(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            expect(swRegisterSpy).toHaveBeenCalledWith('sw.js', {scope: undefined}); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('registers the SW when the app stabilizes with `registerWhenStable`', fakeAsync(() => { | 
					
						
							|  |  |  |            const isStableSub = configTestBedWithMockedStability('registerWhenStable'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            isStableSub.next(false); | 
					
						
							|  |  |  |            isStableSub.next(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            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(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-04-25 16:51:08 +03:00
										 |  |  |   }); | 
					
						
							|  |  |  | }); |