Add testability hook to downgraded component so that protractor can wait for asynchronous call to complete. Add unregisterApplication() and unregisterAllApplications() to testability registry for cleaning up testability and unit test.
324 lines
11 KiB
TypeScript
324 lines
11 KiB
TypeScript
/**
|
|
* @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 {EventEmitter} from '@angular/core';
|
|
import {Injectable} from '@angular/core/src/di';
|
|
import {Testability, TestabilityRegistry} from '@angular/core/src/testability/testability';
|
|
import {NgZone} from '@angular/core/src/zone/ng_zone';
|
|
import {AsyncTestCompleter, SpyObject, beforeEach, describe, expect, inject, it} from '@angular/core/testing/src/testing_internal';
|
|
|
|
import {scheduleMicroTask} from '../../src/util';
|
|
|
|
|
|
|
|
// Schedules a microtasks (using a resolved promise .then())
|
|
function microTask(fn: Function): void {
|
|
scheduleMicroTask(() => {
|
|
// We do double dispatch so that we can wait for scheduleMicrotask in the Testability when
|
|
// NgZone becomes stable.
|
|
scheduleMicroTask(fn);
|
|
});
|
|
}
|
|
|
|
@Injectable()
|
|
class MockNgZone extends NgZone {
|
|
/** @internal */
|
|
onUnstable: EventEmitter<any>;
|
|
|
|
/** @internal */
|
|
onStable: EventEmitter<any>;
|
|
|
|
constructor() {
|
|
super({enableLongStackTrace: false});
|
|
this.onUnstable = new EventEmitter(false);
|
|
this.onStable = new EventEmitter(false);
|
|
}
|
|
|
|
unstable(): void { this.onUnstable.emit(null); }
|
|
|
|
stable(): void { this.onStable.emit(null); }
|
|
}
|
|
|
|
export function main() {
|
|
describe('Testability', () => {
|
|
let testability: Testability;
|
|
let execute: any;
|
|
let execute2: any;
|
|
let ngZone: MockNgZone;
|
|
|
|
beforeEach(() => {
|
|
ngZone = new MockNgZone();
|
|
testability = new Testability(ngZone);
|
|
execute = new SpyObject().spy('execute');
|
|
execute2 = new SpyObject().spy('execute');
|
|
});
|
|
|
|
describe('Pending count logic', () => {
|
|
it('should start with a pending count of 0',
|
|
() => { expect(testability.getPendingRequestCount()).toEqual(0); });
|
|
|
|
it('should fire whenstable callbacks if pending count is 0',
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
|
testability.whenStable(execute);
|
|
microTask(() => {
|
|
expect(execute).toHaveBeenCalled();
|
|
async.done();
|
|
});
|
|
}));
|
|
|
|
it('should not fire whenstable callbacks synchronously if pending count is 0', () => {
|
|
testability.whenStable(execute);
|
|
expect(execute).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not call whenstable callbacks when there are pending counts',
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
|
testability.increasePendingRequestCount();
|
|
testability.increasePendingRequestCount();
|
|
testability.whenStable(execute);
|
|
|
|
microTask(() => {
|
|
expect(execute).not.toHaveBeenCalled();
|
|
testability.decreasePendingRequestCount();
|
|
|
|
microTask(() => {
|
|
expect(execute).not.toHaveBeenCalled();
|
|
async.done();
|
|
});
|
|
});
|
|
}));
|
|
|
|
it('should fire whenstable callbacks when pending drops to 0',
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
|
testability.increasePendingRequestCount();
|
|
testability.whenStable(execute);
|
|
|
|
microTask(() => {
|
|
expect(execute).not.toHaveBeenCalled();
|
|
testability.decreasePendingRequestCount();
|
|
|
|
microTask(() => {
|
|
expect(execute).toHaveBeenCalled();
|
|
async.done();
|
|
});
|
|
});
|
|
}));
|
|
|
|
it('should not fire whenstable callbacks synchronously when pending drops to 0', () => {
|
|
testability.increasePendingRequestCount();
|
|
testability.whenStable(execute);
|
|
testability.decreasePendingRequestCount();
|
|
|
|
expect(execute).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should fire whenstable callbacks with didWork if pending count is 0',
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
|
testability.whenStable(execute);
|
|
microTask(() => {
|
|
expect(execute).toHaveBeenCalledWith(false);
|
|
async.done();
|
|
});
|
|
}));
|
|
|
|
it('should fire whenstable callbacks with didWork when pending drops to 0',
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
|
testability.increasePendingRequestCount();
|
|
testability.whenStable(execute);
|
|
|
|
microTask(() => {
|
|
testability.decreasePendingRequestCount();
|
|
|
|
microTask(() => {
|
|
expect(execute).toHaveBeenCalledWith(true);
|
|
testability.whenStable(execute2);
|
|
|
|
microTask(() => {
|
|
expect(execute2).toHaveBeenCalledWith(false);
|
|
async.done();
|
|
});
|
|
});
|
|
});
|
|
}));
|
|
});
|
|
|
|
describe('NgZone callback logic', () => {
|
|
it('should fire whenstable callback if event is already finished',
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
|
ngZone.unstable();
|
|
ngZone.stable();
|
|
testability.whenStable(execute);
|
|
|
|
microTask(() => {
|
|
expect(execute).toHaveBeenCalled();
|
|
async.done();
|
|
});
|
|
}));
|
|
|
|
it('should not fire whenstable callbacks synchronously if event is already finished', () => {
|
|
ngZone.unstable();
|
|
ngZone.stable();
|
|
testability.whenStable(execute);
|
|
|
|
expect(execute).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should fire whenstable callback when event finishes',
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
|
ngZone.unstable();
|
|
testability.whenStable(execute);
|
|
|
|
microTask(() => {
|
|
expect(execute).not.toHaveBeenCalled();
|
|
ngZone.stable();
|
|
|
|
microTask(() => {
|
|
expect(execute).toHaveBeenCalled();
|
|
async.done();
|
|
});
|
|
});
|
|
}));
|
|
|
|
it('should not fire whenstable callbacks synchronously when event finishes', () => {
|
|
ngZone.unstable();
|
|
testability.whenStable(execute);
|
|
ngZone.stable();
|
|
|
|
expect(execute).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not fire whenstable callback when event did not finish',
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
|
ngZone.unstable();
|
|
testability.increasePendingRequestCount();
|
|
testability.whenStable(execute);
|
|
|
|
microTask(() => {
|
|
expect(execute).not.toHaveBeenCalled();
|
|
testability.decreasePendingRequestCount();
|
|
|
|
microTask(() => {
|
|
expect(execute).not.toHaveBeenCalled();
|
|
ngZone.stable();
|
|
|
|
microTask(() => {
|
|
expect(execute).toHaveBeenCalled();
|
|
async.done();
|
|
});
|
|
});
|
|
});
|
|
}));
|
|
|
|
it('should not fire whenstable callback when there are pending counts',
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
|
ngZone.unstable();
|
|
testability.increasePendingRequestCount();
|
|
testability.increasePendingRequestCount();
|
|
testability.whenStable(execute);
|
|
|
|
microTask(() => {
|
|
expect(execute).not.toHaveBeenCalled();
|
|
ngZone.stable();
|
|
|
|
microTask(() => {
|
|
expect(execute).not.toHaveBeenCalled();
|
|
testability.decreasePendingRequestCount();
|
|
|
|
microTask(() => {
|
|
expect(execute).not.toHaveBeenCalled();
|
|
testability.decreasePendingRequestCount();
|
|
|
|
microTask(() => {
|
|
expect(execute).toHaveBeenCalled();
|
|
async.done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}));
|
|
|
|
it('should fire whenstable callback with didWork if event is already finished',
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
|
ngZone.unstable();
|
|
ngZone.stable();
|
|
testability.whenStable(execute);
|
|
|
|
microTask(() => {
|
|
expect(execute).toHaveBeenCalledWith(true);
|
|
testability.whenStable(execute2);
|
|
|
|
microTask(() => {
|
|
expect(execute2).toHaveBeenCalledWith(false);
|
|
async.done();
|
|
});
|
|
});
|
|
}));
|
|
|
|
it('should fire whenstable callback with didwork when event finishes',
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
|
ngZone.unstable();
|
|
testability.whenStable(execute);
|
|
|
|
microTask(() => {
|
|
ngZone.stable();
|
|
|
|
microTask(() => {
|
|
expect(execute).toHaveBeenCalledWith(true);
|
|
testability.whenStable(execute2);
|
|
|
|
microTask(() => {
|
|
expect(execute2).toHaveBeenCalledWith(false);
|
|
async.done();
|
|
});
|
|
});
|
|
});
|
|
}));
|
|
});
|
|
});
|
|
|
|
describe('TestabilityRegistry', () => {
|
|
let testability1: Testability;
|
|
let testability2: Testability;
|
|
let resgitry: TestabilityRegistry;
|
|
let ngZone: MockNgZone;
|
|
|
|
beforeEach(() => {
|
|
ngZone = new MockNgZone();
|
|
testability1 = new Testability(ngZone);
|
|
testability2 = new Testability(ngZone);
|
|
resgitry = new TestabilityRegistry();
|
|
});
|
|
describe('unregister testability', () => {
|
|
it('should remove the testability when unregistering an existing testability', () => {
|
|
resgitry.registerApplication('testability1', testability1);
|
|
resgitry.registerApplication('testability2', testability2);
|
|
resgitry.unregisterApplication('testability2');
|
|
expect(resgitry.getAllTestabilities().length).toEqual(1);
|
|
expect(resgitry.getTestability('testability1')).toEqual(testability1);
|
|
});
|
|
|
|
it('should remain the same when unregistering a non-existing testability', () => {
|
|
expect(resgitry.getAllTestabilities().length).toEqual(0);
|
|
resgitry.registerApplication('testability1', testability1);
|
|
resgitry.registerApplication('testability2', testability2);
|
|
resgitry.unregisterApplication('testability3');
|
|
expect(resgitry.getAllTestabilities().length).toEqual(2);
|
|
expect(resgitry.getTestability('testability1')).toEqual(testability1);
|
|
expect(resgitry.getTestability('testability2')).toEqual(testability2);
|
|
});
|
|
|
|
it('should remove all the testability when unregistering all testabilities', () => {
|
|
resgitry.registerApplication('testability1', testability1);
|
|
resgitry.registerApplication('testability2', testability2);
|
|
resgitry.unregisterAllApplications();
|
|
expect(resgitry.getAllTestabilities().length).toEqual(0);
|
|
});
|
|
});
|
|
});
|
|
}
|