fix(docs-infra): notify `ErrorHandler` of `UnrecoverableState` errors (#42941)
With this commit, the `ErrorHandler` is notified of ServiceWorker `UnrecoverableState` errors. The main purpose of this change is gathering info about the occurrence (and frequency) of such errors in Google analytics. PR Close #42941
This commit is contained in:
parent
b1082b7ad8
commit
85e93c3833
|
@ -1,4 +1,4 @@
|
||||||
import { ApplicationRef, Injector } from '@angular/core';
|
import { ApplicationRef, ErrorHandler, Injector } from '@angular/core';
|
||||||
import { discardPeriodicTasks, fakeAsync, tick } from '@angular/core/testing';
|
import { discardPeriodicTasks, fakeAsync, tick } from '@angular/core/testing';
|
||||||
import { SwUpdate } from '@angular/service-worker';
|
import { SwUpdate } from '@angular/service-worker';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
@ -13,6 +13,7 @@ import { SwUpdatesService } from './sw-updates.service';
|
||||||
describe('SwUpdatesService', () => {
|
describe('SwUpdatesService', () => {
|
||||||
let injector: Injector;
|
let injector: Injector;
|
||||||
let appRef: MockApplicationRef;
|
let appRef: MockApplicationRef;
|
||||||
|
let errorHandler: ErrorHandler;
|
||||||
let location: MockLocationService;
|
let location: MockLocationService;
|
||||||
let service: SwUpdatesService;
|
let service: SwUpdatesService;
|
||||||
let swu: MockSwUpdate;
|
let swu: MockSwUpdate;
|
||||||
|
@ -27,13 +28,15 @@ describe('SwUpdatesService', () => {
|
||||||
const setup = (isSwUpdateEnabled: boolean) => {
|
const setup = (isSwUpdateEnabled: boolean) => {
|
||||||
injector = Injector.create({providers: [
|
injector = Injector.create({providers: [
|
||||||
{ provide: ApplicationRef, useClass: MockApplicationRef, deps: [] },
|
{ provide: ApplicationRef, useClass: MockApplicationRef, deps: [] },
|
||||||
|
{ provide: ErrorHandler, useValue: {handleError: jasmine.createSpy('handlerError')} },
|
||||||
{ provide: LocationService, useFactory: () => new MockLocationService(''), deps: [] },
|
{ provide: LocationService, useFactory: () => new MockLocationService(''), deps: [] },
|
||||||
{ provide: Logger, useClass: MockLogger, deps: [] },
|
{ provide: Logger, useClass: MockLogger, deps: [] },
|
||||||
{ provide: SwUpdate, useFactory: () => new MockSwUpdate(isSwUpdateEnabled), deps: [] },
|
{ provide: SwUpdate, useFactory: () => new MockSwUpdate(isSwUpdateEnabled), deps: [] },
|
||||||
{ provide: SwUpdatesService, deps: [ApplicationRef, LocationService, Logger, SwUpdate] }
|
{ provide: SwUpdatesService, deps: [ApplicationRef, ErrorHandler, LocationService, Logger, SwUpdate] }
|
||||||
]});
|
]});
|
||||||
|
|
||||||
appRef = injector.get(ApplicationRef) as unknown as MockApplicationRef;
|
appRef = injector.get(ApplicationRef) as unknown as MockApplicationRef;
|
||||||
|
errorHandler = injector.get(ErrorHandler);
|
||||||
location = injector.get(LocationService) as unknown as MockLocationService;
|
location = injector.get(LocationService) as unknown as MockLocationService;
|
||||||
service = injector.get(SwUpdatesService);
|
service = injector.get(SwUpdatesService);
|
||||||
swu = injector.get(SwUpdate) as unknown as MockSwUpdate;
|
swu = injector.get(SwUpdate) as unknown as MockSwUpdate;
|
||||||
|
@ -129,6 +132,24 @@ describe('SwUpdatesService', () => {
|
||||||
expect(location.reloadPage).toHaveBeenCalledTimes(2);
|
expect(location.reloadPage).toHaveBeenCalledTimes(2);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should notify the `ErrorHandler` when an unrecoverable state has been detected', run(() => {
|
||||||
|
expect(errorHandler.handleError).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
swu.$$unrecoverableSubj.next({reason: 'Something bad happened'});
|
||||||
|
expect(errorHandler.handleError).toHaveBeenCalledBefore(location.reloadPage);
|
||||||
|
expect(errorHandler.handleError)
|
||||||
|
.toHaveBeenCalledWith('Unrecoverable state: Something bad happened');
|
||||||
|
|
||||||
|
(errorHandler.handleError as jasmine.Spy).calls.reset();
|
||||||
|
location.reloadPage.calls.reset();
|
||||||
|
|
||||||
|
swu.$$unrecoverableSubj.next({reason: 'Something worse happened'});
|
||||||
|
expect(errorHandler.handleError).toHaveBeenCalledBefore(location.reloadPage);
|
||||||
|
expect(errorHandler.handleError)
|
||||||
|
.toHaveBeenCalledWith('Unrecoverable state: Something worse happened');
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
describe('when `SwUpdate` is not enabled', () => {
|
describe('when `SwUpdate` is not enabled', () => {
|
||||||
const runDeactivated = (specFn: VoidFunction) => run(specFn, false);
|
const runDeactivated = (specFn: VoidFunction) => run(specFn, false);
|
||||||
|
|
||||||
|
@ -165,6 +186,7 @@ describe('SwUpdatesService', () => {
|
||||||
swu.$$unrecoverableSubj.next({reason: 'Something bad happened'});
|
swu.$$unrecoverableSubj.next({reason: 'Something bad happened'});
|
||||||
swu.$$unrecoverableSubj.next({reason: 'Something worse happened'});
|
swu.$$unrecoverableSubj.next({reason: 'Something worse happened'});
|
||||||
|
|
||||||
|
expect(errorHandler.handleError).not.toHaveBeenCalled();
|
||||||
expect(location.reloadPage).not.toHaveBeenCalled();
|
expect(location.reloadPage).not.toHaveBeenCalled();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -221,12 +243,15 @@ describe('SwUpdatesService', () => {
|
||||||
|
|
||||||
it('should stop requesting page reloads when unrecoverable states are detected', run(() => {
|
it('should stop requesting page reloads when unrecoverable states are detected', run(() => {
|
||||||
swu.$$unrecoverableSubj.next({reason: 'Something bad happened'});
|
swu.$$unrecoverableSubj.next({reason: 'Something bad happened'});
|
||||||
|
expect(errorHandler.handleError).toHaveBeenCalledTimes(1);
|
||||||
expect(location.reloadPage).toHaveBeenCalledTimes(1);
|
expect(location.reloadPage).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
service.ngOnDestroy();
|
service.ngOnDestroy();
|
||||||
|
(errorHandler.handleError as jasmine.Spy).calls.reset();
|
||||||
location.reloadPage.calls.reset();
|
location.reloadPage.calls.reset();
|
||||||
|
|
||||||
swu.$$unrecoverableSubj.next({reason: 'Something worse happened'});
|
swu.$$unrecoverableSubj.next({reason: 'Something worse happened'});
|
||||||
|
expect(errorHandler.handleError).not.toHaveBeenCalled();
|
||||||
expect(location.reloadPage).not.toHaveBeenCalled();
|
expect(location.reloadPage).not.toHaveBeenCalled();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ApplicationRef, Injectable, OnDestroy } from '@angular/core';
|
import { ApplicationRef, ErrorHandler, Injectable, OnDestroy } from '@angular/core';
|
||||||
import { SwUpdate } from '@angular/service-worker';
|
import { SwUpdate } from '@angular/service-worker';
|
||||||
import { concat, interval, Subject } from 'rxjs';
|
import { concat, interval, Subject } from 'rxjs';
|
||||||
import { first, takeUntil, tap } from 'rxjs/operators';
|
import { first, takeUntil, tap } from 'rxjs/operators';
|
||||||
|
@ -21,8 +21,8 @@ export class SwUpdatesService implements OnDestroy {
|
||||||
private onDestroy = new Subject<void>();
|
private onDestroy = new Subject<void>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
appRef: ApplicationRef, location: LocationService, private logger: Logger,
|
appRef: ApplicationRef, errorHandler: ErrorHandler, location: LocationService,
|
||||||
private swu: SwUpdate) {
|
private logger: Logger, private swu: SwUpdate) {
|
||||||
if (!swu.isEnabled) {
|
if (!swu.isEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,11 @@ export class SwUpdatesService implements OnDestroy {
|
||||||
// Request an immediate page reload once an unrecoverable state has been detected.
|
// Request an immediate page reload once an unrecoverable state has been detected.
|
||||||
this.swu.unrecoverable
|
this.swu.unrecoverable
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(evt => this.log(`Unrecoverable state: ${evt.reason}\nReloading...`)),
|
tap(evt => {
|
||||||
|
const errorMsg = `Unrecoverable state: ${evt.reason}`;
|
||||||
|
errorHandler.handleError(errorMsg);
|
||||||
|
this.log(`${errorMsg}\nReloading...`);
|
||||||
|
}),
|
||||||
takeUntil(this.onDestroy),
|
takeUntil(this.onDestroy),
|
||||||
)
|
)
|
||||||
.subscribe(() => location.reloadPage());
|
.subscribe(() => location.reloadPage());
|
||||||
|
|
Loading…
Reference in New Issue