test(ivy): add more test for content projection with ngIf / ngFor (#27705)

PR Close #27705
This commit is contained in:
Pawel Kozlowski 2018-12-17 15:26:46 +01:00 committed by Miško Hevery
parent 94f17e9038
commit d132baede3
1 changed files with 118 additions and 6 deletions

View File

@ -9,10 +9,10 @@
import {SelectorFlags} from '@angular/core/src/render3/interfaces/projection'; import {SelectorFlags} from '@angular/core/src/render3/interfaces/projection';
import {AttributeMarker, detectChanges} from '../../src/render3/index'; import {AttributeMarker, detectChanges} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, projection, projectionDef, template, text} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, projection, projectionDef, template, text, textBinding, interpolation1} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition'; import {RenderFlags} from '../../src/render3/interfaces/definition';
import {NgIf} from './common_with_def'; import {NgIf, NgForOf} from './common_with_def';
import {ComponentFixture, createComponent, getDirectiveOnNode, renderComponent, toHtml} from './render_util'; import {ComponentFixture, createComponent, getDirectiveOnNode, renderComponent, toHtml} from './render_util';
describe('content projection', () => { describe('content projection', () => {
@ -45,7 +45,7 @@ describe('content projection', () => {
expect(toHtml(parent)).toEqual('<child><div>content</div></child>'); expect(toHtml(parent)).toEqual('<child><div>content</div></child>');
}); });
it('should project content when root.', () => { it('should project content when <ng-content> is at a template root', () => {
/** <ng-content></ng-content> */ /** <ng-content></ng-content> */
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) { const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
@ -824,7 +824,6 @@ describe('content projection', () => {
function IfTemplate(rf1: RenderFlags, ctx: any) { function IfTemplate(rf1: RenderFlags, ctx: any) {
if (rf1 & RenderFlags.Create) { if (rf1 & RenderFlags.Create) {
projectionDef();
projection(0); projection(0);
} }
} }
@ -889,7 +888,6 @@ describe('content projection', () => {
function IfTemplate(rf: RenderFlags, ctx: any) { function IfTemplate(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
projectionDef();
projection(0); projection(0);
} }
} }
@ -931,6 +929,74 @@ describe('content projection', () => {
expect(fixture.html).toEqual('<child>Before-<div>A</div>Some text-After</child>'); expect(fixture.html).toEqual('<child>Before-<div>A</div>Some text-After</child>');
}); });
it('should project into dynamic views with specific selectors', () => {
/**
* <ng-content></ng-content>
* Before-
* <ng-template [ngIf]="showing">
* <ng-content select="div"></ng-content>
* </ng-template>
* -After
*/
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef([[['div']]], ['div']);
projection(0);
text(1, 'Before-');
template(2, IfTemplate, 1, 0, '', [AttributeMarker.SelectOnly, 'ngIf']);
text(3, '-After');
}
if (rf & RenderFlags.Update) {
elementProperty(2, 'ngIf', bind(ctx.showing));
}
}, 4, 1, [NgIf]);
function IfTemplate(rf1: RenderFlags) {
if (rf1 & RenderFlags.Create) {
projection(0, 1);
}
}
let child: {showing: boolean};
/**
* <child>
* <div>A</div>
* <span>B</span>
* </child>
*/
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
elementStart(1, 'div');
{ text(2, 'A'); }
elementEnd();
elementStart(3, 'span');
{ text(4, 'B'); }
elementEnd();
}
elementEnd();
// testing
child = getDirectiveOnNode(0);
}
}, 5, 0, [Child]);
const fixture = new ComponentFixture(App);
child !.showing = true;
fixture.update();
expect(fixture.html).toEqual('<child><span>B</span>Before-<div>A</div>-After</child>');
child !.showing = false;
fixture.update();
expect(fixture.html).toEqual('<child><span>B</span>Before--After</child>');
child !.showing = true;
fixture.update();
expect(fixture.html).toEqual('<child><span>B</span>Before-<div>A</div>-After</child>');
});
it('should project nodes into the last ng-content', () => { it('should project nodes into the last ng-content', () => {
/** /**
* <div><ng-content></ng-content></div> * <div><ng-content></ng-content></div>
@ -1027,6 +1093,52 @@ describe('content projection', () => {
expect(toHtml(parent)).toEqual('<child><div>content</div></child>'); expect(toHtml(parent)).toEqual('<child><div>content</div></child>');
}); });
// https://stackblitz.com/edit/angular-ceqmnw?file=src%2Fapp%2Fapp.component.ts
it('should project nodes into the last ng-content unrolled by ngFor', () => {
const items = [1, 2];
/**
<div *ngFor="let item of [1, 2]; let index = index">
({{index}}): <ng-content></ng-content>
</div>
*/
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef();
{ template(0, ForTemplate, 3, 1, undefined, ['ngForOf', '']); }
}
if (rf & RenderFlags.Update) {
elementProperty(0, 'ngForOf', bind(items));
}
}, 1, 1, [NgForOf]);
function ForTemplate(rf1: RenderFlags, ctx: {index: number}) {
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div');
text(1);
projection(2);
elementEnd();
}
if (rf1 & RenderFlags.Update) {
textBinding(1, interpolation1('(', ctx.index, '):'));
}
}
/**
* <child>content</child>
*/
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{ text(1, 'content'); }
elementEnd();
}
}, 2, 0, [Child]);
const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child><div>(0):</div><div>(1):content</div></child>');
});
it('should project with multiple instances of a component with projection', () => { it('should project with multiple instances of a component with projection', () => {
const ProjectionComp = createComponent('projection-comp', function(rf: RenderFlags, ctx: any) { const ProjectionComp = createComponent('projection-comp', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {