feat(testability): hook zone into whenstable api with async support

closes(#428)
This commit is contained in:
Hank Duan
2015-07-24 12:46:12 -07:00
parent 19d8b221b4
commit a8b75c3d41
9 changed files with 511 additions and 54 deletions

View File

@ -3,6 +3,8 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
import {Map, MapWrapper, List, ListWrapper} from 'angular2/src/facade/collection';
import {StringWrapper, isBlank, BaseException} from 'angular2/src/facade/lang';
import * as getTestabilityModule from './get_testability';
import {NgZone} from '../zone/ng_zone';
import {PromiseWrapper} from 'angular2/src/facade/async';
/**
@ -12,40 +14,57 @@ import * as getTestabilityModule from './get_testability';
*/
@Injectable()
export class Testability {
_pendingCount: number;
_callbacks: List<Function>;
_pendingCount: number = 0;
_callbacks: List<Function> = [];
_isAngularEventPending: boolean = false;
constructor() {
this._pendingCount = 0;
this._callbacks = [];
constructor(public _ngZone: NgZone) { this._watchAngularEvents(_ngZone); }
_watchAngularEvents(_ngZone: NgZone): void {
_ngZone.overrideOnTurnStart(() => { this._isAngularEventPending = true; });
_ngZone.overrideOnEventDone(() => {
this._isAngularEventPending = false;
this._runCallbacksIfReady();
}, true);
}
increaseCount(delta: number = 1): number {
this._pendingCount += delta;
if (this._pendingCount < 0) {
throw new BaseException('pending async requests below zero');
} else if (this._pendingCount == 0) {
this._runCallbacks();
}
increasePendingRequestCount(): number {
this._pendingCount += 1;
return this._pendingCount;
}
_runCallbacks() {
while (this._callbacks.length !== 0) {
ListWrapper.removeLast(this._callbacks)();
decreasePendingRequestCount(): number {
this._pendingCount -= 1;
if (this._pendingCount < 0) {
throw new BaseException('pending async requests below zero');
}
this._runCallbacksIfReady();
return this._pendingCount;
}
whenStable(callback: Function) {
_runCallbacksIfReady(): void {
if (this._pendingCount != 0 || this._isAngularEventPending) {
return; // Not ready
}
// Schedules the call backs in a new frame so that it is always async.
PromiseWrapper.resolve(null).then((_) => {
while (this._callbacks.length !== 0) {
(this._callbacks.pop())();
}
});
}
whenStable(callback: Function): void {
this._callbacks.push(callback);
if (this._pendingCount === 0) {
this._runCallbacks();
}
// TODO(juliemr) - hook into the zone api.
this._runCallbacksIfReady();
}
getPendingCount(): number { return this._pendingCount; }
getPendingRequestCount(): number { return this._pendingCount; }
// This only accounts for ngZone, and not pending counts. Use `whenStable` to
// check for stability.
isAngularEventPending(): boolean { return this._isAngularEventPending; }
findBindings(using: any, binding: string, exactMatch: boolean): List<any> {
// TODO(juliemr): implement.
@ -55,13 +74,9 @@ export class Testability {
@Injectable()
export class TestabilityRegistry {
_applications: Map<any, Testability>;
_applications: Map<any, Testability> = new Map();
constructor() {
this._applications = new Map();
getTestabilityModule.GetTestability.addToWindow(this);
}
constructor() { getTestabilityModule.GetTestability.addToWindow(this); }
registerApplication(token: any, testability: Testability) {
this._applications.set(token, testability);