diff --git a/packages/upgrade/test/common/downgrade_component_adapter_spec.ts b/packages/upgrade/test/common/downgrade_component_adapter_spec.ts index d7d5e0e566..bf5d4cc471 100644 --- a/packages/upgrade/test/common/downgrade_component_adapter_spec.ts +++ b/packages/upgrade/test/common/downgrade_component_adapter_spec.ts @@ -7,7 +7,6 @@ */ import {Compiler, Component, ComponentFactory, Injector, NgModule, TestabilityRegistry} from '@angular/core'; import {TestBed} from '@angular/core/testing'; -import {fixmeIvy} from '@angular/private/testing'; import * as angular from '@angular/upgrade/src/common/angular1'; import {DowngradeComponentAdapter, groupNodesBySelector} from '@angular/upgrade/src/common/downgrade_component_adapter'; diff --git a/packages/upgrade/test/dynamic/upgrade_spec.ts b/packages/upgrade/test/dynamic/upgrade_spec.ts index 5ebc3e42aa..51de32f600 100644 --- a/packages/upgrade/test/dynamic/upgrade_spec.ts +++ b/packages/upgrade/test/dynamic/upgrade_spec.ts @@ -1681,52 +1681,51 @@ withEachNg1Version(() => { }); })); - fixmeIvy('unknown') && - it('should not call `$onInit()` on scope', async(() => { - const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); - const $onInitSpy = jasmine.createSpy('$onInit'); + it('should not call `$onInit()` on scope', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); + const $onInitSpy = jasmine.createSpy('$onInit'); - @Component({selector: 'ng2', template: ' | '}) - class Ng2Component { - } + @Component({selector: 'ng2', template: ' | '}) + class Ng2Component { + } - angular.module('ng1', []) - .directive('ng1A', () => ({ - template: '', - scope: {}, - bindToController: true, - controllerAs: '$ctrl', - controller: function($scope: angular.IScope) { - Object.getPrototypeOf($scope).$onInit = $onInitSpy; - } - })) - .directive('ng1B', () => ({ - template: '', - scope: {}, - bindToController: false, - controllerAs: '$ctrl', - controller: function($scope: angular.IScope) { - $scope['$onInit'] = $onInitSpy; - } - })) - .directive('ng2', adapter.downgradeNg2Component(Ng2Component)); + angular.module('ng1', []) + .directive('ng1A', () => ({ + template: '', + scope: {}, + bindToController: true, + controllerAs: '$ctrl', + controller: function($scope: angular.IScope) { + Object.getPrototypeOf($scope).$onInit = $onInitSpy; + } + })) + .directive('ng1B', () => ({ + template: '', + scope: {}, + bindToController: false, + controllerAs: '$ctrl', + controller: function($scope: angular.IScope) { + $scope['$onInit'] = $onInitSpy; + } + })) + .directive('ng2', adapter.downgradeNg2Component(Ng2Component)); - @NgModule({ - declarations: [ - adapter.upgradeNg1Component('ng1A'), adapter.upgradeNg1Component('ng1B'), - Ng2Component - ], - imports: [BrowserModule], - }) - class Ng2Module { - } + @NgModule({ + declarations: [ + adapter.upgradeNg1Component('ng1A'), adapter.upgradeNg1Component('ng1B'), + Ng2Component + ], + imports: [BrowserModule], + }) + class Ng2Module { + } - const element = html(`
`); - adapter.bootstrap(element, ['ng1']).ready((ref) => { - expect($onInitSpy).not.toHaveBeenCalled(); - ref.dispose(); - }); - })); + const element = html(`
`); + adapter.bootstrap(element, ['ng1']).ready((ref) => { + expect($onInitSpy).not.toHaveBeenCalled(); + ref.dispose(); + }); + })); fixmeIvy('unknown') && it('should call `$doCheck()` on controller', async(() => { @@ -1783,61 +1782,60 @@ withEachNg1Version(() => { }); })); - fixmeIvy('unknown') && - it('should not call `$doCheck()` on scope', async(() => { - const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); - const $doCheckSpyA = jasmine.createSpy('$doCheckA'); - const $doCheckSpyB = jasmine.createSpy('$doCheckB'); - let changeDetector: ChangeDetectorRef; + it('should not call `$doCheck()` on scope', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); + const $doCheckSpyA = jasmine.createSpy('$doCheckA'); + const $doCheckSpyB = jasmine.createSpy('$doCheckB'); + let changeDetector: ChangeDetectorRef; - @Component({selector: 'ng2', template: ' | '}) - class Ng2Component { - constructor(cd: ChangeDetectorRef) { changeDetector = cd; } - } + @Component({selector: 'ng2', template: ' | '}) + class Ng2Component { + constructor(cd: ChangeDetectorRef) { changeDetector = cd; } + } - angular.module('ng1', []) - .directive('ng1A', () => ({ - template: '', - scope: {}, - bindToController: true, - controllerAs: '$ctrl', - controller: function($scope: angular.IScope) { - Object.getPrototypeOf($scope).$doCheck = $doCheckSpyA; - } - })) - .directive('ng1B', () => ({ - template: '', - scope: {}, - bindToController: false, - controllerAs: '$ctrl', - controller: function($scope: angular.IScope) { - $scope['$doCheck'] = $doCheckSpyB; - } - })) - .directive('ng2', adapter.downgradeNg2Component(Ng2Component)); + angular.module('ng1', []) + .directive('ng1A', () => ({ + template: '', + scope: {}, + bindToController: true, + controllerAs: '$ctrl', + controller: function($scope: angular.IScope) { + Object.getPrototypeOf($scope).$doCheck = $doCheckSpyA; + } + })) + .directive('ng1B', () => ({ + template: '', + scope: {}, + bindToController: false, + controllerAs: '$ctrl', + controller: function($scope: angular.IScope) { + $scope['$doCheck'] = $doCheckSpyB; + } + })) + .directive('ng2', adapter.downgradeNg2Component(Ng2Component)); - @NgModule({ - declarations: [ - adapter.upgradeNg1Component('ng1A'), adapter.upgradeNg1Component('ng1B'), - Ng2Component - ], - imports: [BrowserModule], - }) - class Ng2Module { - } + @NgModule({ + declarations: [ + adapter.upgradeNg1Component('ng1A'), adapter.upgradeNg1Component('ng1B'), + Ng2Component + ], + imports: [BrowserModule], + }) + class Ng2Module { + } - const element = html(`
`); - adapter.bootstrap(element, ['ng1']).ready((ref) => { - $doCheckSpyA.calls.reset(); - $doCheckSpyB.calls.reset(); - changeDetector.detectChanges(); + const element = html(`
`); + adapter.bootstrap(element, ['ng1']).ready((ref) => { + $doCheckSpyA.calls.reset(); + $doCheckSpyB.calls.reset(); + changeDetector.detectChanges(); - expect($doCheckSpyA).not.toHaveBeenCalled(); - expect($doCheckSpyB).not.toHaveBeenCalled(); + expect($doCheckSpyA).not.toHaveBeenCalled(); + expect($doCheckSpyB).not.toHaveBeenCalled(); - ref.dispose(); - }); - })); + ref.dispose(); + }); + })); fixmeIvy('unknown') && it('should call `$postLink()` on controller', async(() => { @@ -1885,52 +1883,51 @@ withEachNg1Version(() => { }); })); - fixmeIvy('unknown') && - it('should not call `$postLink()` on scope', async(() => { - const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); - const $postLinkSpy = jasmine.createSpy('$postLink'); + it('should not call `$postLink()` on scope', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); + const $postLinkSpy = jasmine.createSpy('$postLink'); - @Component({selector: 'ng2', template: ' | '}) - class Ng2Component { - } + @Component({selector: 'ng2', template: ' | '}) + class Ng2Component { + } - angular.module('ng1', []) - .directive('ng1A', () => ({ - template: '', - scope: {}, - bindToController: true, - controllerAs: '$ctrl', - controller: function($scope: angular.IScope) { - Object.getPrototypeOf($scope).$postLink = $postLinkSpy; - } - })) - .directive('ng1B', () => ({ - template: '', - scope: {}, - bindToController: false, - controllerAs: '$ctrl', - controller: function($scope: angular.IScope) { - $scope['$postLink'] = $postLinkSpy; - } - })) - .directive('ng2', adapter.downgradeNg2Component(Ng2Component)); + angular.module('ng1', []) + .directive('ng1A', () => ({ + template: '', + scope: {}, + bindToController: true, + controllerAs: '$ctrl', + controller: function($scope: angular.IScope) { + Object.getPrototypeOf($scope).$postLink = $postLinkSpy; + } + })) + .directive('ng1B', () => ({ + template: '', + scope: {}, + bindToController: false, + controllerAs: '$ctrl', + controller: function($scope: angular.IScope) { + $scope['$postLink'] = $postLinkSpy; + } + })) + .directive('ng2', adapter.downgradeNg2Component(Ng2Component)); - @NgModule({ - declarations: [ - adapter.upgradeNg1Component('ng1A'), adapter.upgradeNg1Component('ng1B'), - Ng2Component - ], - imports: [BrowserModule], - }) - class Ng2Module { - } + @NgModule({ + declarations: [ + adapter.upgradeNg1Component('ng1A'), adapter.upgradeNg1Component('ng1B'), + Ng2Component + ], + imports: [BrowserModule], + }) + class Ng2Module { + } - const element = html(`
`); - adapter.bootstrap(element, ['ng1']).ready((ref) => { - expect($postLinkSpy).not.toHaveBeenCalled(); - ref.dispose(); - }); - })); + const element = html(`
`); + adapter.bootstrap(element, ['ng1']).ready((ref) => { + expect($postLinkSpy).not.toHaveBeenCalled(); + ref.dispose(); + }); + })); fixmeIvy('unknown') && it('should call `$onChanges()` on binding destination', fakeAsync(() => { diff --git a/packages/upgrade/test/static/integration/downgrade_component_spec.ts b/packages/upgrade/test/static/integration/downgrade_component_spec.ts index 6cb9636c1b..4ca5bb86b2 100644 --- a/packages/upgrade/test/static/integration/downgrade_component_spec.ts +++ b/packages/upgrade/test/static/integration/downgrade_component_spec.ts @@ -520,96 +520,94 @@ withEachNg1Version(() => { }); })); - fixmeIvy('FW-713: ngDestroy not being called when downgraded ng2 component is destroyed') && - it('should properly run cleanup when ng1 directive is destroyed', async(() => { + it('should properly run cleanup when ng1 directive is destroyed', async(() => { - let destroyed = false; - @Component({selector: 'ng2', template: 'test'}) - class Ng2Component implements OnDestroy { - ngOnDestroy() { destroyed = true; } - } + let destroyed = false; + @Component({selector: 'ng2', template: 'test'}) + class Ng2Component implements OnDestroy { + ngOnDestroy() { destroyed = true; } + } - @NgModule({ - declarations: [Ng2Component], - entryComponents: [Ng2Component], - imports: [BrowserModule, UpgradeModule] - }) - class Ng2Module { - ngDoBootstrap() {} - } + @NgModule({ + declarations: [Ng2Component], + entryComponents: [Ng2Component], + imports: [BrowserModule, UpgradeModule] + }) + class Ng2Module { + ngDoBootstrap() {} + } - const ng1Module = - angular.module('ng1', []) - .directive( - 'ng1', - () => { return {template: '
'}; }) - .directive('ng2', downgradeComponent({component: Ng2Component})); - const element = html(''); - platformBrowserDynamic().bootstrapModule(Ng2Module).then((ref) => { - const adapter = ref.injector.get(UpgradeModule) as UpgradeModule; - adapter.bootstrap(element, [ng1Module.name]); - expect(element.textContent).toContain('test'); - expect(destroyed).toBe(false); + const ng1Module = + angular.module('ng1', []) + .directive( + 'ng1', + () => { return {template: '
'}; }) + .directive('ng2', downgradeComponent({component: Ng2Component})); + const element = html(''); + platformBrowserDynamic().bootstrapModule(Ng2Module).then((ref) => { + const adapter = ref.injector.get(UpgradeModule) as UpgradeModule; + adapter.bootstrap(element, [ng1Module.name]); + expect(element.textContent).toContain('test'); + expect(destroyed).toBe(false); - const $rootScope = adapter.$injector.get('$rootScope'); - $rootScope.$apply('destroyIt = true'); + const $rootScope = adapter.$injector.get('$rootScope'); + $rootScope.$apply('destroyIt = true'); - expect(element.textContent).not.toContain('test'); - expect(destroyed).toBe(true); - }); - })); + expect(element.textContent).not.toContain('test'); + expect(destroyed).toBe(true); + }); + })); - fixmeIvy('FW-642: ASSERTION ERROR: Slot should have been initialized to NO_CHANGE') && - it('should properly run cleanup with multiple levels of nesting', async(() => { - let destroyed = false; + it('should properly run cleanup with multiple levels of nesting', async(() => { + let destroyed = false; - @Component({ - selector: 'ng2-outer', - template: '
', - }) - class Ng2OuterComponent { - @Input() destroyIt = false; - } + @Component({ + selector: 'ng2-outer', + template: '
', + }) + class Ng2OuterComponent { + @Input() destroyIt = false; + } - @Component({selector: 'ng2-inner', template: 'test'}) - class Ng2InnerComponent implements OnDestroy { - ngOnDestroy() { destroyed = true; } - } + @Component({selector: 'ng2-inner', template: 'test'}) + class Ng2InnerComponent implements OnDestroy { + ngOnDestroy() { destroyed = true; } + } - @Directive({selector: 'ng1'}) - class Ng1ComponentFacade extends UpgradeComponent { - constructor(elementRef: ElementRef, injector: Injector) { - super('ng1', elementRef, injector); - } - } + @Directive({selector: 'ng1'}) + class Ng1ComponentFacade extends UpgradeComponent { + constructor(elementRef: ElementRef, injector: Injector) { + super('ng1', elementRef, injector); + } + } - @NgModule({ - imports: [BrowserModule, UpgradeModule], - declarations: [Ng1ComponentFacade, Ng2InnerComponent, Ng2OuterComponent], - entryComponents: [Ng2InnerComponent, Ng2OuterComponent], - }) - class Ng2Module { - ngDoBootstrap() {} - } + @NgModule({ + imports: [BrowserModule, UpgradeModule], + declarations: [Ng1ComponentFacade, Ng2InnerComponent, Ng2OuterComponent], + entryComponents: [Ng2InnerComponent, Ng2OuterComponent], + }) + class Ng2Module { + ngDoBootstrap() {} + } - const ng1Module = - angular.module('ng1', []) - .directive('ng1', () => ({template: ''})) - .directive('ng2Inner', downgradeComponent({component: Ng2InnerComponent})) - .directive('ng2Outer', downgradeComponent({component: Ng2OuterComponent})); + const ng1Module = + angular.module('ng1', []) + .directive('ng1', () => ({template: ''})) + .directive('ng2Inner', downgradeComponent({component: Ng2InnerComponent})) + .directive('ng2Outer', downgradeComponent({component: Ng2OuterComponent})); - const element = html(''); + const element = html(''); - bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then(upgrade => { - expect(element.textContent).toBe('test'); - expect(destroyed).toBe(false); + bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then(upgrade => { + expect(element.textContent).toBe('test'); + expect(destroyed).toBe(false); - $apply(upgrade, 'destroyIt = true'); + $apply(upgrade, 'destroyIt = true'); - expect(element.textContent).toBe(''); - expect(destroyed).toBe(true); - }); - })); + expect(element.textContent).toBe(''); + expect(destroyed).toBe(true); + }); + })); it('should work when compiled outside the dom (by fallback to the root ng2.injector)', async(() => { @@ -743,7 +741,7 @@ withEachNg1Version(() => { }); })); - fixmeIvy('FW-561: Runtime compiler is not loaded') && + fixmeIvy('FW-717: Browser locks up and disconnects') && it('should work with ng2 lazy loaded components', async(() => { let componentInjector: Injector; diff --git a/packages/upgrade/test/static/integration/downgrade_module_spec.ts b/packages/upgrade/test/static/integration/downgrade_module_spec.ts index 9214607e76..aec04938fd 100644 --- a/packages/upgrade/test/static/integration/downgrade_module_spec.ts +++ b/packages/upgrade/test/static/integration/downgrade_module_spec.ts @@ -225,42 +225,41 @@ withEachNg1Version(() => { }); })); - fixmeIvy('FW-713: ngDestroy not being called when downgraded ng2 component is destroyed') && - it('should destroy components inside the Angular zone', async(() => { - let destroyedInTheZone = false; + it('should destroy components inside the Angular zone', async(() => { + let destroyedInTheZone = false; - @Component({selector: 'ng2', template: ''}) - class Ng2Component implements OnDestroy { - ngOnDestroy() { destroyedInTheZone = NgZone.isInAngularZone(); } - } + @Component({selector: 'ng2', template: ''}) + class Ng2Component implements OnDestroy { + ngOnDestroy() { destroyedInTheZone = NgZone.isInAngularZone(); } + } - @NgModule({ - declarations: [Ng2Component], - entryComponents: [Ng2Component], - imports: [BrowserModule], - }) - class Ng2Module { - ngDoBootstrap() {} - } + @NgModule({ + declarations: [Ng2Component], + entryComponents: [Ng2Component], + imports: [BrowserModule], + }) + class Ng2Module { + ngDoBootstrap() {} + } - const bootstrapFn = (extraProviders: StaticProvider[]) => - platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module); - const lazyModuleName = downgradeModule(bootstrapFn); - const ng1Module = - angular.module('ng1', [lazyModuleName]) - .directive( - 'ng2', downgradeComponent({component: Ng2Component, propagateDigest})); + const bootstrapFn = (extraProviders: StaticProvider[]) => + platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module); + const lazyModuleName = downgradeModule(bootstrapFn); + const ng1Module = + angular.module('ng1', [lazyModuleName]) + .directive( + 'ng2', downgradeComponent({component: Ng2Component, propagateDigest})); - const element = html(''); - const $injector = angular.bootstrap(element, [ng1Module.name]); - const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService; + const element = html(''); + const $injector = angular.bootstrap(element, [ng1Module.name]); + const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService; - // Wait for the module to be bootstrapped. - setTimeout(() => { - $rootScope.$apply('hideNg2 = true'); - expect(destroyedInTheZone).toBe(true); - }); - })); + // Wait for the module to be bootstrapped. + setTimeout(() => { + $rootScope.$apply('hideNg2 = true'); + expect(destroyedInTheZone).toBe(true); + }); + })); fixmeIvy('FW-715: ngOnChanges being called a second time unexpectedly') && it('should propagate input changes inside the Angular zone', async(() => { @@ -526,54 +525,53 @@ withEachNg1Version(() => { }); })); - fixmeIvy('FW-717: Browser locks up and disconnects') && - it('should detach hostViews from the ApplicationRef once destroyed', async(() => { - let ng2Component: Ng2Component; + it('should detach hostViews from the ApplicationRef once destroyed', async(() => { + let ng2Component: Ng2Component; - @Component({selector: 'ng2', template: ''}) - class Ng2Component { - constructor(public appRef: ApplicationRef) { - ng2Component = this; - spyOn(appRef, 'attachView').and.callThrough(); - spyOn(appRef, 'detachView').and.callThrough(); - } - } + @Component({selector: 'ng2', template: ''}) + class Ng2Component { + constructor(public appRef: ApplicationRef) { + ng2Component = this; + spyOn(appRef, 'attachView').and.callThrough(); + spyOn(appRef, 'detachView').and.callThrough(); + } + } - @NgModule({ - declarations: [Ng2Component], - entryComponents: [Ng2Component], - imports: [BrowserModule], - }) - class Ng2Module { - ngDoBootstrap() {} - } + @NgModule({ + declarations: [Ng2Component], + entryComponents: [Ng2Component], + imports: [BrowserModule], + }) + class Ng2Module { + ngDoBootstrap() {} + } - const bootstrapFn = (extraProviders: StaticProvider[]) => - platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module); - const lazyModuleName = downgradeModule(bootstrapFn); - const ng1Module = - angular.module('ng1', [lazyModuleName]) - .directive( - 'ng2', downgradeComponent({component: Ng2Component, propagateDigest})); + const bootstrapFn = (extraProviders: StaticProvider[]) => + platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module); + const lazyModuleName = downgradeModule(bootstrapFn); + const ng1Module = + angular.module('ng1', [lazyModuleName]) + .directive( + 'ng2', downgradeComponent({component: Ng2Component, propagateDigest})); - const element = html(''); - const $injector = angular.bootstrap(element, [ng1Module.name]); - const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService; + const element = html(''); + const $injector = angular.bootstrap(element, [ng1Module.name]); + const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService; - setTimeout(() => { // Wait for the module to be bootstrapped. - setTimeout(() => { // Wait for the hostView to be attached (during the `$digest`). - const hostView: ViewRef = - (ng2Component.appRef.attachView as jasmine.Spy).calls.mostRecent().args[0]; + setTimeout(() => { // Wait for the module to be bootstrapped. + setTimeout(() => { // Wait for the hostView to be attached (during the `$digest`). + const hostView: ViewRef = + (ng2Component.appRef.attachView as jasmine.Spy).calls.mostRecent().args[0]; - expect(hostView.destroyed).toBe(false); + expect(hostView.destroyed).toBe(false); - $rootScope.$apply('hideNg2 = true'); + $rootScope.$apply('hideNg2 = true'); - expect(hostView.destroyed).toBe(true); - expect(ng2Component.appRef.detachView).toHaveBeenCalledWith(hostView); - }); - }); - })); + expect(hostView.destroyed).toBe(true); + expect(ng2Component.appRef.detachView).toHaveBeenCalledWith(hostView); + }); + }); + })); it('should only retrieve the Angular zone once (and cache it for later use)', fakeAsync(() => { diff --git a/packages/upgrade/test/static/integration/upgrade_component_spec.ts b/packages/upgrade/test/static/integration/upgrade_component_spec.ts index 31e8f143ae..63f050b8cb 100644 --- a/packages/upgrade/test/static/integration/upgrade_component_spec.ts +++ b/packages/upgrade/test/static/integration/upgrade_component_spec.ts @@ -3965,23 +3965,22 @@ withEachNg1Version(() => { }); })); - fixmeIvy('FW-642: ASSERTION ERROR: Slot should have been initialized to NO_CHANGE') && - it('should support ng2 > ng1 > ng2 (with inputs/outputs)', fakeAsync(() => { - let ng2ComponentAInstance: Ng2ComponentA; - let ng2ComponentBInstance: Ng2ComponentB; - let ng1ControllerXInstance: Ng1ControllerX; + it('should support ng2 > ng1 > ng2 (with inputs/outputs)', fakeAsync(() => { + let ng2ComponentAInstance: Ng2ComponentA; + let ng2ComponentBInstance: Ng2ComponentB; + let ng1ControllerXInstance: Ng1ControllerX; - // Define `ng1Component` - class Ng1ControllerX { - // TODO(issue/24571): remove '!'. - ng1XInputA !: string; - ng1XInputB: any; - ng1XInputC: any; + // Define `ng1Component` + class Ng1ControllerX { + // TODO(issue/24571): remove '!'. + ng1XInputA !: string; + ng1XInputB: any; + ng1XInputC: any; - constructor() { ng1ControllerXInstance = this; } - } - const ng1Component: angular.IComponent = { - template: ` + constructor() { ng1ControllerXInstance = this; } + } + const ng1Component: angular.IComponent = { + template: ` ng1X({{ $ctrl.ng1XInputA }}, {{ $ctrl.ng1XInputB.value }}, {{ $ctrl.ng1XInputC.value }}) | { (ng2-b-output-c)="$ctrl.ng1XInputC = {value: $event}"> `, - bindings: { - ng1XInputA: '@', - ng1XInputB: '<', - ng1XInputC: '=', - ng1XOutputA: '&', - ng1XOutputB: '&' - }, - controller: Ng1ControllerX - }; + bindings: { + ng1XInputA: '@', + ng1XInputB: '<', + ng1XInputC: '=', + ng1XOutputA: '&', + ng1XOutputB: '&' + }, + controller: Ng1ControllerX + }; - // Define `Ng1ComponentFacade` - @Directive({selector: 'ng1X'}) - class Ng1ComponentXFacade extends UpgradeComponent { - // TODO(issue/24571): remove '!'. - @Input() ng1XInputA !: string; - @Input() ng1XInputB: any; - @Input() ng1XInputC: any; - // TODO(issue/24571): remove '!'. - @Output() ng1XInputCChange !: EventEmitter; - // TODO(issue/24571): remove '!'. - @Output() ng1XOutputA !: EventEmitter; - // TODO(issue/24571): remove '!'. - @Output() ng1XOutputB !: EventEmitter; + // Define `Ng1ComponentFacade` + @Directive({selector: 'ng1X'}) + class Ng1ComponentXFacade extends UpgradeComponent { + // TODO(issue/24571): remove '!'. + @Input() ng1XInputA !: string; + @Input() ng1XInputB: any; + @Input() ng1XInputC: any; + // TODO(issue/24571): remove '!'. + @Output() ng1XInputCChange !: EventEmitter; + // TODO(issue/24571): remove '!'. + @Output() ng1XOutputA !: EventEmitter; + // TODO(issue/24571): remove '!'. + @Output() ng1XOutputB !: EventEmitter; - constructor(elementRef: ElementRef, injector: Injector) { - super('ng1X', elementRef, injector); - } - } + constructor(elementRef: ElementRef, injector: Injector) { + super('ng1X', elementRef, injector); + } + } - // Define `Ng2Component` - @Component({ - selector: 'ng2-a', - template: ` + // Define `Ng2Component` + @Component({ + selector: 'ng2-a', + template: ` ng2A({{ ng2ADataA.value }}, {{ ng2ADataB.value }}, {{ ng2ADataC.value }}) | { on-ng1XOutputB="ng2ADataB.value = $event"> ` - }) - class Ng2ComponentA { - ng2ADataA = {value: 'foo'}; - ng2ADataB = {value: 'bar'}; - ng2ADataC = {value: 'baz'}; + }) + class Ng2ComponentA { + ng2ADataA = {value: 'foo'}; + ng2ADataB = {value: 'bar'}; + ng2ADataC = {value: 'baz'}; - constructor() { ng2ComponentAInstance = this; } - } + constructor() { ng2ComponentAInstance = this; } + } - @Component({selector: 'ng2-b', template: 'ng2B({{ ng2BInputA }}, {{ ng2BInputC }})'}) - class Ng2ComponentB { - @Input('ng2BInput1') ng2BInputA: any; - @Input() ng2BInputC: any; - @Output() ng2BOutputC = new EventEmitter(); + @Component({selector: 'ng2-b', template: 'ng2B({{ ng2BInputA }}, {{ ng2BInputC }})'}) + class Ng2ComponentB { + @Input('ng2BInput1') ng2BInputA: any; + @Input() ng2BInputC: any; + @Output() ng2BOutputC = new EventEmitter(); - constructor() { ng2ComponentBInstance = this; } - } + constructor() { ng2ComponentBInstance = this; } + } - // Define `ng1Module` - const ng1Module = - angular.module('ng1', []) - .component('ng1X', ng1Component) - .directive('ng2A', downgradeComponent({component: Ng2ComponentA})) - .directive('ng2B', downgradeComponent({component: Ng2ComponentB})); + // Define `ng1Module` + const ng1Module = angular.module('ng1', []) + .component('ng1X', ng1Component) + .directive('ng2A', downgradeComponent({component: Ng2ComponentA})) + .directive('ng2B', downgradeComponent({component: Ng2ComponentB})); - // Define `Ng2Module` - @NgModule({ - declarations: [Ng1ComponentXFacade, Ng2ComponentA, Ng2ComponentB], - entryComponents: [Ng2ComponentA, Ng2ComponentB], - imports: [BrowserModule, UpgradeModule], - schemas: [NO_ERRORS_SCHEMA], - }) - class Ng2Module { - ngDoBootstrap() {} - } + // Define `Ng2Module` + @NgModule({ + declarations: [Ng1ComponentXFacade, Ng2ComponentA, Ng2ComponentB], + entryComponents: [Ng2ComponentA, Ng2ComponentB], + imports: [BrowserModule, UpgradeModule], + schemas: [NO_ERRORS_SCHEMA], + }) + class Ng2Module { + ngDoBootstrap() {} + } - // Bootstrap - const element = html(``); + // Bootstrap + const element = html(``); - bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then(adapter => { - // Initial value propagation. - // (ng2A > ng1X > ng2B) - expect(multiTrim(document.body.textContent)) - .toBe('ng2A(foo, bar, baz) | ng1X(foo, bar, baz) | ng2B(foo, baz)'); + bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then(adapter => { + // Initial value propagation. + // (ng2A > ng1X > ng2B) + expect(multiTrim(document.body.textContent)) + .toBe('ng2A(foo, bar, baz) | ng1X(foo, bar, baz) | ng2B(foo, baz)'); - // Update `ng2BInputA`/`ng2BInputC`. - // (Should not propagate upwards.) - ng2ComponentBInstance.ng2BInputA = 'foo2'; - ng2ComponentBInstance.ng2BInputC = 'baz2'; - $digest(adapter); - tick(); + // Update `ng2BInputA`/`ng2BInputC`. + // (Should not propagate upwards.) + ng2ComponentBInstance.ng2BInputA = 'foo2'; + ng2ComponentBInstance.ng2BInputC = 'baz2'; + $digest(adapter); + tick(); - expect(multiTrim(document.body.textContent)) - .toBe('ng2A(foo, bar, baz) | ng1X(foo, bar, baz) | ng2B(foo2, baz2)'); + expect(multiTrim(document.body.textContent)) + .toBe('ng2A(foo, bar, baz) | ng1X(foo, bar, baz) | ng2B(foo2, baz2)'); - // Emit from `ng2BOutputC`. - // (Should propagate all the way up to `ng1ADataC` and back all the way down to - // `ng2BInputC`.) - ng2ComponentBInstance.ng2BOutputC.emit('baz3'); - $digest(adapter); - tick(); + // Emit from `ng2BOutputC`. + // (Should propagate all the way up to `ng1ADataC` and back all the way down to + // `ng2BInputC`.) + ng2ComponentBInstance.ng2BOutputC.emit('baz3'); + $digest(adapter); + tick(); - expect(multiTrim(document.body.textContent)) - .toBe('ng2A(foo, bar, baz3) | ng1X(foo, bar, baz3) | ng2B(foo2, baz3)'); + expect(multiTrim(document.body.textContent)) + .toBe('ng2A(foo, bar, baz3) | ng1X(foo, bar, baz3) | ng2B(foo2, baz3)'); - // Update `ng1XInputA`/`ng1XInputB`. - // (Should not propagate upwards, only downwards.) - ng1ControllerXInstance.ng1XInputA = 'foo4'; - ng1ControllerXInstance.ng1XInputB = {value: 'bar4'}; - $digest(adapter); - tick(); + // Update `ng1XInputA`/`ng1XInputB`. + // (Should not propagate upwards, only downwards.) + ng1ControllerXInstance.ng1XInputA = 'foo4'; + ng1ControllerXInstance.ng1XInputB = {value: 'bar4'}; + $digest(adapter); + tick(); - expect(multiTrim(document.body.textContent)) - .toBe('ng2A(foo, bar, baz3) | ng1X(foo4, bar4, baz3) | ng2B(foo4, baz3)'); + expect(multiTrim(document.body.textContent)) + .toBe('ng2A(foo, bar, baz3) | ng1X(foo4, bar4, baz3) | ng2B(foo4, baz3)'); - // Update `ng1XInputC`. - // (Should propagate upwards and downwards.) - ng1ControllerXInstance.ng1XInputC = {value: 'baz5'}; - $digest(adapter); - tick(); + // Update `ng1XInputC`. + // (Should propagate upwards and downwards.) + ng1ControllerXInstance.ng1XInputC = {value: 'baz5'}; + $digest(adapter); + tick(); - expect(multiTrim(document.body.textContent)) - .toBe('ng2A(foo, bar, baz5) | ng1X(foo4, bar4, baz5) | ng2B(foo4, baz5)'); + expect(multiTrim(document.body.textContent)) + .toBe('ng2A(foo, bar, baz5) | ng1X(foo4, bar4, baz5) | ng2B(foo4, baz5)'); - // Update a property on `ng1XInputC`. - // (Should propagate upwards and downwards.) - ng1ControllerXInstance.ng1XInputC.value = 'baz6'; - $digest(adapter); - tick(); + // Update a property on `ng1XInputC`. + // (Should propagate upwards and downwards.) + ng1ControllerXInstance.ng1XInputC.value = 'baz6'; + $digest(adapter); + tick(); - expect(multiTrim(document.body.textContent)) - .toBe('ng2A(foo, bar, baz6) | ng1X(foo4, bar4, baz6) | ng2B(foo4, baz6)'); + expect(multiTrim(document.body.textContent)) + .toBe('ng2A(foo, bar, baz6) | ng1X(foo4, bar4, baz6) | ng2B(foo4, baz6)'); - // Emit from `ng1XOutputA`. - // (Should propagate upwards to `ng1ADataA` and back all the way down to - // `ng2BInputA`.) - (ng1ControllerXInstance as any).ng1XOutputA({value: 'foo7'}); - $digest(adapter); - tick(); + // Emit from `ng1XOutputA`. + // (Should propagate upwards to `ng1ADataA` and back all the way down to + // `ng2BInputA`.) + (ng1ControllerXInstance as any).ng1XOutputA({value: 'foo7'}); + $digest(adapter); + tick(); - expect(multiTrim(document.body.textContent)) - .toBe('ng2A(foo7, bar, baz6) | ng1X(foo7, bar4, baz6) | ng2B(foo7, baz6)'); + expect(multiTrim(document.body.textContent)) + .toBe('ng2A(foo7, bar, baz6) | ng1X(foo7, bar4, baz6) | ng2B(foo7, baz6)'); - // Emit from `ng1XOutputB`. - // (Should propagate upwards to `ng1ADataB`, but not downwards, - // since `ng1XInputB` has been re-assigned (i.e. `ng2ADataB !== ng1XInputB`).) - (ng1ControllerXInstance as any).ng1XOutputB('bar8'); - $digest(adapter); - tick(); + // Emit from `ng1XOutputB`. + // (Should propagate upwards to `ng1ADataB`, but not downwards, + // since `ng1XInputB` has been re-assigned (i.e. `ng2ADataB !== ng1XInputB`).) + (ng1ControllerXInstance as any).ng1XOutputB('bar8'); + $digest(adapter); + tick(); - expect(multiTrim(document.body.textContent)) - .toBe('ng2A(foo7, bar8, baz6) | ng1X(foo7, bar4, baz6) | ng2B(foo7, baz6)'); + expect(multiTrim(document.body.textContent)) + .toBe('ng2A(foo7, bar8, baz6) | ng1X(foo7, bar4, baz6) | ng2B(foo7, baz6)'); - // Update `ng2ADataA`/`ng2ADataB`/`ng2ADataC`. - // (Should propagate everywhere.) - ng2ComponentAInstance.ng2ADataA = {value: 'foo9'}; - ng2ComponentAInstance.ng2ADataB = {value: 'bar9'}; - ng2ComponentAInstance.ng2ADataC = {value: 'baz9'}; - $digest(adapter); - tick(); + // Update `ng2ADataA`/`ng2ADataB`/`ng2ADataC`. + // (Should propagate everywhere.) + ng2ComponentAInstance.ng2ADataA = {value: 'foo9'}; + ng2ComponentAInstance.ng2ADataB = {value: 'bar9'}; + ng2ComponentAInstance.ng2ADataC = {value: 'baz9'}; + $digest(adapter); + tick(); - expect(multiTrim(document.body.textContent)) - .toBe('ng2A(foo9, bar9, baz9) | ng1X(foo9, bar9, baz9) | ng2B(foo9, baz9)'); - }); - })); + expect(multiTrim(document.body.textContent)) + .toBe('ng2A(foo9, bar9, baz9) | ng1X(foo9, bar9, baz9) | ng2B(foo9, baz9)'); + }); + })); it('should support ng2 > ng1 > ng2 > ng1 (with `require`)', async(() => { // Define `ng1Component`