diff --git a/packages/core/test/acceptance/template_ref_spec.ts b/packages/core/test/acceptance/template_ref_spec.ts
index 981cc43bac..7184479bad 100644
--- a/packages/core/test/acceptance/template_ref_spec.ts
+++ b/packages/core/test/acceptance/template_ref_spec.ts
@@ -9,6 +9,7 @@
import {Component, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core';
import {TestBed} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers';
+import {onlyInIvy} from '@angular/private/testing';
describe('TemplateRef', () => {
describe('rootNodes', () => {
@@ -52,6 +53,117 @@ describe('TemplateRef', () => {
expect(rootNodeTextContent).toEqual(['Header', 'Item one', 'Item two']);
});
- });
+ it('should return root render nodes for an embedded view instance', () => {
+ @Component({
+ template: `
+
+
+ some text
+
+
+ `
+ })
+ class App {
+ @ViewChild('templateRef')
+ templateRef !: TemplateRef;
+ }
+
+ TestBed.configureTestingModule({
+ declarations: [App],
+ });
+ const fixture = TestBed.createComponent(App);
+ fixture.detectChanges();
+
+ const embeddedView = fixture.componentInstance.templateRef.createEmbeddedView({});
+ expect(embeddedView.rootNodes.length).toBe(3);
+ });
+
+ /**
+ * This is different as compared to the view engine implementation which returns a comment node
+ * in this case:
+ * https://stackblitz.com/edit/angular-uiqry6?file=src/app/app.component.ts
+ *
+ * Returning a comment node for a template ref with no nodes is wrong is fixed in Ivy.
+ */
+ onlyInIvy('Fixed: Ivy no longer adds a comment node in this case.')
+ .it('should return an empty array for embedded view with no nodes', () => {
+ @Component({
+ template: `
+
+ `
+ })
+ class App {
+ @ViewChild('templateRef')
+ templateRef !: TemplateRef;
+ }
+
+ TestBed.configureTestingModule({
+ declarations: [App],
+ });
+ const fixture = TestBed.createComponent(App);
+ fixture.detectChanges();
+
+ const embeddedView = fixture.componentInstance.templateRef.createEmbeddedView({});
+ expect(embeddedView.rootNodes.length).toBe(0);
+ });
+
+ it('should not descend into containers when retrieving root nodes', () => {
+ /**
+ * NOTE: In VE, if `SUFFIX` text node below is _not_ present, VE will add an
+ * additional `` comment, thus being slightly different than Ivy.
+ * (resulting in 1 root node in Ivy and 2 in VE).
+ */
+ @Component({
+ template: `
+ textSUFFIX
+ `
+ })
+ class App {
+ @ViewChild('templateRef')
+ templateRef !: TemplateRef;
+ }
+
+ TestBed.configureTestingModule({
+ declarations: [App],
+ });
+ const fixture = TestBed.createComponent(App);
+ fixture.detectChanges();
+
+ const embeddedView = fixture.componentInstance.templateRef.createEmbeddedView({});
+ expect(embeddedView.rootNodes.length).toBe(2);
+ expect(embeddedView.rootNodes[0].nodeType).toBe(Node.COMMENT_NODE);
+ expect(embeddedView.rootNodes[1].nodeType).toBe(Node.TEXT_NODE);
+ });
+
+ /**
+ * Contrary to containers () we _do_ descend into element containers
+ * ()
+ */
+ it('should descend into element containers when retrieving root nodes', () => {
+ @Component({
+ template: `
+
+ text
+
+ `
+ })
+ class App {
+ @ViewChild('templateRef')
+ templateRef !: TemplateRef;
+ }
+
+ TestBed.configureTestingModule({
+ declarations: [App],
+ });
+ const fixture = TestBed.createComponent(App);
+ fixture.detectChanges();
+
+ const embeddedView = fixture.componentInstance.templateRef.createEmbeddedView({});
+
+ expect(embeddedView.rootNodes.length).toBe(2);
+ expect(embeddedView.rootNodes[0].nodeType).toBe(Node.COMMENT_NODE);
+ expect(embeddedView.rootNodes[1].nodeType).toBe(Node.TEXT_NODE);
+ });
+ });
});
diff --git a/packages/core/test/render3/template_ref_spec.ts b/packages/core/test/render3/template_ref_spec.ts
deleted file mode 100644
index d5059f366e..0000000000
--- a/packages/core/test/render3/template_ref_spec.ts
+++ /dev/null
@@ -1,178 +0,0 @@
-/**
- * @license
- * Copyright Google Inc. All Rights Reserved.
- *
- * Use of this source code is governed by an MIT-style license that can be
- * found in the LICENSE file at https://angular.io/license
- */
-
-import {TemplateRef} from '@angular/core';
-
-import {AttributeMarker, RenderFlags, ΔdefineDirective} from '../../src/render3/index';
-import {Δbind, ΔdirectiveInject, Δelement, ΔelementContainerEnd, ΔelementContainerStart, ΔelementProperty, Δtemplate, Δtext} from '../../src/render3/instructions/all';
-
-import {NgIf} from './common_with_def';
-import {ComponentFixture, createComponent, getDirectiveOnNode} from './render_util';
-
-describe('TemplateRef', () => {
-
- describe('rootNodes', () => {
-
- class DirectiveWithTplRef {
- static ngDirectiveDef = ΔdefineDirective({
- type: DirectiveWithTplRef,
- selectors: [['', 'tplRef', '']],
- factory: () => new DirectiveWithTplRef(ΔdirectiveInject(TemplateRef as any))
- });
-
- // injecting a ViewContainerRef to create a dynamic container in which embedded views will be
- // created
- constructor(public tplRef: TemplateRef<{}>) {}
- }
-
- it('should return root render nodes for an embedded view instance', () => {
- let directiveWithTplRef: DirectiveWithTplRef;
-
- function embeddedTemplate(rf: RenderFlags, ctx: any) {
- if (rf & RenderFlags.Create) {
- Δelement(0, 'div');
- Δtext(1, 'some text');
- Δelement(2, 'span');
- }
- }
-
- /*
-
-
- some text
-
-
- */
- const AppComponent = createComponent('app-cmp', function(rf: RenderFlags, ctx: any) {
- if (rf & RenderFlags.Create) {
- Δtemplate(0, embeddedTemplate, 3, 0, 'ng-template', ['tplRef', '']);
- directiveWithTplRef = getDirectiveOnNode(0, 0);
- }
- }, 1, 0, [DirectiveWithTplRef]);
-
-
- const fixture = new ComponentFixture(AppComponent);
- expect(directiveWithTplRef !).toBeDefined();
-
- const viewRef = directiveWithTplRef !.tplRef.createEmbeddedView({});
- expect(viewRef.rootNodes.length).toBe(3);
- });
-
- /**
- * This is different as compared to the view engine implementation which returns a comment node
- * in this case:
- * https://stackblitz.com/edit/angular-uiqry6?file=src/app/app.component.ts
- *
- * Returning a comment node for a template ref with no nodes is wrong and should be fixed in
- * ivy.
- */
- it('should return an empty array for embedded view with no nodes', () => {
- let directiveWithTplRef: DirectiveWithTplRef;
-
- /*
-
- */
- const AppComponent = createComponent('app-cmp', function(rf: RenderFlags, ctx: any) {
- if (rf & RenderFlags.Create) {
- Δtemplate(0, () => {}, 0, 0, 'ng-template', ['tplRef', '']);
- directiveWithTplRef = getDirectiveOnNode(0, 0);
- }
- }, 1, 0, [DirectiveWithTplRef]);
-
-
- const fixture = new ComponentFixture(AppComponent);
- expect(directiveWithTplRef !).toBeDefined();
-
- const viewRef = directiveWithTplRef !.tplRef.createEmbeddedView({});
- expect(viewRef.rootNodes.length).toBe(0);
- });
-
- /**
- * This is somehow surprising but the current view engine don't descend into containers when
- * getting root nodes of an embedded view:
- * https://stackblitz.com/edit/angular-z8zev7?file=src/app/app.component.ts
- */
- it('should not descend into containers when retrieving root nodes', () => {
- let directiveWithTplRef: DirectiveWithTplRef;
-
- function ngIfTemplate(rf: RenderFlags, ctx: any) {
- if (rf & RenderFlags.Create) {
- Δtext(0, 'text');
- }
- }
-
- function embeddedTemplate(rf: RenderFlags, ctx: any) {
- if (rf & RenderFlags.Create) {
- Δtemplate(0, ngIfTemplate, 1, 0, 'ng-template', [AttributeMarker.Bindings, 'ngIf']);
- }
- if (rf & RenderFlags.Update) {
- ΔelementProperty(0, 'ngIf', Δbind(ctx.showing));
- }
- }
-
- /*
- text
- */
- const AppComponent = createComponent('app-cmp', function(rf: RenderFlags, ctx: any) {
- if (rf & RenderFlags.Create) {
- Δtemplate(0, embeddedTemplate, 1, 1, 'ng-template', ['tplRef', '']);
- directiveWithTplRef = getDirectiveOnNode(0, 0);
- }
- }, 1, 0, [DirectiveWithTplRef, NgIf]);
-
-
- const fixture = new ComponentFixture(AppComponent);
- expect(directiveWithTplRef !).toBeDefined();
-
- const viewRef = directiveWithTplRef !.tplRef.createEmbeddedView({});
-
- // assert that we've got a comment node (only!) corresponding to
- expect(viewRef.rootNodes.length).toBe(1);
- expect(viewRef.rootNodes[0].nodeType).toBe(8);
- });
-
-
- /**
- * Contrary to containers () we _do_ descend into element containers
- * ( {
- let directiveWithTplRef: DirectiveWithTplRef;
-
- function embeddedTemplate(rf: RenderFlags, ctx: any) {
- if (rf & RenderFlags.Create) {
- ΔelementContainerStart(0);
- { Δtext(1, 'text'); }
- ΔelementContainerEnd();
- }
- }
-
- /*
- text
- */
- const AppComponent = createComponent('app-cmp', function(rf: RenderFlags, ctx: any) {
- if (rf & RenderFlags.Create) {
- Δtemplate(0, embeddedTemplate, 2, 0, 'ng-template', ['tplRef', '']);
- directiveWithTplRef = getDirectiveOnNode(0, 0);
- }
- }, 1, 0, [DirectiveWithTplRef]);
-
-
- const fixture = new ComponentFixture(AppComponent);
- expect(directiveWithTplRef !).toBeDefined();
-
- const viewRef = directiveWithTplRef !.tplRef.createEmbeddedView({});
-
- expect(viewRef.rootNodes.length).toBe(2);
- expect(viewRef.rootNodes[0].nodeType)
- .toBe(8); // a comment node (only!) corresponding to
- expect(viewRef.rootNodes[1].nodeType).toBe(3); // a text node
- });
- });
-});