test(ivy): re-enable passing upgrade tests (#28088)

PR Close #28088
This commit is contained in:
Kara Erickson 2019-01-11 13:42:30 -08:00 committed by Andrew Kushnir
parent b73d6781da
commit fe4d3a1619

View File

@ -159,180 +159,177 @@ withEachNg1Version(() => {
}); });
})); }));
fixmeIvy('FW-714: ng1 projected content is not being rendered') it('should support nesting components from different downgraded modules (via projection)',
.it('should support nesting components from different downgraded modules (via projection)', async(() => {
async(() => { @Component({
@Component({ selector: 'ng2A',
selector: 'ng2A', template: 'ng2A(<ng-content></ng-content>)',
template: 'ng2A(<ng-content></ng-content>)', })
}) class Ng2ComponentA {
class Ng2ComponentA { }
}
@Component({ @Component({
selector: 'ng2B', selector: 'ng2B',
template: 'ng2B', template: 'ng2B',
}) })
class Ng2ComponentB { class Ng2ComponentB {
} }
@NgModule({ @NgModule({
declarations: [Ng2ComponentA], declarations: [Ng2ComponentA],
entryComponents: [Ng2ComponentA], entryComponents: [Ng2ComponentA],
imports: [BrowserModule], imports: [BrowserModule],
}) })
class Ng2ModuleA { class Ng2ModuleA {
ngDoBootstrap() {} ngDoBootstrap() {}
} }
@NgModule({ @NgModule({
declarations: [Ng2ComponentB], declarations: [Ng2ComponentB],
entryComponents: [Ng2ComponentB], entryComponents: [Ng2ComponentB],
imports: [BrowserModule], imports: [BrowserModule],
}) })
class Ng2ModuleB { class Ng2ModuleB {
ngDoBootstrap() {} ngDoBootstrap() {}
} }
const doDowngradeModule = (module: Type<any>) => { const doDowngradeModule = (module: Type<any>) => {
const bootstrapFn = (extraProviders: StaticProvider[]) => { const bootstrapFn = (extraProviders: StaticProvider[]) => {
const platformRef = getPlatform() || platformBrowserDynamic(extraProviders); const platformRef = getPlatform() || platformBrowserDynamic(extraProviders);
return platformRef.bootstrapModule(module); return platformRef.bootstrapModule(module);
}; };
return downgradeModule(bootstrapFn); return downgradeModule(bootstrapFn);
}; };
const downModA = doDowngradeModule(Ng2ModuleA); const downModA = doDowngradeModule(Ng2ModuleA);
const downModB = doDowngradeModule(Ng2ModuleB); const downModB = doDowngradeModule(Ng2ModuleB);
const ng1Module = angular.module('ng1', [downModA, downModB]) const ng1Module = angular.module('ng1', [downModA, downModB])
.directive('ng2A', downgradeComponent({ .directive('ng2A', downgradeComponent({
component: Ng2ComponentA, component: Ng2ComponentA,
downgradedModule: downModA, propagateDigest, downgradedModule: downModA, propagateDigest,
})) }))
.directive('ng2B', downgradeComponent({ .directive('ng2B', downgradeComponent({
component: Ng2ComponentB, component: Ng2ComponentB,
downgradedModule: downModB, propagateDigest, downgradedModule: downModB, propagateDigest,
})); }));
const element = html('<ng2-a><ng2-b ng-if="showB"></ng2-b></ng2-a>'); const element = html('<ng2-a><ng2-b ng-if="showB"></ng2-b></ng2-a>');
const $injector = angular.bootstrap(element, [ng1Module.name]); const $injector = angular.bootstrap(element, [ng1Module.name]);
const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService; const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService;
// Wait for module A to be bootstrapped. // Wait for module A to be bootstrapped.
setTimeout(() => { setTimeout(() => {
expect(element.textContent).toBe('ng2A()'); expect(element.textContent).toBe('ng2A()');
$rootScope.$apply('showB = true'); $rootScope.$apply('showB = true');
// Wait for module B to be bootstrapped. // Wait for module B to be bootstrapped.
setTimeout(() => expect(element.textContent).toBe('ng2A(ng2B)')); setTimeout(() => expect(element.textContent).toBe('ng2A(ng2B)'));
}); });
})); }));
fixmeIvy('FW-714: ng1 projected content is not being rendered') it('should support manually setting up a root module for all downgraded modules',
.it('should support manually setting up a root module for all downgraded modules', fakeAsync(() => {
fakeAsync(() => { @Injectable({providedIn: 'root'})
@Injectable({providedIn: 'root'}) class CounterService {
class CounterService { private static counter = 0;
private static counter = 0; value = ++CounterService.counter;
value = ++CounterService.counter; }
}
@Component({ @Component({
selector: 'ng2A', selector: 'ng2A',
template: 'ng2A(Counter:{{ counter.value }} | <ng-content></ng-content>)', template: 'ng2A(Counter:{{ counter.value }} | <ng-content></ng-content>)',
}) })
class Ng2ComponentA { class Ng2ComponentA {
constructor(public counter: CounterService) {} constructor(public counter: CounterService) {}
} }
@Component({ @Component({
selector: 'ng2B', selector: 'ng2B',
template: 'Counter:{{ counter.value }}', template: 'Counter:{{ counter.value }}',
}) })
class Ng2ComponentB { class Ng2ComponentB {
constructor(public counter: CounterService) {} constructor(public counter: CounterService) {}
} }
@NgModule({ @NgModule({
declarations: [Ng2ComponentA], declarations: [Ng2ComponentA],
entryComponents: [Ng2ComponentA], entryComponents: [Ng2ComponentA],
}) })
class Ng2ModuleA { class Ng2ModuleA {
} }
@NgModule({ @NgModule({
declarations: [Ng2ComponentB], declarations: [Ng2ComponentB],
entryComponents: [Ng2ComponentB], entryComponents: [Ng2ComponentB],
}) })
class Ng2ModuleB { class Ng2ModuleB {
} }
// "Empty" module that will serve as root for all downgraded modules, // "Empty" module that will serve as root for all downgraded modules,
// ensuring there will only be one instance for all injectables provided in "root". // ensuring there will only be one instance for all injectables provided in "root".
@NgModule({ @NgModule({
imports: [BrowserModule], imports: [BrowserModule],
}) })
class Ng2ModuleRoot { class Ng2ModuleRoot {
ngDoBootstrap() {} ngDoBootstrap() {}
} }
let rootInjectorPromise: Promise<Injector>|null = null; let rootInjectorPromise: Promise<Injector>|null = null;
const doDowngradeModule = (module: Type<any>) => { const doDowngradeModule = (module: Type<any>) => {
const bootstrapFn = (extraProviders: StaticProvider[]) => { const bootstrapFn = (extraProviders: StaticProvider[]) => {
if (!rootInjectorPromise) { if (!rootInjectorPromise) {
rootInjectorPromise = platformBrowserDynamic(extraProviders) rootInjectorPromise = platformBrowserDynamic(extraProviders)
.bootstrapModule(Ng2ModuleRoot) .bootstrapModule(Ng2ModuleRoot)
.then(ref => ref.injector); .then(ref => ref.injector);
} }
return rootInjectorPromise.then(rootInjector => { return rootInjectorPromise.then(rootInjector => {
const compiler = rootInjector.get(Compiler); const compiler = rootInjector.get(Compiler);
const moduleFactory = compiler.compileModuleSync(module); const moduleFactory = compiler.compileModuleSync(module);
return moduleFactory.create(rootInjector); return moduleFactory.create(rootInjector);
}); });
}; };
return downgradeModule(bootstrapFn); return downgradeModule(bootstrapFn);
}; };
const downModA = doDowngradeModule(Ng2ModuleA); const downModA = doDowngradeModule(Ng2ModuleA);
const downModB = doDowngradeModule(Ng2ModuleB); const downModB = doDowngradeModule(Ng2ModuleB);
const ng1Module = angular.module('ng1', [downModA, downModB]) const ng1Module = angular.module('ng1', [downModA, downModB])
.directive('ng2A', downgradeComponent({ .directive('ng2A', downgradeComponent({
component: Ng2ComponentA, component: Ng2ComponentA,
downgradedModule: downModA, propagateDigest, downgradedModule: downModA, propagateDigest,
})) }))
.directive('ng2B', downgradeComponent({ .directive('ng2B', downgradeComponent({
component: Ng2ComponentB, component: Ng2ComponentB,
downgradedModule: downModB, propagateDigest, downgradedModule: downModB, propagateDigest,
})); }));
const element = html(` const element = html(`
<ng2-a><ng2-b ng-if="showB1"></ng2-b></ng2-a> <ng2-a><ng2-b ng-if="showB1"></ng2-b></ng2-a>
<ng2-b ng-if="showB2"></ng2-b> <ng2-b ng-if="showB2"></ng2-b>
`); `);
const $injector = angular.bootstrap(element, [ng1Module.name]); const $injector = angular.bootstrap(element, [ng1Module.name]);
const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService; const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService;
tick(); // Wait for module A to be bootstrapped. tick(); // Wait for module A to be bootstrapped.
expect(multiTrim(element.textContent)).toBe('ng2A(Counter:1 | )'); expect(multiTrim(element.textContent)).toBe('ng2A(Counter:1 | )');
// Nested component B should use the same `CounterService` instance. // Nested component B should use the same `CounterService` instance.
$rootScope.$apply('showB1 = true'); $rootScope.$apply('showB1 = true');
tick(); // Wait for module B to be bootstrapped. tick(); // Wait for module B to be bootstrapped.
expect(multiTrim(element.children[0].textContent)) expect(multiTrim(element.children[0].textContent)).toBe('ng2A(Counter:1 | Counter:1)');
.toBe('ng2A(Counter:1 | Counter:1)');
// Top-level component B should use the same `CounterService` instance. // Top-level component B should use the same `CounterService` instance.
$rootScope.$apply('showB2 = true'); $rootScope.$apply('showB2 = true');
tick(); tick();
expect(multiTrim(element.children[1].textContent)).toBe('Counter:1'); expect(multiTrim(element.children[1].textContent)).toBe('Counter:1');
})); }));
fixmeIvy('FW-714: ng1 projected content is not being rendered') fixmeIvy('FW-873: projected component injector hierarchy not wired up correctly')
.it('should correctly traverse the injector tree of downgraded components', async(() => { .it('should correctly traverse the injector tree of downgraded components', async(() => {
@Component({ @Component({
selector: 'ng2A', selector: 'ng2A',
@ -420,7 +417,7 @@ withEachNg1Version(() => {
}); });
})); }));
fixmeIvy('FW-714: ng1 projected content is not being rendered') fixmeIvy('FW-873: projected component injector hierarchy not wired up correctly')
.it('should correctly traverse the injector tree of downgraded components (from different modules)', .it('should correctly traverse the injector tree of downgraded components (from different modules)',
async(() => { async(() => {
@Component({ @Component({
@ -783,68 +780,67 @@ withEachNg1Version(() => {
}); });
})); }));
fixmeIvy('FW-714: ng1 projected content is not being rendered') it('should create and destroy nested, asynchronously instantiated components inside the Angular zone',
.it('should create and destroy nested, asynchronously instantiated components inside the Angular zone', async(() => {
async(() => { let createdInTheZone = false;
let createdInTheZone = false; let destroyedInTheZone = false;
let destroyedInTheZone = false;
@Component({ @Component({
selector: 'test', selector: 'test',
template: '', template: '',
}) })
class TestComponent implements OnDestroy { class TestComponent implements OnDestroy {
constructor() { createdInTheZone = NgZone.isInAngularZone(); } constructor() { createdInTheZone = NgZone.isInAngularZone(); }
ngOnDestroy() { destroyedInTheZone = NgZone.isInAngularZone(); } ngOnDestroy() { destroyedInTheZone = NgZone.isInAngularZone(); }
} }
@Component({ @Component({
selector: 'wrapper', selector: 'wrapper',
template: '<ng-content></ng-content>', template: '<ng-content></ng-content>',
}) })
class WrapperComponent { class WrapperComponent {
} }
@NgModule({ @NgModule({
declarations: [TestComponent, WrapperComponent], declarations: [TestComponent, WrapperComponent],
entryComponents: [TestComponent, WrapperComponent], entryComponents: [TestComponent, WrapperComponent],
imports: [BrowserModule], imports: [BrowserModule],
}) })
class Ng2Module { class Ng2Module {
ngDoBootstrap() {} ngDoBootstrap() {}
} }
const bootstrapFn = (extraProviders: StaticProvider[]) => const bootstrapFn = (extraProviders: StaticProvider[]) =>
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module); platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn); const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module = const ng1Module =
angular.module('ng1', [lazyModuleName]) angular.module('ng1', [lazyModuleName])
.directive( .directive(
'test', downgradeComponent({component: TestComponent, propagateDigest})) 'test', downgradeComponent({component: TestComponent, propagateDigest}))
.directive( .directive(
'wrapper', 'wrapper',
downgradeComponent({component: WrapperComponent, propagateDigest})); downgradeComponent({component: WrapperComponent, propagateDigest}));
// Important: `ng-if` makes `<test>` render asynchronously. // Important: `ng-if` makes `<test>` render asynchronously.
const element = html('<wrapper><test ng-if="showNg2"></test></wrapper>'); const element = html('<wrapper><test ng-if="showNg2"></test></wrapper>');
const $injector = angular.bootstrap(element, [ng1Module.name]); const $injector = angular.bootstrap(element, [ng1Module.name]);
const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService; const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService;
// Wait for the module to be bootstrapped. // Wait for the module to be bootstrapped.
setTimeout(() => { setTimeout(() => {
// Create nested component asynchronously. // Create nested component asynchronously.
expect(createdInTheZone).toBe(false); expect(createdInTheZone).toBe(false);
$rootScope.$apply('showNg2 = true'); $rootScope.$apply('showNg2 = true');
expect(createdInTheZone).toBe(true); expect(createdInTheZone).toBe(true);
// Destroy nested component asynchronously. // Destroy nested component asynchronously.
expect(destroyedInTheZone).toBe(false); expect(destroyedInTheZone).toBe(false);
$rootScope.$apply('showNg2 = false'); $rootScope.$apply('showNg2 = false');
expect(destroyedInTheZone).toBe(true); expect(destroyedInTheZone).toBe(true);
}); });
})); }));
it('should wire up the component for change detection', async(() => { it('should wire up the component for change detection', async(() => {
@Component( @Component(
@ -888,65 +884,62 @@ withEachNg1Version(() => {
}); });
})); }));
fixmeIvy('FW-714: ng1 projected content is not being rendered') it('should wire up nested, asynchronously instantiated components for change detection',
.it('should wire up nested, asynchronously instantiated components for change detection', async(() => {
async(() => { @Component(
@Component({ {selector: 'test', template: '{{ count }}<button (click)="increment()"></button>'})
selector: 'test', class TestComponent {
template: '{{ count }}<button (click)="increment()"></button>' count = 0;
}) increment() { ++this.count; }
class TestComponent { }
count = 0;
increment() { ++this.count; }
}
@Component({ @Component({
selector: 'wrapper', selector: 'wrapper',
template: '<ng-content></ng-content>', template: '<ng-content></ng-content>',
}) })
class WrapperComponent { class WrapperComponent {
} }
@NgModule({ @NgModule({
declarations: [TestComponent, WrapperComponent], declarations: [TestComponent, WrapperComponent],
entryComponents: [TestComponent, WrapperComponent], entryComponents: [TestComponent, WrapperComponent],
imports: [BrowserModule], imports: [BrowserModule],
}) })
class Ng2Module { class Ng2Module {
ngDoBootstrap() {} ngDoBootstrap() {}
} }
const bootstrapFn = (extraProviders: StaticProvider[]) => const bootstrapFn = (extraProviders: StaticProvider[]) =>
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module); platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn); const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module = const ng1Module =
angular.module('ng1', [lazyModuleName]) angular.module('ng1', [lazyModuleName])
.directive( .directive(
'test', downgradeComponent({component: TestComponent, propagateDigest})) 'test', downgradeComponent({component: TestComponent, propagateDigest}))
.directive( .directive(
'wrapper', 'wrapper',
downgradeComponent({component: WrapperComponent, propagateDigest})); downgradeComponent({component: WrapperComponent, propagateDigest}));
// Important: `ng-if` makes `<test>` render asynchronously. // Important: `ng-if` makes `<test>` render asynchronously.
const element = html('<wrapper><test ng-if="showNg2"></test></wrapper>'); const element = html('<wrapper><test ng-if="showNg2"></test></wrapper>');
const $injector = angular.bootstrap(element, [ng1Module.name]); const $injector = angular.bootstrap(element, [ng1Module.name]);
const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService; const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService;
// Wait for the module to be bootstrapped. // Wait for the module to be bootstrapped.
setTimeout(() => { setTimeout(() => {
// Create nested component asynchronously. // Create nested component asynchronously.
$rootScope.$apply('showNg2 = true'); $rootScope.$apply('showNg2 = true');
const button = element.querySelector('button') !; const button = element.querySelector('button') !;
expect(element.textContent).toBe('0'); expect(element.textContent).toBe('0');
button.click(); button.click();
expect(element.textContent).toBe('1'); expect(element.textContent).toBe('1');
button.click(); button.click();
expect(element.textContent).toBe('2'); expect(element.textContent).toBe('2');
}); });
})); }));
it('should run the lifecycle hooks in the correct order', async(() => { it('should run the lifecycle hooks in the correct order', async(() => {
const logs: string[] = []; const logs: string[] = [];