import { AsyncTestCompleter, beforeEach, ddescribe, describe, el, expect, iit, inject, it, xit, TestComponentBuilder, asNativeElements } from 'angular2/test_lib'; import {Injectable, Optional} from 'angular2/di'; import {QueryList} from 'angular2/core'; import {Query, ViewQuery, Component, Directive, View} from 'angular2/annotations'; import {NgIf, NgFor} from 'angular2/angular2'; import {ListWrapper, iterableToList} from 'angular2/src/facade/collection'; import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter'; export function main() { BrowserDomAdapter.makeCurrent(); describe('Query API', () => { describe("querying by directive type", () => { it('should contain all direct child directives in the light dom', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = '
' + '
' + '
' + '
' + '
'; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { view.detectChanges(); expect(asNativeElements(view.componentViewChildren)).toHaveText('2|3|'); async.done(); }); })); it('should contain all directives in the light dom when descendants flag is used', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = '
' + '
' + '
' + '
' + '
'; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { view.detectChanges(); expect(asNativeElements(view.componentViewChildren)).toHaveText('2|3|4|'); async.done(); }); })); it('should contain all directives in the light dom', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = '
' + '
' + '
'; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { view.detectChanges(); expect(asNativeElements(view.componentViewChildren)).toHaveText('2|3|'); async.done(); }); })); it('should reflect dynamically inserted directives', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = '
' + '
' + '
'; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { view.detectChanges(); expect(asNativeElements(view.componentViewChildren)).toHaveText('2|'); view.componentInstance.shouldShow = true; view.detectChanges(); expect(asNativeElements(view.componentViewChildren)).toHaveText('2|3|'); async.done(); }); })); it('should reflect moved directives', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = '
' + '
' + '
'; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { view.detectChanges(); expect(asNativeElements(view.componentViewChildren)).toHaveText('2|1d|2d|3d|'); view.componentInstance.list = ['3d', '2d']; view.detectChanges(); view.detectChanges(); expect(asNativeElements(view.componentViewChildren)).toHaveText('2|3d|2d|'); async.done(); }); })); }); describe("onChange", () => { it('should notify query on change', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = '' + '
' + '
' + '
'; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { var q = view.componentViewChildren[0].getLocal("q"); view.detectChanges(); q.query.onChange(() => { expect(q.query.first.text).toEqual("1"); expect(q.query.last.text).toEqual("2"); async.done(); }); view.componentInstance.shouldShow = true; view.detectChanges(); }); })); it("should notify child's query before notifying parent's query", inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = '' + '' + '
' + '
' + '
'; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { var q1 = view.componentViewChildren[0].getLocal("q1"); var q2 = view.componentViewChildren[0].getLocal("q2"); var firedQ2 = false; q2.query.onChange(() => { firedQ2 = true; }); q1.query.onChange(() => { expect(firedQ2).toBe(true); async.done(); }); view.detectChanges(); }); })); }); describe("querying by var binding", () => { it('should contain all the child directives in the light dom with the given var binding', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = '' + '
' + '
'; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { var q = view.componentViewChildren[0].getLocal("q"); view.componentInstance.list = ['1d', '2d']; view.detectChanges(); expect(q.query.first.text).toEqual("1d"); expect(q.query.last.text).toEqual("2d"); async.done(); }); })); it('should support querying by multiple var bindings', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = '' + '
' + '
' + '
'; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { var q = view.componentViewChildren[0].getLocal("q"); view.detectChanges(); expect(q.query.first.text).toEqual("one"); expect(q.query.last.text).toEqual("two"); async.done(); }); })); it('should reflect dynamically inserted directives', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = '' + '
' + '
'; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { var q = view.componentViewChildren[0].getLocal("q"); view.componentInstance.list = ['1d', '2d']; view.detectChanges(); view.componentInstance.list = ['2d', '1d']; view.detectChanges(); expect(q.query.last.text).toEqual("1d"); async.done(); }); })); it('should contain all the elements in the light dom with the given var binding', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = '' + '
' + '
{{item}}
' + '
' + '
'; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { var q = view.componentViewChildren[0].getLocal("q"); view.componentInstance.list = ['1d', '2d']; view.detectChanges(); expect(q.query.first.nativeElement).toHaveText("1d"); expect(q.query.last.nativeElement).toHaveText("2d"); async.done(); }); })); }); describe("querying in the view", () => { it('should contain all the elements in the view with that have the given directive', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = '
'; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { var q: NeedsViewQuery = view.componentViewChildren[0].getLocal("q"); view.detectChanges(); expect(q.query.map((d: TextDirective) => d.text)).toEqual(["1", "2", "3"]); async.done(); }); })); it('should query descendants in the view when the flag is used', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = ''; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { var q: NeedsViewQueryDesc = view.componentViewChildren[0].getLocal("q"); view.detectChanges(); expect(q.query.map((d: TextDirective) => d.text)).toEqual(["1", "2", "3", "4"]); async.done(); }); })); it('should include directive present on the host element', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = ''; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { var q: NeedsViewQuery = view.componentViewChildren[0].getLocal("q"); view.detectChanges(); expect(q.query.map((d: TextDirective) => d.text)).toEqual(["self", "1", "2", "3"]); async.done(); }); })); it('should reflect changes in the component', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = ''; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { var q: NeedsViewQueryIf = view.componentViewChildren[0].getLocal("q"); view.detectChanges(); expect(q.query.length).toBe(0); q.show = true; view.detectChanges(); expect(q.query.first.text).toEqual("1"); async.done(); }); })); /* TODO(rado): fix and reenable. it('should maintain directives in pre-order depth-first DOM order after dynamic insertion', inject([TestComponentBuilder, AsyncTestCompleter], (tcb:TestComponentBuilder, async) => { var template = ''; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { var q:NeedsViewQueryOrder = view.componentViewChildren[0].getLocal("q"); view.detectChanges(); expect(q.query.length).toBe(4); expect(q.query.first.text).toEqual("1"); expect(q.query.first.text).toEqual("4"); async.done(); }); }));*/ }); }); } @Directive({selector: '[text]', properties: ['text'], exportAs: 'textDir'}) @Injectable() class TextDirective { text: string; constructor() {} } @Component({selector: 'needs-query'}) @View({directives: [NgFor], template: '
{{dir.text}}|
'}) @Injectable() class NeedsQuery { query: QueryList; constructor(@Query(TextDirective) query: QueryList) { this.query = query; } } @Component({selector: 'needs-query-desc'}) @View({directives: [NgFor], template: '
{{dir.text}}|
'}) @Injectable() class NeedsQueryDesc { query: QueryList; constructor(@Query(TextDirective, {descendants: true}) query: QueryList) { this.query = query; } } @Component({selector: 'needs-query-by-var-binding'}) @View({directives: [], template: ''}) @Injectable() class NeedsQueryByLabel { query: QueryList; constructor(@Query("textLabel", {descendants: true}) query: QueryList) { this.query = query; } } @Component({selector: 'needs-query-by-var-bindings'}) @View({directives: [], template: ''}) @Injectable() class NeedsQueryByTwoLabels { query: QueryList; constructor(@Query("textLabel1,textLabel2", {descendants: true}) query: QueryList) { this.query = query; } } @Component({selector: 'needs-view-query'}) @View({ directives: [TextDirective], template: '
' + '
' }) @Injectable() class NeedsViewQuery { query: QueryList; constructor(@ViewQuery(TextDirective) query: QueryList) { this.query = query; } } @Component({selector: 'needs-view-query-desc'}) @View({ directives: [TextDirective], template: '
' + '
' }) @Injectable() class NeedsViewQueryDesc { query: QueryList; constructor(@ViewQuery(TextDirective, {descendants: true}) query: QueryList) { this.query = query; } } @Component({selector: 'needs-view-query-if'}) @View({directives: [NgIf, TextDirective], template: '
'}) @Injectable() class NeedsViewQueryIf { show: boolean; query: QueryList; constructor(@ViewQuery(TextDirective) query: QueryList) { this.query = query; this.show = false; } } @Component({selector: 'needs-view-query-order'}) @View({ directives: [NgFor, TextDirective], template: '
' + '
' + '
; constructor(@ViewQuery(TextDirective) query: QueryList) { this.query = query; } } @Component({selector: 'my-comp'}) @View({ directives: [ NeedsQuery, NeedsQueryDesc, NeedsQueryByLabel, NeedsQueryByTwoLabels, NeedsViewQuery, NeedsViewQueryDesc, NeedsViewQueryIf, NeedsViewQueryOrder, TextDirective, NgIf, NgFor ] }) @Injectable() class MyComp { shouldShow: boolean; list; constructor() { this.shouldShow = false; this.list = ['1d', '2d', '3d']; } }