fix(ngUpgrade): make AoT ngUpgrade work with the testability API and resumeBootstrap() (#12910)

This commit is contained in:
Sammy Jelin 2016-11-16 01:04:56 -08:00 committed by Victor Berchet
parent d6ba092a27
commit 42198cd7d5
3 changed files with 60 additions and 4 deletions

View File

@ -13,6 +13,9 @@ export const $INJECTOR = '$injector';
export const $PARSE = '$parse';
export const $ROOT_SCOPE = '$rootScope';
export const $SCOPE = '$scope';
export const $PROVIDE = '$provide';
export const $DELEGATE = '$delegate';
export const $$TESTABILITY = '$$testability';
export const $COMPILE = '$compile';
export const $TEMPLATE_CACHE = '$templateCache';

View File

@ -6,13 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, NgModule, NgZone} from '@angular/core';
import {Injector, NgModule, NgZone, Testability} from '@angular/core';
import * as angular from '../angular_js';
import {controllerKey} from '../util';
import {angular1Providers, setTempInjectorRef} from './angular1_providers';
import {$INJECTOR, INJECTOR_KEY, UPGRADE_MODULE_NAME} from './constants';
import {$$TESTABILITY, $DELEGATE, $INJECTOR, $PROVIDE, $ROOT_SCOPE, INJECTOR_KEY, UPGRADE_MODULE_NAME} from './constants';
/**
@ -40,6 +41,37 @@ export class UpgradeModule {
.value(INJECTOR_KEY, this.injector)
.config([
$PROVIDE, $INJECTOR,
($provide: angular.IProvideService, $injector: angular.IInjectorService) => {
if ($injector.has($$TESTABILITY)) {
$provide.decorator($$TESTABILITY, [
$DELEGATE,
(testabilityDelegate: angular.ITestabilityService) => {
const originalWhenStable: Function = testabilityDelegate.whenStable;
const injector = this.injector;
// Cannot use arrow function below because we need to grab the context
const newWhenStable = function(callback: Function) {
const whenStableContext: any = this;
originalWhenStable.call(this, function() {
const ng2Testability: Testability = injector.get(Testability);
if (ng2Testability.isStable()) {
callback.apply(this, arguments);
} else {
ng2Testability.whenStable(
newWhenStable.bind(whenStableContext, callback));
}
});
};
testabilityDelegate.whenStable = newWhenStable;
return testabilityDelegate;
}
]);
}
}
])
.run([
$INJECTOR,
($injector: angular.IInjectorService) => {
@ -59,7 +91,22 @@ export class UpgradeModule {
}
]);
// Make sure resumeBootstrap() only exists if the current bootstrap is deferred
const windowAngular = (window as any /** TODO #???? */)['angular'];
windowAngular.resumeBootstrap = undefined;
// Bootstrap the angular 1 application inside our zone
this.ngZone.run(() => { angular.bootstrap(element, [upgradeModule.name], config); });
// Patch resumeBootstrap() to run inside the ngZone
if (windowAngular.resumeBootstrap) {
const originalResumeBootstrap: () => void = windowAngular.resumeBootstrap;
const ngZone = this.ngZone;
windowAngular.resumeBootstrap = function() {
let args = arguments;
windowAngular.resumeBootstrap = originalResumeBootstrap;
ngZone.run(() => { windowAngular.resumeBootstrap.apply(this, args); });
};
}
}
}

View File

@ -7,6 +7,7 @@
*/
import {NgModule, Testability, destroyPlatform} from '@angular/core';
import {NgZone} from '@angular/core/src/zone/ng_zone';
import {fakeAsync, tick} from '@angular/core/testing';
import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
@ -28,7 +29,11 @@ export function main() {
it('should handle deferred bootstrap', fakeAsync(() => {
let applicationRunning = false;
const ng1Module = angular.module('ng1', []).run(() => { applicationRunning = true; });
let stayedInTheZone: boolean;
const ng1Module = angular.module('ng1', []).run(() => {
applicationRunning = true;
stayedInTheZone = NgZone.isInAngularZone();
});
const element = html('<div></div>');
window.name = 'NG_DEFER_BOOTSTRAP!' + window.name;
@ -40,6 +45,7 @@ export function main() {
expect(applicationRunning).toEqual(false);
tick(100);
expect(applicationRunning).toEqual(true);
expect(stayedInTheZone).toEqual(true);
}));
it('should wait for ng2 testability', fakeAsync(() => {