From 6feef368f6611e2780f4f56599fe7394a1cfcd71 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Fri, 21 Dec 2018 10:05:31 +0000 Subject: [PATCH] test(ivy): add tests for component factory projectable node corner cases (#27791) In some cases ivy expects projectable nodes to be passed in a different order to ViewEngine. Specifically, ivy expects the catch-all ("*") to be at index 0, whereas ViewEngine expects it to be at its position at which it was parsed in the template. This commit adds one test that breaks under ivy and others that just describe more accurately what happens in corner cases. PR Close #27791 --- packages/compiler/test/aot/compiler_spec.ts | 11 ++++-- .../linker/projection_integration_spec.ts | 38 ++++++++++++++++++- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/packages/compiler/test/aot/compiler_spec.ts b/packages/compiler/test/aot/compiler_spec.ts index 9d020e581c..fd30a6d1a9 100644 --- a/packages/compiler/test/aot/compiler_spec.ts +++ b/packages/compiler/test/aot/compiler_spec.ts @@ -422,7 +422,12 @@ describe('compiler (unbundled Angular)', () => { @Component({ selector: 'my-comp', - template: '' + template: + '' + + '' + + '' + + '' + + '' }) export class MyComp { @Input('aInputName') @@ -449,8 +454,8 @@ describe('compiler (unbundled Angular)', () => { expect(createComponentFactoryCall).toContain(`{aInputProp:'aInputName'}`); // outputs expect(createComponentFactoryCall).toContain(`{aOutputProp:'aOutputName'}`); - // ngContentSelectors - expect(createComponentFactoryCall).toContain(`['*','child']`); + // ngContentSelectors - note that the catch-all doesn't have to appear at the start + expect(createComponentFactoryCall).toContain(`['child1','*','child2','child3','child1']`); }); }); diff --git a/packages/core/test/linker/projection_integration_spec.ts b/packages/core/test/linker/projection_integration_spec.ts index 9ef90d3195..1789efccb7 100644 --- a/packages/core/test/linker/projection_integration_spec.ts +++ b/packages/core/test/linker/projection_integration_spec.ts @@ -6,12 +6,12 @@ * found in the LICENSE file at https://angular.io/license */ -import {Component, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, Injector, Input, NgModule, OnInit, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation} from '@angular/core'; +import {Component, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, Injector, Input, NO_ERRORS_SCHEMA, NgModule, OnInit, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {By} from '@angular/platform-browser/src/dom/debug/by'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {expect} from '@angular/platform-browser/testing/src/matchers'; -import {fixmeIvy} from '@angular/private/testing'; +import {fixmeIvy, modifiedInIvy} from '@angular/private/testing'; describe('projection', () => { beforeEach(() => TestBed.configureTestingModule({declarations: [MainComp, OtherComp, Simple]})); @@ -111,6 +111,40 @@ describe('projection', () => { expect(main.nativeElement).toHaveText('(A, BC)'); }); + modifiedInIvy( + 'FW-886: `projectableNodes` passed to a componentFactory should be in the order of declaration') + .it('should support passing projectable nodes via factory function', () => { + + @Component({ + selector: 'multiple-content-tags', + template: '(, )', + }) + class MultipleContentTagsComponent { + } + + @NgModule({ + declarations: [MultipleContentTagsComponent], + entryComponents: [MultipleContentTagsComponent], + schemas: [NO_ERRORS_SCHEMA], + }) + class MyModule { + } + + TestBed.configureTestingModule({imports: [MyModule]}); + const injector: Injector = TestBed.get(Injector); + + const componentFactoryResolver: ComponentFactoryResolver = + injector.get(ComponentFactoryResolver); + const componentFactory = + componentFactoryResolver.resolveComponentFactory(MultipleContentTagsComponent); + expect(componentFactory.ngContentSelectors).toEqual(['h1', '*']); + + const nodeOne = getDOM().createTextNode('one'); + const nodeTwo = getDOM().createTextNode('two'); + const component = componentFactory.create(injector, [[nodeOne], [nodeTwo]]); + expect(component.location.nativeElement).toHaveText('(one, two)'); + }); + it('should redistribute only direct children', () => { TestBed.configureTestingModule({declarations: [MultipleContentTagsComponent]}); TestBed.overrideComponent(MainComp, {