diff --git a/packages/core/test/acceptance/query_spec.ts b/packages/core/test/acceptance/query_spec.ts index 3a260bfce7..c269578e39 100644 --- a/packages/core/test/acceptance/query_spec.ts +++ b/packages/core/test/acceptance/query_spec.ts @@ -6,8 +6,10 @@ * found in the LICENSE file at https://angular.io/license */ -import {Component, ContentChild, ContentChildren, Directive, ElementRef, Input, QueryList, TemplateRef, Type, ViewChild, ViewChildren} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {Component, ContentChild, ContentChildren, Directive, ElementRef, Input, QueryList, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core'; import {TestBed} from '@angular/core/testing'; +import {By} from '@angular/platform-browser'; import {expect} from '@angular/platform-browser/testing/src/matchers'; import {onlyInIvy} from '@angular/private/testing'; @@ -601,6 +603,44 @@ describe('query logic', () => { expect(fixture.componentInstance.subComp.foo.length).toBe(2); }); + it('should match shallow content queries in views inserted / removed by ngIf', () => { + @Component({ + selector: 'test-comp', + template: ` + +
+
+ ` + }) + class TestComponent { + showing = false; + } + + @Component({ + selector: 'shallow-comp', + template: '', + }) + class ShallowComp { + @ContentChildren('foo', {descendants: false}) foos !: QueryList; + } + + TestBed.configureTestingModule( + {declarations: [TestComponent, ShallowComp], imports: [CommonModule]}); + const fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + + const shallowComp = fixture.debugElement.query(By.directive(ShallowComp)).componentInstance; + const queryList = shallowComp !.foos; + expect(queryList.length).toBe(0); + + fixture.componentInstance.showing = true; + fixture.detectChanges(); + expect(queryList.length).toBe(1); + + fixture.componentInstance.showing = false; + fixture.detectChanges(); + expect(queryList.length).toBe(0); + }); }); // Some root components may have ContentChildren queries if they are also @@ -665,6 +705,253 @@ describe('query logic', () => { }); + describe('view boundaries', () => { + + describe('ViewContainerRef', () => { + + @Directive({selector: '[vc]', exportAs: 'vc'}) + class ViewContainerManipulatorDirective { + constructor(private _vcRef: ViewContainerRef) {} + + insertTpl(tpl: TemplateRef<{}>, ctx: {}, idx?: number) { + this._vcRef.createEmbeddedView(tpl, ctx, idx); + } + + remove(index?: number) { this._vcRef.remove(index); } + } + + it('should report results in views inserted / removed by ngIf', () => { + @Component({ + selector: 'test-comp', + template: ` + +
+
+ ` + }) + class TestComponent { + value: boolean = false; + @ViewChildren('foo') query !: QueryList; + } + + TestBed.configureTestingModule({declarations: [TestComponent]}); + + const fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + + const queryList = fixture.componentInstance.query; + expect(queryList.length).toBe(0); + + fixture.componentInstance.value = true; + fixture.detectChanges(); + expect(queryList.length).toBe(1); + + fixture.componentInstance.value = false; + fixture.detectChanges(); + expect(queryList.length).toBe(0); + }); + + it('should report results in views inserted / removed by ngFor', () => { + @Component({ + selector: 'test-comp', + template: ` + +
+
+ `, + }) + class TestComponent { + value: string[]|undefined; + @ViewChildren('foo') query !: QueryList; + } + + TestBed.configureTestingModule({declarations: [TestComponent]}); + const fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + + const queryList = fixture.componentInstance.query; + expect(queryList.length).toBe(0); + + fixture.componentInstance.value = ['a', 'b', 'c']; + fixture.detectChanges(); + expect(queryList.length).toBe(3); + + // Remove the "b" element from the value. + fixture.componentInstance.value.splice(1, 1); + fixture.detectChanges(); + expect(queryList.length).toBe(2); + + // make sure that the "b" element has been removed from query results + expect(queryList.first.nativeElement.id).toBe('a'); + expect(queryList.last.nativeElement.id).toBe('c'); + }); + + // https://stackblitz.com/edit/angular-rrmmuf?file=src/app/app.component.ts + it('should report results when different instances of TemplateRef are inserted into one ViewContainerRefs', + () => { + @Component({ + selector: 'test-comp', + template: ` + +
+
+ +
+ + +
+
+ + + `, + }) + class TestComponent { + @ViewChild(ViewContainerManipulatorDirective) vc !: ViewContainerManipulatorDirective; + @ViewChild('tpl1') tpl1 !: TemplateRef; + @ViewChild('tpl2') tpl2 !: TemplateRef; + @ViewChildren('foo') query !: QueryList; + } + + TestBed.configureTestingModule( + {declarations: [ViewContainerManipulatorDirective, TestComponent]}); + const fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + + const queryList = fixture.componentInstance.query; + const {tpl1, tpl2, vc} = fixture.componentInstance; + + expect(queryList.length).toBe(1); + expect(queryList.first.nativeElement.getAttribute('id')).toBe('middle'); + + vc.insertTpl(tpl1 !, {idx: 0}, 0); + vc.insertTpl(tpl2 !, {idx: 1}, 1); + fixture.detectChanges(); + + expect(queryList.length).toBe(3); + let qListArr = queryList.toArray(); + expect(qListArr[0].nativeElement.getAttribute('id')).toBe('foo1_0'); + expect(qListArr[1].nativeElement.getAttribute('id')).toBe('middle'); + expect(qListArr[2].nativeElement.getAttribute('id')).toBe('foo2_1'); + + vc.insertTpl(tpl1 !, {idx: 1}, 1); + fixture.detectChanges(); + + expect(queryList.length).toBe(4); + qListArr = queryList.toArray(); + expect(qListArr[0].nativeElement.getAttribute('id')).toBe('foo1_0'); + expect(qListArr[1].nativeElement.getAttribute('id')).toBe('foo1_1'); + expect(qListArr[2].nativeElement.getAttribute('id')).toBe('middle'); + expect(qListArr[3].nativeElement.getAttribute('id')).toBe('foo2_1'); + + vc.remove(1); + fixture.detectChanges(); + + expect(queryList.length).toBe(3); + qListArr = queryList.toArray(); + expect(qListArr[0].nativeElement.getAttribute('id')).toBe('foo1_0'); + expect(qListArr[1].nativeElement.getAttribute('id')).toBe('middle'); + expect(qListArr[2].nativeElement.getAttribute('id')).toBe('foo2_1'); + + vc.remove(1); + fixture.detectChanges(); + + expect(queryList.length).toBe(2); + qListArr = queryList.toArray(); + expect(qListArr[0].nativeElement.getAttribute('id')).toBe('foo1_0'); + expect(qListArr[1].nativeElement.getAttribute('id')).toBe('middle'); + }); + + // https://stackblitz.com/edit/angular-7vvo9j?file=src%2Fapp%2Fapp.component.ts + // https://stackblitz.com/edit/angular-xzwp6n + onlyInIvy('FW-1318: QueryList entries are ordered differently in Ivy.') + .it('should report results when the same TemplateRef is inserted into different ViewContainerRefs', + () => { + @Component({ + selector: 'test-comp', + template: ` + +
+
+ + + + `, + }) + class TestComponent { + @ViewChild('tpl') tpl !: TemplateRef; + @ViewChild('vi0') vi0 !: ViewContainerManipulatorDirective; + @ViewChild('vi1') vi1 !: ViewContainerManipulatorDirective; + @ViewChildren('foo') query !: QueryList; + } + + TestBed.configureTestingModule( + {declarations: [ViewContainerManipulatorDirective, TestComponent]}); + const fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + + const queryList = fixture.componentInstance.query; + const {tpl, vi0, vi1} = fixture.componentInstance; + + expect(queryList.length).toBe(0); + + vi0.insertTpl(tpl !, {idx: 0, container_idx: 0}, 0); + vi1.insertTpl(tpl !, {idx: 0, container_idx: 1}, 0); + fixture.detectChanges(); + + expect(queryList.length).toBe(2); + let qListArr = queryList.toArray(); + expect(qListArr[0].nativeElement.getAttribute('id')).toBe('foo_1_0'); + expect(qListArr[1].nativeElement.getAttribute('id')).toBe('foo_0_0'); + + vi0.remove(); + fixture.detectChanges(); + + expect(queryList.length).toBe(1); + qListArr = queryList.toArray(); + expect(qListArr[0].nativeElement.getAttribute('id')).toBe('foo_1_0'); + + vi1.remove(); + fixture.detectChanges(); + expect(queryList.length).toBe(0); + }); + + // https://stackblitz.com/edit/angular-wpd6gv?file=src%2Fapp%2Fapp.component.ts + it('should report results from views inserted in a lifecycle hook', () => { + @Component({ + selector: 'my-app', + template: ` + + + + + + `, + }) + class MyApp { + show = false; + @ViewChildren('foo') query !: QueryList; + } + + TestBed.configureTestingModule({declarations: [MyApp], imports: [CommonModule]}); + const fixture = TestBed.createComponent(MyApp); + fixture.detectChanges(); + + const queryList = fixture.componentInstance.query; + expect(queryList.length).toBe(0); + + fixture.componentInstance.show = true; + fixture.detectChanges(); + expect(queryList.length).toBe(1); + expect(queryList.first.nativeElement.id).toBe('from_tpl'); + + fixture.componentInstance.show = false; + fixture.detectChanges(); + expect(queryList.length).toBe(0); + }); + + }); + }); + }); function initWithTemplate(compType: Type, template: string) { diff --git a/packages/core/test/render3/query_spec.ts b/packages/core/test/render3/query_spec.ts index 033fc2ea72..0ee0ff8859 100644 --- a/packages/core/test/render3/query_spec.ts +++ b/packages/core/test/render3/query_spec.ts @@ -6,19 +6,17 @@ * found in the LICENSE file at https://angular.io/license */ -import {NgForOfContext} from '@angular/common'; import {ElementRef, QueryList, TemplateRef, ViewContainerRef} from '@angular/core'; import {EventEmitter} from '../..'; import {AttributeMarker, detectChanges, ΔProvidersFeature, ΔdefineComponent, ΔdefineDirective} from '../../src/render3/index'; -import {Δbind, Δcontainer, ΔcontainerRefreshEnd, ΔcontainerRefreshStart, ΔdirectiveInject, Δelement, ΔelementContainerEnd, ΔelementContainerStart, ΔelementEnd, ΔelementProperty, ΔelementStart, ΔembeddedViewEnd, ΔembeddedViewStart, Δload, Δreference, Δtemplate, Δtext} from '../../src/render3/instructions/all'; +import {Δcontainer, ΔcontainerRefreshEnd, ΔcontainerRefreshStart, ΔdirectiveInject, Δelement, ΔelementContainerEnd, ΔelementContainerStart, ΔelementEnd, ΔelementStart, ΔembeddedViewEnd, ΔembeddedViewStart, Δload, Δtemplate, Δtext} from '../../src/render3/instructions/all'; import {RenderFlags} from '../../src/render3/interfaces/definition'; import {query, ΔcontentQuery, ΔloadContentQuery, ΔloadViewQuery, ΔqueryRefresh, ΔviewQuery} from '../../src/render3/query'; import {getLView} from '../../src/render3/state'; import {getNativeByIndex} from '../../src/render3/util/view_utils'; import {ΔtemplateRefExtractor} from '../../src/render3/view_engine_compatibility_prebound'; -import {NgForOf, NgIf, NgTemplateOutlet} from './common_with_def'; import {ComponentFixture, TemplateFixture, createComponent, createDirective, getDirectiveOnNode, renderComponent} from './render_util'; @@ -1346,412 +1344,6 @@ describe('query', () => { describe('view boundaries', () => { - describe('ViewContainerRef', () => { - - let directiveInstances: ViewContainerManipulatorDirective[] = []; - - class ViewContainerManipulatorDirective { - static ngDirectiveDef = ΔdefineDirective({ - type: ViewContainerManipulatorDirective, - selectors: [['', 'vc', '']], - factory: () => { - const directiveInstance = - new ViewContainerManipulatorDirective(ΔdirectiveInject(ViewContainerRef as any)); - directiveInstances.push(directiveInstance); - return directiveInstance; - } - }); - - constructor(private _vcRef: ViewContainerRef) {} - - insertTpl(tpl: TemplateRef<{}>, ctx: {}, idx?: number) { - this._vcRef.createEmbeddedView(tpl, ctx, idx); - } - - remove(index?: number) { this._vcRef.remove(index); } - } - - beforeEach(() => { directiveInstances = []; }); - - it('should report results in views inserted / removed by ngIf', () => { - - function Cmpt_Template_1(rf: RenderFlags, ctx1: any) { - if (rf & RenderFlags.Create) { - Δelement(0, 'div', null, ['foo', '']); - } - } - - /** - * - *
- *
- * class Cmpt { - * @ViewChildren('foo') query; - * } - */ - const Cmpt = createComponent( - 'cmpt', - function(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - Δtemplate( - 0, Cmpt_Template_1, 2, 0, 'ng-template', [AttributeMarker.Bindings, 'ngIf']); - } - if (rf & RenderFlags.Update) { - ΔelementProperty(0, 'ngIf', Δbind(ctx.value)); - } - }, - 2, 1, [NgIf], [], - function(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - ΔviewQuery(['foo'], true, null); - } - if (rf & RenderFlags.Update) { - let tmp: any; - ΔqueryRefresh(tmp = ΔloadViewQuery>()) && - (ctx.query = tmp as QueryList); - } - }); - - const fixture = new ComponentFixture(Cmpt); - const qList = fixture.component.query; - expect(qList.length).toBe(0); - - fixture.component.value = true; - fixture.update(); - expect(qList.length).toBe(1); - - fixture.component.value = false; - fixture.update(); - expect(qList.length).toBe(0); - }); - - it('should report results in views inserted / removed by ngFor', () => { - - function Cmpt_Template_1(rf1: RenderFlags, row: NgForOfContext) { - if (rf1 & RenderFlags.Create) { - Δelement(0, 'div', null, ['foo', '']); - } - if (rf1 & RenderFlags.Update) { - ΔelementProperty(0, 'id', Δbind(row.$implicit)); - } - } - - /** - * - *
- *
- * class Cmpt { - * @ViewChildren('foo') query; - * } - */ - class Cmpt { - // TODO(issue/24571): remove '!'. - value !: string[]; - query: any; - static ngComponentDef = ΔdefineComponent({ - type: Cmpt, - factory: () => new Cmpt(), - selectors: [['my-app']], - consts: 2, - vars: 1, - template: function(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - Δtemplate(0, Cmpt_Template_1, 2, 1, 'ng-template', ['ngForOf', '']); - } - if (rf & RenderFlags.Update) { - ΔelementProperty(0, 'ngForOf', Δbind(ctx.value)); - } - }, - viewQuery: function(rf: RenderFlags, ctx: Cmpt) { - let tmp: any; - if (rf & RenderFlags.Create) { - ΔviewQuery(['foo'], true, null); - } - if (rf & RenderFlags.Update) { - ΔqueryRefresh(tmp = ΔloadViewQuery>()) && - (ctx.query = tmp as QueryList); - } - }, - directives: () => [NgForOf] - }); - } - - const fixture = new ComponentFixture(Cmpt); - const qList = fixture.component.query; - expect(qList.length).toBe(0); - - fixture.component.value = ['a', 'b', 'c']; - fixture.update(); - expect(qList.length).toBe(3); - - fixture.component.value.splice(1, 1); // remove "b" - fixture.update(); - expect(qList.length).toBe(2); - - // make sure that a proper element was removed from query results - expect(qList.first.nativeElement.id).toBe('a'); - expect(qList.last.nativeElement.id).toBe('c'); - - }); - - // https://stackblitz.com/edit/angular-rrmmuf?file=src/app/app.component.ts - it('should report results when different instances of TemplateRef are inserted into one ViewContainerRefs', - () => { - let tpl1: TemplateRef<{}>; - let tpl2: TemplateRef<{}>; - - function Cmpt_Template_1(rf: RenderFlags, ctx: {idx: number}) { - if (rf & RenderFlags.Create) { - Δelement(0, 'div', null, ['foo', '']); - } - if (rf & RenderFlags.Update) { - ΔelementProperty(0, 'id', Δbind('foo1_' + ctx.idx)); - } - } - - function Cmpt_Template_5(rf: RenderFlags, ctx: {idx: number}) { - if (rf & RenderFlags.Create) { - Δelement(0, 'div', null, ['foo', '']); - } - if (rf & RenderFlags.Update) { - ΔelementProperty(0, 'id', Δbind('foo2_' + ctx.idx)); - } - } - - /** - * - *
- *
- * - *
- * - * - *
- *
- * - * - */ - const Cmpt = createComponent( - 'cmpt', - function(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - Δtemplate( - 0, Cmpt_Template_1, 2, 1, 'ng-template', null, ['tpl1', ''], - ΔtemplateRefExtractor); - Δelement(2, 'div', ['id', 'middle'], ['foo', '']); - Δtemplate( - 4, Cmpt_Template_5, 2, 1, 'ng-template', null, ['tpl2', ''], - ΔtemplateRefExtractor); - Δtemplate(6, null, 0, 0, 'ng-template', [AttributeMarker.Bindings, 'vc']); - } - - if (rf & RenderFlags.Update) { - tpl1 = Δreference(1); - tpl2 = Δreference(5); - } - - }, - 8, 0, [ViewContainerManipulatorDirective], [], - function(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - ΔviewQuery(['foo'], true, null); - } - if (rf & RenderFlags.Update) { - let tmp: any; - ΔqueryRefresh(tmp = ΔloadViewQuery>()) && - (ctx.query = tmp as QueryList); - } - }); - - const fixture = new ComponentFixture(Cmpt); - const qList = fixture.component.query; - - expect(qList.length).toBe(1); - expect(qList.first.nativeElement.getAttribute('id')).toBe('middle'); - - directiveInstances[0].insertTpl(tpl1 !, {idx: 0}, 0); - directiveInstances[0].insertTpl(tpl2 !, {idx: 1}, 1); - fixture.update(); - expect(qList.length).toBe(3); - let qListArr = qList.toArray(); - expect(qListArr[0].nativeElement.getAttribute('id')).toBe('foo1_0'); - expect(qListArr[1].nativeElement.getAttribute('id')).toBe('middle'); - expect(qListArr[2].nativeElement.getAttribute('id')).toBe('foo2_1'); - - directiveInstances[0].insertTpl(tpl1 !, {idx: 1}, 1); - fixture.update(); - expect(qList.length).toBe(4); - qListArr = qList.toArray(); - expect(qListArr[0].nativeElement.getAttribute('id')).toBe('foo1_0'); - expect(qListArr[1].nativeElement.getAttribute('id')).toBe('foo1_1'); - expect(qListArr[2].nativeElement.getAttribute('id')).toBe('middle'); - expect(qListArr[3].nativeElement.getAttribute('id')).toBe('foo2_1'); - - directiveInstances[0].remove(1); - fixture.update(); - expect(qList.length).toBe(3); - qListArr = qList.toArray(); - expect(qListArr[0].nativeElement.getAttribute('id')).toBe('foo1_0'); - expect(qListArr[1].nativeElement.getAttribute('id')).toBe('middle'); - expect(qListArr[2].nativeElement.getAttribute('id')).toBe('foo2_1'); - - directiveInstances[0].remove(1); - fixture.update(); - expect(qList.length).toBe(2); - qListArr = qList.toArray(); - expect(qListArr[0].nativeElement.getAttribute('id')).toBe('foo1_0'); - expect(qListArr[1].nativeElement.getAttribute('id')).toBe('middle'); - }); - - // https://stackblitz.com/edit/angular-7vvo9j?file=src%2Fapp%2Fapp.component.ts - // https://stackblitz.com/edit/angular-xzwp6n - it('should report results when the same TemplateRef is inserted into different ViewContainerRefs', - () => { - let tpl: TemplateRef<{}>; - - function Cmpt_Template_1(rf: RenderFlags, ctx: {idx: number, container_idx: number}) { - if (rf & RenderFlags.Create) { - Δelement(0, 'div', null, ['foo', '']); - } - if (rf & RenderFlags.Update) { - ΔelementProperty(0, 'id', Δbind('foo_' + ctx.container_idx + '_' + ctx.idx)); - } - } - - /** - * - *
- *
- * - * - * - */ - class Cmpt { - query: any; - static ngComponentDef = ΔdefineComponent({ - type: Cmpt, - factory: () => new Cmpt(), - selectors: [['my-app']], - consts: 4, - vars: 0, - template: function(rf: RenderFlags, ctx: any) { - let tmp: any; - if (rf & RenderFlags.Create) { - Δtemplate( - 0, Cmpt_Template_1, 2, 1, 'ng-template', [], ['tpl', ''], - ΔtemplateRefExtractor); - Δtemplate(2, null, 0, 0, 'ng-template', [AttributeMarker.Bindings, 'vc']); - Δtemplate(3, null, 0, 0, 'ng-template', [AttributeMarker.Bindings, 'vc']); - } - - if (rf & RenderFlags.Update) { - tpl = Δreference(1); - } - - }, - viewQuery: (rf: RenderFlags, cmpt: Cmpt) => { - let tmp: any; - if (rf & RenderFlags.Create) { - ΔviewQuery(['foo'], true, null); - } - if (rf & RenderFlags.Update) { - ΔqueryRefresh(tmp = ΔloadViewQuery>()) && - (cmpt.query = tmp as QueryList); - } - }, - directives: () => [ViewContainerManipulatorDirective], - }); - } - const fixture = new ComponentFixture(Cmpt); - const qList = fixture.component.query; - - expect(qList.length).toBe(0); - - directiveInstances[0].insertTpl(tpl !, {idx: 0, container_idx: 0}, 0); - directiveInstances[1].insertTpl(tpl !, {idx: 0, container_idx: 1}, 0); - fixture.update(); - expect(qList.length).toBe(2); - let qListArr = qList.toArray(); - expect(qListArr[0].nativeElement.getAttribute('id')).toBe('foo_1_0'); - expect(qListArr[1].nativeElement.getAttribute('id')).toBe('foo_0_0'); - - directiveInstances[0].remove(); - fixture.update(); - expect(qList.length).toBe(1); - qListArr = qList.toArray(); - expect(qListArr[0].nativeElement.getAttribute('id')).toBe('foo_1_0'); - - directiveInstances[1].remove(); - fixture.update(); - expect(qList.length).toBe(0); - }); - - // https://stackblitz.com/edit/angular-wpd6gv?file=src%2Fapp%2Fapp.component.ts - it('should report results from views inserted in a lifecycle hook', () => { - - function MyApp_Template_1(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - Δelement(0, 'span', ['id', 'from_tpl'], ['foo', '']); - } - } - - class MyApp { - show = false; - query: any; - static ngComponentDef = ΔdefineComponent({ - type: MyApp, - factory: () => new MyApp(), - selectors: [['my-app']], - consts: 4, - vars: 1, - /** - * - * - */ - template: (rf: RenderFlags, myApp: MyApp) => { - if (rf & RenderFlags.Create) { - Δtemplate( - 0, MyApp_Template_1, 2, 0, 'ng-template', undefined, ['tpl', ''], - ΔtemplateRefExtractor); - Δtemplate( - 2, null, 0, 0, 'ng-template', [AttributeMarker.Bindings, 'ngTemplateOutlet']); - } - if (rf & RenderFlags.Update) { - const tplRef = Δreference(1); - ΔelementProperty(2, 'ngTemplateOutlet', Δbind(myApp.show ? tplRef : null)); - } - }, - directives: () => [NgTemplateOutlet], - viewQuery: (rf: RenderFlags, myApp: MyApp) => { - let tmp: any; - if (rf & RenderFlags.Create) { - ΔviewQuery(['foo'], true, null); - } - if (rf & RenderFlags.Update) { - ΔqueryRefresh(tmp = ΔloadViewQuery>()) && - (myApp.query = tmp as QueryList); - } - } - }); - } - - const fixture = new ComponentFixture(MyApp); - const qList = fixture.component.query; - - expect(qList.length).toBe(0); - - fixture.component.show = true; - fixture.update(); - expect(qList.length).toBe(1); - expect(qList.first.nativeElement.id).toBe('from_tpl'); - - fixture.component.show = false; - fixture.update(); - expect(qList.length).toBe(0); - }); - - }); - describe('JS blocks', () => { it('should report results in embedded views', () => { @@ -2233,12 +1825,8 @@ describe('query', () => { describe('content', () => { let withContentInstance: WithContentDirective|null; - let shallowCompInstance: ShallowComp|null; - beforeEach(() => { - withContentInstance = null; - shallowCompInstance = null; - }); + beforeEach(() => { withContentInstance = null; }); class WithContentDirective { // @ContentChildren('foo') @@ -2268,29 +1856,6 @@ describe('query', () => { }); } - class ShallowComp { - // @ContentChildren('foo', {descendants: false}) - foos !: QueryList; - - static ngComponentDef = ΔdefineComponent({ - type: ShallowComp, - selectors: [['shallow-comp']], - factory: () => shallowCompInstance = new ShallowComp(), - template: function(rf: RenderFlags, ctx: any) {}, - consts: 0, - vars: 0, - contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => { - if (rf & RenderFlags.Create) { - ΔcontentQuery(dirIndex, ['foo'], false, null); - } - if (rf & RenderFlags.Update) { - let tmp: any; - ΔqueryRefresh(tmp = ΔloadContentQuery()) && (ctx.foos = tmp); - } - } - }); - } - it('should support content queries for directives', () => { /** *
@@ -2381,43 +1946,6 @@ describe('query', () => { .toBe(0, `Expected content query not to match
.`); }); - it('should match shallow content queries in views inserted / removed by ngIf', () => { - function IfTemplate(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - Δelement(0, 'div', null, ['foo', '']); - } - } - - /** - * - *
- *
- */ - const AppComponent = createComponent('app-component', function(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - ΔelementStart(0, 'shallow-comp'); - { Δtemplate(1, IfTemplate, 2, 0, 'div', [AttributeMarker.Template, 'ngIf', '']); } - ΔelementEnd(); - } - if (rf & RenderFlags.Update) { - ΔelementProperty(1, 'ngIf', Δbind(ctx.showing)); - } - }, 2, 1, [ShallowComp, NgIf]); - - const fixture = new ComponentFixture(AppComponent); - const qList = shallowCompInstance !.foos; - expect(qList.length).toBe(0); - - fixture.component.showing = true; - fixture.update(); - expect(qList.length).toBe(1); - - fixture.component.showing = false; - fixture.update(); - expect(qList.length).toBe(0); - }); - - // https://stackblitz.com/edit/angular-wlenwd?file=src%2Fapp%2Fapp.component.ts it('should support view and content queries matching the same element', () => { /**