import {
AsyncTestCompleter,
beforeEach,
ddescribe,
xdescribe,
describe,
el,
dispatchEvent,
expect,
iit,
inject,
beforeEachBindings,
it,
xit,
viewRootNodes,
TestComponentBuilder,
RootTestComponent,
inspectElement,
By
} from 'angular2/test_lib';
import {Injector} from 'angular2/di';
import {NgIf} from 'angular2/directives';
import {Component, View, LifecycleEvent} from 'angular2/annotations';
import * as viewAnn from 'angular2/src/core/annotations_impl/view';
import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader';
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
import {DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer';
import {DOM} from 'angular2/src/dom/dom_adapter';
export function main() {
describe('DynamicComponentLoader', function() {
describe("loading into a location", () => {
it('should work',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(
MyComp,
new viewAnn.View(
{template: '', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
loader.loadIntoLocation(DynamicallyLoaded, tc.elementRef, 'loc')
.then(ref => {
expect(tc.nativeElement).toHaveText("Location;DynamicallyLoaded;");
async.done();
});
});
}));
it('should return a disposable component ref',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(
MyComp,
new viewAnn.View(
{template: '', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
loader.loadIntoLocation(DynamicallyLoaded, tc.elementRef, 'loc')
.then(ref => {
ref.dispose();
expect(tc.nativeElement).toHaveText("Location;");
async.done();
});
});
}));
it('should allow to dispose even if the location has been removed',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new viewAnn.View({
template: '',
directives: [NgIf, ChildComp]
}))
.overrideView(
ChildComp,
new viewAnn.View(
{template: '', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
tc.componentInstance.ctxBoolProp = true;
tc.detectChanges();
var childCompEl = tc.query(By.css('child-cmp'));
loader.loadIntoLocation(DynamicallyLoaded, childCompEl.elementRef, 'loc')
.then(ref => {
expect(tc.nativeElement).toHaveText("Location;DynamicallyLoaded;");
tc.componentInstance.ctxBoolProp = false;
tc.detectChanges();
expect(tc.nativeElement).toHaveText("");
ref.dispose();
expect(tc.nativeElement).toHaveText("");
async.done();
});
});
}));
it('should update host properties',
inject(
[DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(
MyComp, new viewAnn.View(
{template: '', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
loader.loadIntoLocation(DynamicallyLoadedWithHostProps, tc.elementRef, 'loc')
.then(ref => {
ref.instance.id = "new value";
tc.detectChanges();
var newlyInsertedElement = DOM.childNodes(tc.nativeElement)[1];
expect((newlyInsertedElement).id).toEqual("new value");
async.done();
});
});
}));
it('should throw if the variable does not exist',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(
MyComp,
new viewAnn.View(
{template: '', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
expect(() => loader.loadIntoLocation(DynamicallyLoadedWithHostProps,
tc.elementRef, 'someUnknownVariable'))
.toThrowError('Could not find variable someUnknownVariable');
async.done();
});
}));
});
describe("loading next to a location", () => {
it('should work', inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new viewAnn.View({
template: '
',
directives: [Location]
}))
.createAsync(MyComp)
.then((tc) => {
loader.loadNextToLocation(DynamicallyLoaded, tc.elementRef)
.then(ref => {
expect(tc.nativeElement).toHaveText("Location;");
expect(DOM.nextSibling(tc.nativeElement))
.toHaveText('DynamicallyLoaded;');
async.done();
});
});
}));
it('should return a disposable component ref',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new viewAnn.View({
template: '
',
directives: [Location]
}))
.
createAsync(MyComp)
.then((tc) => {
loader.loadNextToLocation(DynamicallyLoaded, tc.elementRef)
.then(ref => {
loader.loadNextToLocation(DynamicallyLoaded2, tc.elementRef)
.then(ref2 => {
var firstSibling = DOM.nextSibling(tc.nativeElement);
var secondSibling = DOM.nextSibling(firstSibling);
expect(tc.nativeElement).toHaveText("Location;");
expect(firstSibling).toHaveText("DynamicallyLoaded;");
expect(secondSibling).toHaveText("DynamicallyLoaded2;");
ref2.dispose();
firstSibling = DOM.nextSibling(tc.nativeElement);
secondSibling = DOM.nextSibling(firstSibling);
expect(secondSibling).toBeNull();
async.done();
});
});
});
}));
it('should update host properties',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new viewAnn.View({
template: '
',
directives: [Location]
}))
.createAsync(MyComp)
.then((tc) => {
loader.loadNextToLocation(DynamicallyLoadedWithHostProps, tc.elementRef)
.then(ref => {
ref.instance.id = "new value";
tc.detectChanges();
var newlyInsertedElement = DOM.nextSibling(tc.nativeElement);
expect((newlyInsertedElement).id).toEqual("new value");
async.done();
});
});
}));
});
describe('loadAsRoot', () => {
it('should allow to create, update and destroy components',
inject([AsyncTestCompleter, DynamicComponentLoader, DOCUMENT_TOKEN, Injector],
(async, loader, doc, injector) => {
var rootEl = el('');
DOM.appendChild(doc.body, rootEl);
loader.loadAsRoot(ChildComp, null, injector)
.then((componentRef) => {
var el = new RootTestComponent(componentRef);
expect(rootEl.parentNode).toBe(doc.body);
el.detectChanges();
expect(rootEl).toHaveText('hello');
componentRef.instance.ctxProp = 'new';
el.detectChanges();
expect(rootEl).toHaveText('new');
componentRef.dispose();
expect(rootEl).toHaveText('');
expect(rootEl.parentNode).toBe(doc.body);
async.done();
});
}));
});
});
}
@Component({
selector: 'child-cmp',
})
@View({template: '{{ctxProp}}'})
class ChildComp {
ctxProp: string;
constructor() { this.ctxProp = 'hello'; }
}
class DynamicallyCreatedComponentService {}
@Component({
selector: 'hello-cmp',
viewInjector: [DynamicallyCreatedComponentService],
lifecycle: [LifecycleEvent.onDestroy]
})
@View({template: "{{greeting}}"})
class DynamicallyCreatedCmp {
greeting: string;
dynamicallyCreatedComponentService: DynamicallyCreatedComponentService;
destroyed: boolean = false;
constructor(a: DynamicallyCreatedComponentService) {
this.greeting = "hello";
this.dynamicallyCreatedComponentService = a;
}
onDestroy() { this.destroyed = true; }
}
@Component({selector: 'dummy'})
@View({template: "DynamicallyLoaded;"})
class DynamicallyLoaded {
}
@Component({selector: 'dummy'})
@View({template: "DynamicallyLoaded2;"})
class DynamicallyLoaded2 {
}
@Component({selector: 'dummy', host: {'[id]': 'id'}})
@View({template: "DynamicallyLoadedWithHostProps;"})
class DynamicallyLoadedWithHostProps {
id: string;
constructor() { this.id = "default"; }
}
@Component({selector: 'location'})
@View({template: "Location;"})
class Location {
elementRef: ElementRef;
constructor(elementRef: ElementRef) { this.elementRef = elementRef; }
}
@Component({selector: 'my-comp'})
@View({directives: []})
class MyComp {
ctxBoolProp: boolean;
constructor() { this.ctxBoolProp = false; }
}