parent
d272f96e23
commit
430f367c2f
|
@ -97,16 +97,33 @@ export interface IControllerService {
|
||||||
|
|
||||||
export interface IInjectorService { get(key: string): any; }
|
export interface IInjectorService { get(key: string): any; }
|
||||||
|
|
||||||
|
export interface ITestabilityService {
|
||||||
|
findBindings(element: Element, expression: string, opt_exactMatch?: boolean): Element[];
|
||||||
|
findModels(element: Element, expression: string, opt_exactMatch?: boolean): Element[];
|
||||||
|
getLocation(): string;
|
||||||
|
setLocation(url: string): void;
|
||||||
|
whenStable(callback: Function): void;
|
||||||
|
}
|
||||||
|
|
||||||
function noNg() {
|
function noNg() {
|
||||||
throw new Error('AngularJS v1.x is not loaded!');
|
throw new Error('AngularJS v1.x is not loaded!');
|
||||||
}
|
}
|
||||||
|
|
||||||
var angular: {
|
var angular:
|
||||||
bootstrap: (e: Element, modules: string[], config: IAngularBootstrapConfig) => void,
|
{
|
||||||
module: (prefix: string, dependencies?: string[]) => IModule,
|
bootstrap: (e: Element, modules: string[], config: IAngularBootstrapConfig) => void,
|
||||||
element: (e: Element) => IAugmentedJQuery,
|
module: (prefix: string, dependencies?: string[]) => IModule,
|
||||||
version: {major: number}
|
element: (e: Element) => IAugmentedJQuery,
|
||||||
} = <any>{bootstrap: noNg, module: noNg, element: noNg, version: noNg};
|
version: {major: number}, resumeBootstrap?: () => void,
|
||||||
|
getTestability: (e: Element) => ITestabilityService
|
||||||
|
} = <any>{
|
||||||
|
bootstrap: noNg,
|
||||||
|
module: noNg,
|
||||||
|
element: noNg,
|
||||||
|
version: noNg,
|
||||||
|
resumeBootstrap: noNg,
|
||||||
|
getTestability: noNg
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -121,3 +138,5 @@ export var bootstrap = angular.bootstrap;
|
||||||
export var module = angular.module;
|
export var module = angular.module;
|
||||||
export var element = angular.element;
|
export var element = angular.element;
|
||||||
export var version = angular.version;
|
export var version = angular.version;
|
||||||
|
export var resumeBootstrap = angular.resumeBootstrap;
|
||||||
|
export var getTestability = angular.getTestability;
|
||||||
|
|
|
@ -12,4 +12,5 @@ export const NG1_HTTP_BACKEND = '$httpBackend';
|
||||||
export const NG1_INJECTOR = '$injector';
|
export const NG1_INJECTOR = '$injector';
|
||||||
export const NG1_PARSE = '$parse';
|
export const NG1_PARSE = '$parse';
|
||||||
export const NG1_TEMPLATE_CACHE = '$templateCache';
|
export const NG1_TEMPLATE_CACHE = '$templateCache';
|
||||||
|
export const NG1_TESTABILITY = '$$testability';
|
||||||
export const REQUIRE_INJECTOR = '^' + NG2_INJECTOR;
|
export const REQUIRE_INJECTOR = '^' + NG2_INJECTOR;
|
||||||
|
|
|
@ -10,8 +10,10 @@ import {
|
||||||
HostViewFactoryRef,
|
HostViewFactoryRef,
|
||||||
Provider,
|
Provider,
|
||||||
Type,
|
Type,
|
||||||
|
Testability,
|
||||||
APPLICATION_COMMON_PROVIDERS
|
APPLICATION_COMMON_PROVIDERS
|
||||||
} from 'angular2/core';
|
} from 'angular2/core';
|
||||||
|
import {global} from 'angular2/src/facade/lang';
|
||||||
import {ObservableWrapper} from 'angular2/src/facade/async';
|
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||||
import {BROWSER_PROVIDERS, BROWSER_APP_PROVIDERS} from 'angular2/platform/browser';
|
import {BROWSER_PROVIDERS, BROWSER_APP_PROVIDERS} from 'angular2/platform/browser';
|
||||||
|
|
||||||
|
@ -23,6 +25,7 @@ import {
|
||||||
NG1_PARSE,
|
NG1_PARSE,
|
||||||
NG1_ROOT_SCOPE,
|
NG1_ROOT_SCOPE,
|
||||||
NG1_SCOPE,
|
NG1_SCOPE,
|
||||||
|
NG1_TESTABILITY,
|
||||||
NG2_APP_VIEW_MANAGER,
|
NG2_APP_VIEW_MANAGER,
|
||||||
NG2_COMPILER,
|
NG2_COMPILER,
|
||||||
NG2_INJECTOR,
|
NG2_INJECTOR,
|
||||||
|
@ -309,6 +312,7 @@ export class UpgradeAdapter {
|
||||||
var rootScope: angular.IRootScopeService;
|
var rootScope: angular.IRootScopeService;
|
||||||
var hostViewFactoryRefMap: HostViewFactoryRefMap = {};
|
var hostViewFactoryRefMap: HostViewFactoryRefMap = {};
|
||||||
var ng1Module = angular.module(this.idPrefix, modules);
|
var ng1Module = angular.module(this.idPrefix, modules);
|
||||||
|
var ng1BootstrapPromise: Promise<any> = null;
|
||||||
var ng1compilePromise: Promise<any> = null;
|
var ng1compilePromise: Promise<any> = null;
|
||||||
ng1Module.value(NG2_INJECTOR, injector)
|
ng1Module.value(NG2_INJECTOR, injector)
|
||||||
.value(NG2_ZONE, ngZone)
|
.value(NG2_ZONE, ngZone)
|
||||||
|
@ -331,23 +335,68 @@ export class UpgradeAdapter {
|
||||||
return rootScope = rootScopeDelegate;
|
return rootScope = rootScopeDelegate;
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
provide.decorator(NG1_TESTABILITY, [
|
||||||
])
|
'$delegate',
|
||||||
.run([
|
function(testabilityDelegate: angular.ITestabilityService) {
|
||||||
'$injector',
|
var ng2Testability: Testability = injector.get(Testability);
|
||||||
'$rootScope',
|
|
||||||
(injector: angular.IInjectorService, rootScope: angular.IRootScopeService) => {
|
var origonalWhenStable: Function = testabilityDelegate.whenStable;
|
||||||
ng1Injector = injector;
|
var newWhenStable = (callback: Function): void => {
|
||||||
ObservableWrapper.subscribe(ngZone.onMicrotaskEmpty,
|
var whenStableContext: any = this;
|
||||||
(_) => ngZone.runOutsideAngular(() => rootScope.$apply()));
|
origonalWhenStable.call(this, function() {
|
||||||
ng1compilePromise =
|
if (ng2Testability.isStable()) {
|
||||||
UpgradeNg1ComponentAdapterBuilder.resolve(this.downgradedComponents, injector);
|
callback.apply(this, arguments);
|
||||||
|
} else {
|
||||||
|
ng2Testability.whenStable(newWhenStable.bind(whenStableContext, callback));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
testabilityDelegate.whenStable = newWhenStable;
|
||||||
|
return testabilityDelegate;
|
||||||
|
}
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
ng1compilePromise = new Promise((resolve, reject) => {
|
||||||
|
ng1Module.run([
|
||||||
|
'$injector',
|
||||||
|
'$rootScope',
|
||||||
|
(injector: angular.IInjectorService, rootScope: angular.IRootScopeService) => {
|
||||||
|
ng1Injector = injector;
|
||||||
|
ObservableWrapper.subscribe(ngZone.onMicrotaskEmpty,
|
||||||
|
(_) => ngZone.runOutsideAngular(() => rootScope.$apply()));
|
||||||
|
UpgradeNg1ComponentAdapterBuilder.resolve(this.downgradedComponents, injector)
|
||||||
|
.then(resolve, reject);
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make sure resumeBootstrap() only exists if the current bootstrap is deferred
|
||||||
|
var windowAngular = (<any>global).angular;
|
||||||
|
windowAngular.resumeBootstrap = undefined;
|
||||||
|
|
||||||
angular.element(element).data(controllerKey(NG2_INJECTOR), injector);
|
angular.element(element).data(controllerKey(NG2_INJECTOR), injector);
|
||||||
ngZone.run(() => { angular.bootstrap(element, [this.idPrefix], config); });
|
ngZone.run(() => { angular.bootstrap(element, [this.idPrefix], config); });
|
||||||
Promise.all([this.compileNg2Components(compiler, hostViewFactoryRefMap), ng1compilePromise])
|
ng1BootstrapPromise = new Promise((resolve, reject) => {
|
||||||
|
if (windowAngular.resumeBootstrap) {
|
||||||
|
var originalResumeBootstrap: () => void = windowAngular.resumeBootstrap;
|
||||||
|
windowAngular.resumeBootstrap = function() {
|
||||||
|
windowAngular.resumeBootstrap = originalResumeBootstrap;
|
||||||
|
windowAngular.resumeBootstrap.apply(this, arguments);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.all([
|
||||||
|
this.compileNg2Components(compiler, hostViewFactoryRefMap),
|
||||||
|
ng1BootstrapPromise,
|
||||||
|
ng1compilePromise
|
||||||
|
])
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ngZone.run(() => {
|
ngZone.run(() => {
|
||||||
if (rootScopePrototype) {
|
if (rootScopePrototype) {
|
||||||
|
|
|
@ -12,7 +12,16 @@ import {
|
||||||
} from 'angular2/testing_internal';
|
} from 'angular2/testing_internal';
|
||||||
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
|
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
|
||||||
|
|
||||||
import {Component, Class, Inject, EventEmitter, ApplicationRef, provide} from 'angular2/core';
|
import {global} from 'angular2/src/facade/lang';
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
Class,
|
||||||
|
Inject,
|
||||||
|
EventEmitter,
|
||||||
|
ApplicationRef,
|
||||||
|
provide,
|
||||||
|
Testability,
|
||||||
|
} from 'angular2/core';
|
||||||
import {UpgradeAdapter} from 'angular2/upgrade';
|
import {UpgradeAdapter} from 'angular2/upgrade';
|
||||||
import * as angular from 'angular2/src/upgrade/angular_js';
|
import * as angular from 'angular2/src/upgrade/angular_js';
|
||||||
|
|
||||||
|
@ -559,6 +568,52 @@ export function main() {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('testability', () => {
|
||||||
|
it('should handle deferred bootstrap', inject([AsyncTestCompleter], (async) => {
|
||||||
|
var adapter: UpgradeAdapter = new UpgradeAdapter();
|
||||||
|
var ng1Module = angular.module('ng1', []);
|
||||||
|
var bootstrapResumed: boolean = false;
|
||||||
|
|
||||||
|
var element = html("<div></div>");
|
||||||
|
window.name = 'NG_DEFER_BOOTSTRAP!' + window.name;
|
||||||
|
|
||||||
|
adapter.bootstrap(element, ['ng1'])
|
||||||
|
.ready((ref) => {
|
||||||
|
expect(bootstrapResumed).toEqual(true);
|
||||||
|
ref.dispose();
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
bootstrapResumed = true;
|
||||||
|
(<any>global).angular.resumeBootstrap();
|
||||||
|
}, 100);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should wait for ng2 testability', inject([AsyncTestCompleter], (async) => {
|
||||||
|
var adapter: UpgradeAdapter = new UpgradeAdapter();
|
||||||
|
var ng1Module = angular.module('ng1', []);
|
||||||
|
var element = html("<div></div>");
|
||||||
|
adapter.bootstrap(element, ['ng1'])
|
||||||
|
.ready((ref) => {
|
||||||
|
var ng2Testability: Testability = ref.ng2Injector.get(Testability);
|
||||||
|
ng2Testability.increasePendingRequestCount();
|
||||||
|
var ng2Stable = false;
|
||||||
|
|
||||||
|
angular.getTestability(element).whenStable(function() {
|
||||||
|
expect(ng2Stable).toEqual(true);
|
||||||
|
ref.dispose();
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
ng2Stable = true;
|
||||||
|
ng2Testability.decreasePendingRequestCount();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
describe('examples', () => {
|
describe('examples', () => {
|
||||||
it('should verify UpgradeAdapter example', inject([AsyncTestCompleter], (async) => {
|
it('should verify UpgradeAdapter example', inject([AsyncTestCompleter], (async) => {
|
||||||
var adapter = new UpgradeAdapter();
|
var adapter = new UpgradeAdapter();
|
||||||
|
@ -594,7 +649,6 @@ export function main() {
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue