2016-08-02 07:38:14 -07:00
|
|
|
/**
|
|
|
|
* @license
|
2020-05-19 12:08:49 -07:00
|
|
|
* Copyright Google LLC All Rights Reserved.
|
2016-08-02 07:38:14 -07:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
2018-11-05 20:31:54 -08:00
|
|
|
import {APP_INITIALIZER, ApplicationInitStatus} from '@angular/core/src/application_init';
|
2019-10-17 17:48:35 +08:00
|
|
|
import {Observable, Subscriber} from 'rxjs';
|
2020-04-13 16:40:21 -07:00
|
|
|
|
2020-08-01 04:43:18 +09:00
|
|
|
import {inject, TestBed, waitForAsync} from '../testing';
|
2016-08-02 07:38:14 -07:00
|
|
|
|
2017-12-15 16:28:41 -08:00
|
|
|
{
|
2016-08-02 07:54:14 -07:00
|
|
|
describe('ApplicationInitStatus', () => {
|
2016-08-02 07:38:14 -07:00
|
|
|
describe('no initializers', () => {
|
|
|
|
it('should return true for `done`',
|
2020-08-01 04:43:18 +09:00
|
|
|
waitForAsync(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => {
|
2017-12-06 06:56:49 -08:00
|
|
|
(status as any).runInitializers();
|
2016-08-02 07:54:14 -07:00
|
|
|
expect(status.done).toBe(true);
|
2016-08-19 12:10:53 -07:00
|
|
|
})));
|
2016-08-02 07:38:14 -07:00
|
|
|
|
|
|
|
it('should return a promise that resolves immediately for `donePromise`',
|
2020-08-01 04:43:18 +09:00
|
|
|
waitForAsync(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => {
|
2017-12-06 06:56:49 -08:00
|
|
|
(status as any).runInitializers();
|
2020-04-13 16:40:21 -07:00
|
|
|
status.donePromise.then(() => {
|
|
|
|
expect(status.done).toBe(true);
|
|
|
|
});
|
2016-08-02 07:38:14 -07:00
|
|
|
})));
|
|
|
|
});
|
|
|
|
|
2019-10-17 17:48:35 +08:00
|
|
|
describe('with async promise initializers', () => {
|
2016-08-02 15:53:34 -07:00
|
|
|
let resolve: (result: any) => void;
|
2019-10-17 17:48:35 +08:00
|
|
|
let reject: (reason?: any) => void;
|
2016-08-02 15:53:34 -07:00
|
|
|
let promise: Promise<any>;
|
2019-10-17 17:48:35 +08:00
|
|
|
let initFnInvoked = false;
|
2016-08-02 07:38:14 -07:00
|
|
|
beforeEach(() => {
|
2019-10-17 17:48:35 +08:00
|
|
|
promise = new Promise((res, rej) => {
|
2020-04-13 16:40:21 -07:00
|
|
|
resolve = res;
|
2019-10-17 17:48:35 +08:00
|
|
|
reject = rej;
|
2020-04-13 16:40:21 -07:00
|
|
|
});
|
2017-05-16 15:14:55 -07:00
|
|
|
TestBed.configureTestingModule({
|
|
|
|
providers: [
|
|
|
|
{provide: APP_INITIALIZER, multi: true, useValue: () => promise},
|
|
|
|
]
|
|
|
|
});
|
2016-08-02 07:38:14 -07:00
|
|
|
});
|
|
|
|
|
2019-10-17 17:48:35 +08:00
|
|
|
it('should update the status once all async promise initializers are done',
|
2020-08-01 04:43:18 +09:00
|
|
|
waitForAsync(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => {
|
2019-10-17 17:48:35 +08:00
|
|
|
// Accessing internal `runInitializers` function of the `ApplicationInitStatus` class
|
|
|
|
// instance for testing purposes to invoke initializer functions.
|
2017-12-06 06:56:49 -08:00
|
|
|
(status as any).runInitializers();
|
2017-05-16 15:14:55 -07:00
|
|
|
|
2016-08-02 07:38:14 -07:00
|
|
|
setTimeout(() => {
|
2019-10-17 17:48:35 +08:00
|
|
|
initFnInvoked = true;
|
2016-08-02 15:53:34 -07:00
|
|
|
resolve(null);
|
2016-08-02 07:38:14 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
expect(status.done).toBe(false);
|
|
|
|
status.donePromise.then(() => {
|
|
|
|
expect(status.done).toBe(true);
|
2019-10-17 17:48:35 +08:00
|
|
|
expect(initFnInvoked).toBe(true);
|
2016-08-02 07:38:14 -07:00
|
|
|
});
|
|
|
|
})));
|
2019-10-17 17:48:35 +08:00
|
|
|
|
|
|
|
it('should handle a case when promise is rejected',
|
|
|
|
waitForAsync(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => {
|
|
|
|
// Accessing internal `runInitializers` function of the `ApplicationInitStatus` class
|
|
|
|
// instance for testing purposes to invoke initializer functions.
|
|
|
|
(status as any).runInitializers();
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
initFnInvoked = true;
|
|
|
|
reject();
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(status.done).toBe(false);
|
|
|
|
status.donePromise
|
|
|
|
.then(
|
|
|
|
() => fail('`donePromise.then` should not be invoked when promise is rejected'))
|
|
|
|
.catch(() => {
|
|
|
|
expect(status.done).toBe(false);
|
|
|
|
expect(initFnInvoked).toBe(true);
|
|
|
|
});
|
|
|
|
})));
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('with app initializers represented using observables', () => {
|
|
|
|
let subscriber: Subscriber<any>;
|
|
|
|
let observable: Observable<any>;
|
|
|
|
let initFnInvoked = false;
|
|
|
|
beforeEach(() => {
|
|
|
|
observable = new Observable((res) => {
|
|
|
|
subscriber = res;
|
|
|
|
});
|
|
|
|
TestBed.configureTestingModule({
|
|
|
|
providers: [
|
|
|
|
{provide: APP_INITIALIZER, multi: true, useValue: () => observable},
|
|
|
|
]
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should update the status once all async observable initializers are completed',
|
|
|
|
waitForAsync(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => {
|
|
|
|
// Accessing internal `runInitializers` function of the `ApplicationInitStatus` class
|
|
|
|
// instance for testing purposes to invoke initializer functions.
|
|
|
|
(status as any).runInitializers();
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
initFnInvoked = true;
|
|
|
|
subscriber.complete();
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(status.done).toBe(false);
|
|
|
|
status.donePromise.then(() => {
|
|
|
|
expect(status.done).toBe(true);
|
|
|
|
expect(initFnInvoked).toBe(true);
|
|
|
|
});
|
|
|
|
})));
|
|
|
|
|
|
|
|
it('should update the status once all async observable initializers nexted and completed',
|
|
|
|
waitForAsync(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => {
|
|
|
|
// Accessing internal `runInitializers` function of the `ApplicationInitStatus` class
|
|
|
|
// instance for testing purposes to invoke initializer functions.
|
|
|
|
(status as any).runInitializers();
|
|
|
|
|
|
|
|
subscriber.next('one');
|
|
|
|
subscriber.next('two');
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
initFnInvoked = true;
|
|
|
|
subscriber.complete();
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(status.done).toBe(false);
|
|
|
|
status.donePromise.then(() => {
|
|
|
|
expect(status.done).toBe(true);
|
|
|
|
expect(initFnInvoked).toBe(true);
|
|
|
|
});
|
|
|
|
})));
|
|
|
|
|
|
|
|
it('should update the status if all async observable initializers are completed before runInitializers',
|
|
|
|
waitForAsync(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => {
|
|
|
|
subscriber.complete();
|
|
|
|
// Accessing internal `runInitializers` function of the `ApplicationInitStatus` class
|
|
|
|
// instance for testing purposes to invoke initializer functions.
|
|
|
|
(status as any).runInitializers();
|
|
|
|
|
|
|
|
expect(status.done).toBe(false);
|
|
|
|
|
|
|
|
status.donePromise.then(() => {
|
|
|
|
expect(status.done).toBe(true);
|
|
|
|
});
|
|
|
|
})));
|
|
|
|
|
|
|
|
it('should handle a case when observable emits an error',
|
|
|
|
waitForAsync(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => {
|
|
|
|
// Accessing internal `runInitializers` function of the `ApplicationInitStatus` class
|
|
|
|
// instance for testing purposes to invoke initializer functions.
|
|
|
|
(status as any).runInitializers();
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
initFnInvoked = true;
|
|
|
|
subscriber.error();
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(status.done).toBe(false);
|
|
|
|
status.donePromise
|
|
|
|
.then(
|
|
|
|
() => fail(
|
|
|
|
'`donePromise.then` should not be invoked when observable emits an error'))
|
|
|
|
.catch(() => {
|
|
|
|
expect(status.done).toBe(false);
|
|
|
|
expect(initFnInvoked).toBe(true);
|
|
|
|
});
|
|
|
|
})));
|
2016-08-02 07:38:14 -07:00
|
|
|
});
|
|
|
|
});
|
2016-08-02 15:53:34 -07:00
|
|
|
}
|