diff --git a/tests/app/tests/renderer-tests.ts b/tests/app/tests/renderer-tests.ts
index 02c0279e1..72a14cead 100644
--- a/tests/app/tests/renderer-tests.ts
+++ b/tests/app/tests/renderer-tests.ts
@@ -1,42 +1,19 @@
//make sure you import mocha-config before angular2/core
import {assert} from "./test-config";
-import {bootstrap} from "../nativescript-angular/application";
import {
- Type,
Component,
- ComponentRef,
- DynamicComponentLoader,
- ViewChild,
ElementRef,
- provide
} from "angular2/core";
-import {View} from "ui/core/view";
-import * as background from "ui/styling/background";
-import {StackLayout} from "ui/layouts/stack-layout";
-import {GridLayout} from "ui/layouts/grid-layout";
-import {LayoutBase} from "ui/layouts/layout-base";
import {ProxyViewContainer} from "ui/proxy-view-container";
-import {topmost} from 'ui/frame';
-import {APP_ROOT_VIEW} from "../nativescript-angular/platform-providers";
import {Red} from "color/known-colors";
-
-@Component({
- selector: 'my-app',
- template: ``
-})
-export class App {
- @ViewChild("loadSite") public loadSiteRef: ElementRef;
-
- constructor(public loader: DynamicComponentLoader,
- public elementRef: ElementRef) {
- }
-}
+import {dumpView} from "./test-utils";
+import {TestApp} from "./test-app";
@Component({
template: ``
})
export class LayoutWithLabel {
- constructor(public elementRef: ElementRef){}
+ constructor(public elementRef: ElementRef) { }
}
@Component({
@@ -44,7 +21,7 @@ export class LayoutWithLabel {
template: ``
})
export class LabelCmp {
- constructor(public elementRef: ElementRef){
+ constructor(public elementRef: ElementRef) {
}
}
@@ -53,7 +30,7 @@ export class LabelCmp {
template: ``
})
export class LabelContainer {
- constructor(public elementRef: ElementRef){}
+ constructor(public elementRef: ElementRef) { }
}
@Component({
@@ -61,7 +38,7 @@ export class LabelContainer {
template: ``
})
export class ProjectableCmp {
- constructor(public elementRef: ElementRef){
+ constructor(public elementRef: ElementRef) {
}
}
@Component({
@@ -71,7 +48,7 @@ export class ProjectableCmp {
`
})
export class ProjectionContainer {
- constructor(public elementRef: ElementRef){}
+ constructor(public elementRef: ElementRef) { }
}
@Component({
@@ -82,90 +59,125 @@ export class ProjectionContainer {
template: ``
})
export class StyledLabelCmp {
- constructor(public elementRef: ElementRef){
+ constructor(public elementRef: ElementRef) {
}
}
-describe('Renderer E2E', () => {
- let appComponent: App = null;
- let _pendingDispose: ComponentRef[] = [];
+@Component({
+ selector: "ng-if-label",
+ template: ``
+})
+export class NgIfLabel {
+ public show: boolean = false;
+ constructor(public elementRef: ElementRef) {
+ }
+}
- function loadComponent(type: Type): Promise {
- return appComponent.loader.loadIntoLocation(type, appComponent.elementRef, "loadSite").then((componentRef) => {
- _pendingDispose.push(componentRef);
- return componentRef;
- });
+@Component({
+ selector: "ng-for-label",
+ template: ``
+})
+export class NgForLabel {
+ public items: Array = ["one", "two", "three"];
+ constructor(public elementRef: ElementRef) {
}
+}
- afterEach(() => {
- while (_pendingDispose.length > 0) {
- const componentRef = _pendingDispose.pop()
- componentRef.dispose();
- }
- });
+
+describe('Renderer E2E', () => {
+ let testApp: TestApp = null;
before(() => {
- //bootstrap the app in a custom location
- const page = topmost().currentPage;
- const rootLayout = page.content;
- const viewRoot = new StackLayout();
- rootLayout.addChild(viewRoot);
- GridLayout.setRow(rootLayout, 50);
- const rootViewProvider = provide(APP_ROOT_VIEW, {useFactory: () => viewRoot});
- return bootstrap(App, [rootViewProvider]).then((componentRef) => {
- appComponent = componentRef.instance;
- });
+ return TestApp.create().then((app) => {
+ testApp = app;
+ })
+ });
+
+ after(() => {
+ testApp.dispose();
+ });
+
+ afterEach(() => {
+ testApp.disposeComponenets();
});
it("component with a layout", () => {
- return loadComponent(LayoutWithLabel).then((componentRef) => {
+ return testApp.loadComponent(LayoutWithLabel).then((componentRef) => {
const componentRoot = componentRef.instance.elementRef.nativeElement;
assert.equal("(ProxyViewContainer (StackLayout (Label)))", dumpView(componentRoot));
});
});
it("component without a layout", () => {
- return loadComponent(LabelContainer).then((componentRef) => {
+ return testApp.loadComponent(LabelContainer).then((componentRef) => {
const componentRoot = componentRef.instance.elementRef.nativeElement;
assert.equal("(ProxyViewContainer (GridLayout (ProxyViewContainer (Label))))", dumpView(componentRoot));
});
});
it("projects content into components", () => {
- return loadComponent(ProjectionContainer).then((componentRef) => {
+ return testApp.loadComponent(ProjectionContainer).then((componentRef) => {
const componentRoot = componentRef.instance.elementRef.nativeElement;
assert.equal("(ProxyViewContainer (GridLayout (ProxyViewContainer (StackLayout (Button)))))", dumpView(componentRoot));
});
});
it("applies component styles", () => {
- return loadComponent(StyledLabelCmp).then((componentRef) => {
+ return testApp.loadComponent(StyledLabelCmp).then((componentRef) => {
const componentRoot = componentRef.instance.elementRef.nativeElement;
const label = (componentRoot).getChildAt(0);
assert.equal(Red, label.style.color.hex);
});
});
-});
+ describe("Structural directives", () => {
+ it("ngIf hides component when false", () => {
+ return testApp.loadComponent(NgIfLabel).then((componentRef) => {
+ const componentRoot = componentRef.instance.elementRef.nativeElement;
+ assert.equal("(ProxyViewContainer (template))", dumpView(componentRoot));
+ });
+ });
-function dumpView(view: View): string {
- let nodeName = (view).nodeName
- if (!nodeName) {
- nodeName = (view.constructor).name + '!';
- }
- let output = ["(", nodeName, " "];
- (view)._eachChildView((child) => {
- const childDump = dumpView(child);
- output.push(childDump);
- output.push(", ");
- return true;
- });
- if (output[output.length - 1] == ", ") {
- output.pop();
- }
- if (output[output.length - 1] == " ") {
- output.pop();
- }
- output.push(")");
- return output.join("");
-}
+ it("ngIf show component when true", () => {
+ return testApp.loadComponent(NgIfLabel).then((componentRef) => {
+ const component = componentRef.instance;
+ const componentRoot = component.elementRef.nativeElement;
+
+ component.show = true;
+ testApp.appRef.tick();
+ assert.equal("(ProxyViewContainer (template), (Label))", dumpView(componentRoot));
+ });
+ })
+
+ it("ngFor creates element for each item", () => {
+ return testApp.loadComponent(NgForLabel).then((componentRef) => {
+ const componentRoot = componentRef.instance.elementRef.nativeElement;
+ assert.equal("(ProxyViewContainer (template), (Label[text=one]), (Label[text=two]), (Label[text=three]))", dumpView(componentRoot, true));
+ });
+ });
+
+ it("ngFor updates when item is removed", () => {
+ return testApp.loadComponent(NgForLabel).then((componentRef) => {
+ const component = componentRef.instance;
+ const componentRoot = component.elementRef.nativeElement;
+
+ component.items.splice(1, 1);
+ testApp.appRef.tick();
+
+ assert.equal("(ProxyViewContainer (template), (Label[text=one]), (Label[text=three]))", dumpView(componentRoot, true));
+ });
+ });
+
+ it("ngFor updates when item is inserted", () => {
+ return testApp.loadComponent(NgForLabel).then((componentRef) => {
+ const component = componentRef.instance;
+ const componentRoot = component.elementRef.nativeElement;
+
+ component.items.splice(1, 0, "new");
+ testApp.appRef.tick();
+
+ assert.equal("(ProxyViewContainer (template), (Label[text=one]), (Label[text=new]), (Label[text=two]), (Label[text=three]))", dumpView(componentRoot, true));
+ });
+ });
+ })
+})
\ No newline at end of file
diff --git a/tests/app/tests/test-app.ts b/tests/app/tests/test-app.ts
new file mode 100644
index 000000000..477517ac1
--- /dev/null
+++ b/tests/app/tests/test-app.ts
@@ -0,0 +1,75 @@
+//make sure you import mocha-config before angular2/core
+import {bootstrap} from "../nativescript-angular/application";
+import {
+ Type,
+ Component,
+ ComponentRef,
+ DynamicComponentLoader,
+ ViewChild,
+ ElementRef,
+ provide,
+ ApplicationRef
+} from "angular2/core";
+
+import {View} from "ui/core/view";
+import {StackLayout} from "ui/layouts/stack-layout";
+import {GridLayout} from "ui/layouts/grid-layout";
+import {LayoutBase} from "ui/layouts/layout-base";
+import {topmost} from 'ui/frame';
+import {APP_ROOT_VIEW} from "../nativescript-angular/platform-providers";
+
+@Component({
+ selector: 'my-app',
+ template: ``
+})
+export class TestApp {
+ @ViewChild("loadSite") public loadSiteRef: ElementRef;
+ private _pageRoot: LayoutBase;
+ private _appRoot: StackLayout;
+ private _pendingDispose: ComponentRef[] = [];
+
+ constructor(public loader: DynamicComponentLoader,
+ public elementRef: ElementRef,
+ public appRef: ApplicationRef) {
+ }
+
+ public loadComponent(type: Type): Promise {
+ return this.loader.loadIntoLocation(type, this.elementRef, "loadSite").then((componentRef) => {
+ this._pendingDispose.push(componentRef);
+ this.appRef.tick();
+ return componentRef;
+ });
+ }
+
+ public disposeComponenets() {
+ while (this._pendingDispose.length > 0) {
+ const componentRef = this._pendingDispose.pop()
+ componentRef.dispose();
+ }
+ }
+
+ public static create(): Promise {
+ const page = topmost().currentPage;
+ const rootLayout = page.content;
+ const viewRoot = new StackLayout();
+ rootLayout.addChild(viewRoot);
+ GridLayout.setRow(rootLayout, 50);
+ const rootViewProvider = provide(APP_ROOT_VIEW, { useFactory: () => viewRoot });
+ return bootstrap(TestApp, [rootViewProvider]).then((componentRef) => {
+ const testApp = componentRef.instance;
+ testApp._pageRoot = rootLayout;
+ testApp._appRoot = viewRoot;
+ return testApp;
+ });
+ }
+
+ public dispose() {
+ if (!this._appRoot) {
+ throw new Error("Test app already disposed or not initalized.");
+ }
+ this.disposeComponenets();
+ this._pageRoot.removeChild(this._appRoot);
+ this._appRoot = null;
+ this._pageRoot = null;
+ }
+}
\ No newline at end of file
diff --git a/tests/app/tests/test-utils.ts b/tests/app/tests/test-utils.ts
new file mode 100644
index 000000000..37f32bc5c
--- /dev/null
+++ b/tests/app/tests/test-utils.ts
@@ -0,0 +1,29 @@
+import {View} from "ui/core/view";
+import {TextBase} from "ui/text-base";
+
+function getChildren(view: View): Array {
+ var children: Array = [];
+ (view)._eachChildView((child) => {
+ children.push(child);
+ return true;
+ });
+ return children;
+}
+
+export function dumpView(view: View, verbose: boolean = false): string {
+ let nodeName = (view).nodeName
+ let output = ["(", nodeName];
+ if (verbose) {
+ if (view instanceof TextBase) {
+ output.push("[text=", view.text, "]")
+ }
+ }
+
+ let children = getChildren(view).map((c) => dumpView(c, verbose)).join(", ");
+ if (children) {
+ output.push(" ", children);
+ }
+
+ output.push(")");
+ return output.join("");
+}