// // make sure you import mocha-config before @angular/core

// import { assert } from "./test-config";
// import { Component, ComponentRef, ElementRef, NgZone, Renderer2, ViewChild } from "@angular/core";
// import { ProxyViewContainer, LayoutBase, StackLayout, ContentView, Button, isIOS, View, Label } from "@nativescript/core";
// import { Red } from "@nativescript/core/color/known-colors";
// import { dumpView } from "./test-utils";
// import { registerElement } from "@nativescript/angular";
// import { fontInternalProperty, backgroundInternalProperty } from "@nativescript/core/ui/core/view"
// import { nsTestBedAfterEach, nsTestBedBeforeEach, nsTestBedRender } from "@nativescript/angular/testing";
// import { ComponentFixture, TestBed, async } from "@angular/core/testing";
// import { Observable, ReplaySubject } from "rxjs";

// @Component({
//     template: `<StackLayout><Label text="Layout"></Label></StackLayout>`
// })
// export class ZonedRenderer {
//     constructor(public elementRef: ElementRef, public renderer: Renderer2) { }
// }

// @Component({
//     template: `<StackLayout><Label text="Layout"></Label></StackLayout>`
// })
// export class LayoutWithLabel {
//     constructor(public elementRef: ElementRef) { }
// }

// @Component({
//     selector: "label-cmp",
//     template: `<Label text="Layout"></Label>`
// })
// export class LabelCmp {
//     constructor(public elementRef: ElementRef) {
//     }
// }

// @Component({
//     template: `<GridLayout><label-cmp></label-cmp></GridLayout>`
// })
// export class LabelContainer {
//     constructor(public elementRef: ElementRef) { }
// }

// @Component({
//     selector: "projectable-cmp",
//     template: `<StackLayout><ng-content></ng-content></StackLayout>`
// })
// export class ProjectableCmp {
//     constructor(public elementRef: ElementRef) {
//     }
// }
// @Component({
//     template: `<GridLayout>
//         <projectable-cmp><Button text="projected"></Button></projectable-cmp>
//     </GridLayout>`
// })
// export class ProjectionContainer {
//     constructor(public elementRef: ElementRef) { }
// }

// @Component({
//     selector: "styled-label-cmp",
//     styles: [
//         "Label { color: red; }",
//     ],
//     template: `<Label text="Styled!"></Label>`
// })
// export class StyledLabelCmp {
//     constructor(public elementRef: ElementRef) {
//     }
// }

// @Component({
//     selector: "styled-label-cmp2",
//     styles: [
//         `Label { color: red; }`,
//         `
//         StackLayout { color: brown; }
//         TextField { color: red; background-color: lime; }
//         `,
//     ],
//     template: `
//     <StackLayout orientation="horizontal">
//         <Label text="Styled!"></Label>
//         <TextField text="Styled too!"></TextField>
//     </StackLayout>
//     `
// })
// export class StyledLabelCmp2 {
//     constructor(public elementRef: ElementRef) {
//     }
// }

// @Component({
//     selector: "host-styled",
//     styles: [`
//         Label {
//             color: blue;
//         }

//         :host Label {
//             color: red;
//         }
//     `
//     ],
//     template: `<Label text="Styled!"></Label>`
// })
// export class HostStyledCmp {
//     constructor(public elementRef: ElementRef<ProxyViewContainer>) {
//     }
// }

// @Component({
//     selector: "host-styled-parent",
//     template: `
//         <host-styled></host-styled>
//         <host-styled></host-styled>
//     `
// })
// export class HostStyledParentCmp {
//     constructor(public elementRef: ElementRef<ProxyViewContainer>) {
//     }
// }

// @Component({
//     selector: "ng-if-label",
//     template: `<Label *ngIf="show" text="iffed"></Label>`
// })
// export class NgIfLabel {
//     public show: boolean = false;
//     constructor(public elementRef: ElementRef) {
//     }
// }

// @Component({
//     selector: "ng-if-two-elements",
//     template: `
//         <StackLayout>
//             <Label *ngIf="show" text="label"></Label>
//             <Button text="button"></Button>
//         </StackLayout>
//     `
// })
// export class NgIfTwoElements {
//     public show: boolean = false;
//     constructor(public elementRef: ElementRef) {
//     }
// }

// @Component({
//     selector: "ng-if-multiple",
//     template: `
//         <StackLayout>
//             <Label text="1"></Label>
//             <Label text="2"></Label>
//             <Label text="3"></Label>
//             <Label *ngIf="true" text="4"></Label>
//             <Label text="5"></Label>
//         </StackLayout>
//     `
// })
// export class NgIfMultiple {
//     public show: boolean = false;
//     constructor(public elementRef: ElementRef) {
//     }
// }

// @Component({
//     selector: "ng-if-else",
//     template: `
//         <StackLayout>
//             <Label *ngIf="show; else elseClause" text="If"></Label>

//             <ng-template #elseClause>
//                 <Label text="Else"></Label>
//             </ng-template>
//         </StackLayout>
//     `
// })
// export class NgIfElseComponent {
//     public show: boolean = true;
//     constructor(public elementRef: ElementRef) {
//     }
// }

// @Component({
//     selector: "ng-if-then-else",
//     template: `
//         <StackLayout>
//             <Placeholder *ngIf="show; then thenTemplate else elseTemplate">
//             </Placeholder>

//             <ng-template #thenTemplate>
//                 <Label text="Then"></Label>
//             </ng-template>

//             <ng-template #elseTemplate>
//                 <Label text="Else"></Label>
//             </ng-template>
//         </StackLayout>
//     `
// })
// export class NgIfThenElseComponent {
//     public show: boolean = true;
//     constructor(public elementRef: ElementRef) {
//     }
// }

// export class ButtonCounter extends Button {
//     nativeBackgroundRedraws = 0;
//     backgroundInternalSetNativeCount = 0;
//     fontInternalSetNativeCount = 0;

//     [backgroundInternalProperty.setNative](value) {
//         this.backgroundInternalSetNativeCount++;
//         return super[backgroundInternalProperty.setNative](value);
//     }
//     [fontInternalProperty.setNative](value) {
//         this.fontInternalSetNativeCount++;
//         return super[fontInternalProperty.setNative](value);
//     }
//     _redrawNativeBackground(value: any): void {
//         this.nativeBackgroundRedraws++;
//         super["_redrawNativeBackground"](value);
//     }
// }
// registerElement("ButtonCounter", () => ButtonCounter);

// @Component({
//     selector: "ng-control-setters-count",
//     template: `
//         <StackLayout>
//             <ButtonCounter #btn1 id="btn1" borderWidth="1" borderColor="gray" borderRadius="16" fontWeight="bold" fontSize="16"></ButtonCounter>
//             <ButtonCounter #btn2 id="btn2"></ButtonCounter>
//             <ButtonCounter #btn3 id="btn3" borderWidth="1" borderColor="gray" borderRadius="16" fontWeight="bold" fontSize="16"></ButtonCounter>
//             <ButtonCounter #btn4 id="btn4" borderRadius="3" style="background-image: url('~/logo.png'); background-position: center; background-repeat: no-repeat; background-size: cover;"></ButtonCounter>
//         </StackLayout>
//     `,
//     styles: [`
//         #btn2, #btn3, #btn4 {
//             border-width: 2;
//             border-color: teal;
//             border-radius: 20;
//             font-weight: 400;
//             font-size: 32;
//         }`]
// })
// export class NgControlSettersCount {
//     @ViewChild("btn1", { static: false }) btn1: ElementRef;
//     @ViewChild("btn2", { static: false }) btn2: ElementRef;
//     @ViewChild("btn3", { static: false }) btn3: ElementRef;
//     @ViewChild("btn3", { static: false }) btn4: ElementRef;

//     get buttons(): ElementRef[] { return [this.btn1, this.btn2, this.btn3, this.btn4]; }

//     ready$: Observable<boolean> = new ReplaySubject<boolean>(1);

//     ngAfterViewInit() {
//         (this.ready$ as ReplaySubject<boolean>).next(true);
//     }
// }

// @Component({
//     selector: "ng-for-label",
//     template: `<Label *ngFor="let item of items" [text]="item"></Label>`
// })
// export class NgForLabel {
//     public items: Array<string> = ["one", "two", "three"];
//     constructor(public elementRef: ElementRef) {
//     }
// }

// describe("Renderer E2E", () => {
//     beforeEach(nsTestBedBeforeEach([
//         LayoutWithLabel, LabelCmp, LabelContainer,
//         ProjectableCmp, ProjectionContainer,
//         StyledLabelCmp, StyledLabelCmp2,
//         HostStyledCmp, HostStyledParentCmp,
//         NgIfLabel, NgIfThenElseComponent, NgIfMultiple,
//         NgIfTwoElements, NgIfMultiple,
//         NgIfElseComponent, NgIfThenElseComponent,
//         NgForLabel, ZonedRenderer
//     ]));
//     afterEach(nsTestBedAfterEach(false));

//     it("component with a layout", () => {
//         return nsTestBedRender(LayoutWithLabel).then((fixture) => {
//             const componentRef: ComponentRef<LayoutWithLabel> = fixture.componentRef;
//             const componentRoot = componentRef.instance.elementRef.nativeElement;
//             assert.equal("(proxyviewcontainer (stacklayout (label)))", dumpView(componentRoot));
//         });
//     });

//     it("component without a layout", () => {
//         return nsTestBedRender(LabelContainer).then((fixture) => {
//             const componentRef: ComponentRef<LabelContainer> = fixture.componentRef;
//             const componentRoot = componentRef.instance.elementRef.nativeElement;
//             assert.equal("(proxyviewcontainer (gridlayout (proxyviewcontainer (label))))", dumpView(componentRoot));
//         });
//     });

//     it("projects content into components", () => {
//         return nsTestBedRender(ProjectionContainer).then((fixture) => {
//             const componentRef: ComponentRef<ProjectionContainer> = fixture.componentRef;
//             const componentRoot = componentRef.instance.elementRef.nativeElement;
//             assert.equal(
//                 "(proxyviewcontainer (gridlayout (proxyviewcontainer (stacklayout (button)))))",
//                  dumpView(componentRoot));
//         });
//     });

//     it("applies component styles from single source", () => {
//         return nsTestBedRender(StyledLabelCmp).then((fixture) => {
//             const componentRef: ComponentRef<StyledLabelCmp> = fixture.componentRef;
//             const componentRoot = componentRef.instance.elementRef.nativeElement;
//             const label = (<ProxyViewContainer>componentRoot).getChildAt(0);
//             assert.equal(Red, label.style.color.hex);
//         });
//     });

//     it("applies component :host styles", () => {
//         return nsTestBedRender(HostStyledParentCmp).then((fixture) => {
//             const proxyView = fixture.componentRef.instance.elementRef.nativeElement;

//             for (let i = 0; i < 2; i += 1) {
//                 const child = proxyView.getChildAt(i) as ProxyViewContainer;
//                 const label = child.getChildAt(0) as Label;
//                 assert.equal(Red, label.style.color.hex);
//             }
//         });
//     });

//     it("applies component styles from multiple sources", () => {
//         return nsTestBedRender(StyledLabelCmp2).then((fixture) => {
//             const componentRef: ComponentRef<StyledLabelCmp2> = fixture.componentRef;
//             const componentRoot = componentRef.instance.elementRef.nativeElement;
//             const layout = (<ProxyViewContainer>componentRoot).getChildAt(0);

//             const label = (<LayoutBase>layout).getChildAt(0);
//             assert.equal(Red, label.style.color.hex);

//             const textField = (<LayoutBase>layout).getChildAt(1);
//             console.log("TEXT style.color: " + textField.style.color);
//             assert.equal(Red, textField.style.color.hex);
//         });
//     });

//     it("executes events inside NgZone when listen is called inside NgZone", async(() => {
//         const eventName = "someEvent";
//         const view = new StackLayout();
//         const eventArg = { eventName, object: view };
//         const callback = (arg) => {
//             assert.equal(arg, eventArg);
//             assert.isTrue(NgZone.isInAngularZone(), "Event should be executed inside NgZone");
//         };

//         nsTestBedRender(ZonedRenderer).then((fixture: ComponentFixture<ZonedRenderer>) => {
//             fixture.ngZone.run(() => {
//                 fixture.componentInstance.renderer.listen(view, eventName, callback);
//             });

//             setTimeout(() => {
//                 fixture.ngZone.runOutsideAngular(() => {
//                     view.notify(eventArg);
//                 });
//             }, 10);
//         });

//     }));

//     it("executes events inside NgZone when listen is called outside NgZone", async(() => {
//         const eventName = "someEvent";
//         const view = new StackLayout();
//         const eventArg = { eventName, object: view };
//         const callback = (arg) => {
//             assert.equal(arg, eventArg);
//             assert.isTrue(NgZone.isInAngularZone(), "Event should be executed inside NgZone");
//         };
//         nsTestBedRender(ZonedRenderer).then((fixture: ComponentFixture<ZonedRenderer>) => {
//             fixture.ngZone.runOutsideAngular(() => {
//                 fixture.componentInstance.renderer.listen(view, eventName, callback);

//                 view.notify(eventArg);
//             });
//         });
//     }));

//     describe("Structural directives", () => {
//         it("ngIf hides component when false", () => {
//             return nsTestBedRender(NgIfLabel).then((fixture) => {
//                 const componentRef: ComponentRef<NgIfLabel> = fixture.componentRef;
//                 const componentRoot = componentRef.instance.elementRef.nativeElement;
//                 assert.equal("(proxyviewcontainer)", dumpView(componentRoot));
//             });
//         });

//         it("ngIf show component when true", () => {
//             return nsTestBedRender(NgIfLabel).then((fixture) => {
//                 const componentRef: ComponentRef<NgIfLabel> = fixture.componentRef;
//                 const component = <NgIfLabel>componentRef.instance;
//                 const componentRoot = component.elementRef.nativeElement;

//                 component.show = true;
//                 fixture.detectChanges();
//                 assert.equal("(proxyviewcontainer (label))", dumpView(componentRoot));
//             });
//         });

//         it("ngIf shows elements in correct order when two are rendered", () => {
//             return nsTestBedRender(NgIfTwoElements).then((fixture) => {
//                 const componentRef: ComponentRef<NgIfTwoElements> = fixture.componentRef;
//                 const component = <NgIfTwoElements>componentRef.instance;
//                 const componentRoot = component.elementRef.nativeElement;

//                 component.show = true;
//                 fixture.detectChanges();
//                 assert.equal(
//                     "(proxyviewcontainer (stacklayout (label), (button)))",
//                     dumpView(componentRoot));
//             });
//         });

//         it("ngIf shows elements in correct order when multiple are rendered and there's *ngIf", () => {
//             return nsTestBedRender(NgIfMultiple).then((fixture) => {
//                 const componentRef: ComponentRef<NgIfMultiple> = fixture.componentRef;
//                 const component = <NgIfMultiple>componentRef.instance;
//                 const componentRoot = component.elementRef.nativeElement;

//                 component.show = true;
//                 fixture.detectChanges();
//                 assert.equal(
//                     "(proxyviewcontainer " +
//                         "(stacklayout " +
//                             "(label[text=1]), " +
//                             "(label[text=2]), " +
//                             "(label[text=3]), " +
//                             "(label[text=4]), " + // the content to be conditionally displayed
//                             "(label[text=5])" +
//                         ")" +
//                     ")",
//                     dumpView(componentRoot, true));
//             });
//         });

//         it("ngIfElse show 'if' template when condition is true", () => {
//             return nsTestBedRender(NgIfElseComponent).then((fixture) => {
//                 const componentRef: ComponentRef<NgIfElseComponent> = fixture.componentRef;
//                 const component = <NgIfElseComponent>componentRef.instance;
//                 const componentRoot = component.elementRef.nativeElement;

//                 fixture.detectChanges();

//                 assert.equal(
//                     "(proxyviewcontainer " +
//                         "(stacklayout " +
//                             "(label[text=If])" +
//                         ")" +
//                     ")",

//                     dumpView(componentRoot, true));
//             });
//         });

//         it("ngIfElse show 'else' template when condition is false", () => {
//             return nsTestBedRender(NgIfElseComponent).then((fixture) => {
//                 const componentRef: ComponentRef<NgIfElseComponent> = fixture.componentRef;
//                 const component = <NgIfElseComponent>componentRef.instance;
//                 const componentRoot = component.elementRef.nativeElement;

//                 component.show = false;
//                 fixture.detectChanges();
//                 assert.equal(
//                     "(proxyviewcontainer " +
//                         "(stacklayout " +
//                             "(label[text=Else])" +
//                         ")" +
//                     ")",

//                     dumpView(componentRoot, true));
//             });
//         });

//         it("ngIfThenElse show 'then' template when condition is true", () => {
//             return nsTestBedRender(NgIfThenElseComponent).then((fixture) => {
//                 const componentRef: ComponentRef<NgIfThenElseComponent> = fixture.componentRef;
//                 const component = <NgIfThenElseComponent>componentRef.instance;
//                 const componentRoot = component.elementRef.nativeElement;

//                 fixture.detectChanges();
//                 assert.equal(
//                     "(proxyviewcontainer " +
//                         "(stacklayout " +
//                             "(label[text=Then])" +
//                         ")" +
//                     ")",

//                     dumpView(componentRoot, true));
//             });
//         });

//         it("ngIfThenElse show 'else' template when condition is false", () => {
//             return nsTestBedRender(NgIfThenElseComponent).then((fixture) => {
//                 const componentRef: ComponentRef<NgIfThenElseComponent> = fixture.componentRef;
//                 const component = <NgIfThenElseComponent>componentRef.instance;
//                 const componentRoot = component.elementRef.nativeElement;

//                 component.show = false;
//                 fixture.detectChanges();
//                 assert.equal(
//                     "(proxyviewcontainer " +
//                         "(stacklayout " +
//                             "(label[text=Else])" +
//                         ")" +
//                     ")",

//                     dumpView(componentRoot, true));
//             });
//         });

//         it("ngFor creates element for each item", () => {
//             return nsTestBedRender(NgForLabel).then((fixture) => {
//                 const componentRef: ComponentRef<NgForLabel> = fixture.componentRef;
//                 const componentRoot = componentRef.instance.elementRef.nativeElement;
//                 assert.equal(
//                     "(proxyviewcontainer (label[text=one]), (label[text=two]), (label[text=three]))",
//                     dumpView(componentRoot, true));
//             });
//         });

//         it("ngFor updates when item is removed", () => {
//             return nsTestBedRender(NgForLabel).then((fixture) => {
//                 const componentRef: ComponentRef<NgForLabel> = fixture.componentRef;
//                 const component = <NgForLabel>componentRef.instance;
//                 const componentRoot = component.elementRef.nativeElement;

//                 component.items.splice(1, 1);
//                 fixture.detectChanges();

//                 assert.equal(
//                     "(proxyviewcontainer (label[text=one]), (label[text=three]))",
//                     dumpView(componentRoot, true));
//             });
//         });

//         it("ngFor updates when item is inserted", () => {
//             return nsTestBedRender(NgForLabel).then((fixture) => {
//                 const componentRef: ComponentRef<NgForLabel> = fixture.componentRef;
//                 const component = <NgForLabel>componentRef.instance;
//                 const componentRoot = component.elementRef.nativeElement;

//                 component.items.splice(1, 0, "new");
//                 fixture.detectChanges();

//                 assert.equal(
//                     "(proxyviewcontainer " +
//                     "(label[text=one]), (label[text=new]), (label[text=two]), (label[text=three]))",
//                     dumpView(componentRoot, true));
//             });
//         });
//     });
// });

// describe("Renderer createElement", () => {
//     let renderer: Renderer2 = null;
//     beforeEach(nsTestBedBeforeEach([ZonedRenderer]));
//     afterEach(nsTestBedAfterEach(false));
//     beforeEach(() => {
//         return nsTestBedRender(ZonedRenderer).then((fixture: ComponentFixture<ZonedRenderer>) => {
//             fixture.ngZone.run(() => {
//                 renderer = fixture.componentInstance.renderer;
//             });
//         });
//     });

//     it("creates element from CamelCase", () => {
//         const result = renderer.createElement("StackLayout");
//         assert.instanceOf(result, StackLayout, "Renderer should create StackLayout form 'StackLayout'");
//     });

//     it("creates element from lowercase", () => {
//         const result = renderer.createElement("stacklayout");
//         assert.instanceOf(result, StackLayout, "Renderer should create StackLayout form 'stacklayout'");
//     });

//     it("creates element from kebab-case", () => {
//         const result = renderer.createElement("stack-layout");
//         assert.instanceOf(result, StackLayout, "Renderer should create StackLayout form 'stack-layout'");
//     });

//     it("creates ProxyViewContainer for unknownTag", () => {
//         const result = renderer.createElement("unknown-tag");
//         assert.instanceOf(result, ProxyViewContainer, "Renderer should create ProxyViewContainer form 'unknown-tag'");
//     });
// });

// describe("Renderer attach/detach", () => {
//     let renderer: Renderer2 = null;
//     beforeEach(nsTestBedBeforeEach([ZonedRenderer]));
//     afterEach(nsTestBedAfterEach(false));
//     beforeEach(() => {
//         return nsTestBedRender(ZonedRenderer).then((fixture: ComponentFixture<ZonedRenderer>) => {
//             fixture.ngZone.run(() => {
//                 renderer = fixture.componentInstance.renderer;
//             });
//         });
//     });

//     it("createElement element with parent attaches element to content view", () => {
//         const parent = <ContentView>renderer.createElement("ContentView");
//         const button = <Button>renderer.createElement("Button");
//         renderer.appendChild(parent, button);

//         assert.equal(parent.content, button);
//         assert.equal(button.parent, parent);
//     });

//     it("createElement element with parent attaches element to layout view", () => {
//         const parent = <StackLayout>renderer.createElement("StackLayout");
//         const button = <Button>renderer.createElement("Button");
//         renderer.appendChild(parent, button);

//         assert.equal(parent.getChildAt(0), button);
//         assert.equal(button.parent, parent);
//     });

//     it("detachView element removes element from content view", () => {
//         const parent = <ContentView>renderer.createElement("ContentView");
//         const button = <Button>renderer.createElement("Button");
//         renderer.appendChild(parent, button);

//         renderer.removeChild(parent, button);

//         assert.isNull(parent.content);
//         assert.isUndefined(button.parent);
//     });

//     it("detachView element removes element from layout view", () => {
//         const parent = <StackLayout>renderer.createElement("StackLayout");
//         const button = <Button>renderer.createElement("Button");
//         renderer.appendChild(parent, button);

//         renderer.removeChild(parent, button);

//         assert.equal(parent.getChildrenCount(), 0);
//         assert.isUndefined(button.parent);
//     });
// });

// describe("Renderer lifecycle", () => {
//     let renderer: Renderer2 = null;
//     beforeEach(nsTestBedBeforeEach([ZonedRenderer, NgControlSettersCount]));
//     afterEach(nsTestBedAfterEach(false));
//     beforeEach(() => {
//         return nsTestBedRender(ZonedRenderer).then((fixture: ComponentFixture<ZonedRenderer>) => {
//             fixture.ngZone.run(() => {
//                 renderer = fixture.componentInstance.renderer;
//             });
//         });
//     });

//     it("view native setters are called once on startup", () => {
//         const fixture = TestBed.createComponent(NgControlSettersCount);
//         const component: NgControlSettersCount = fixture.componentInstance;
//         return component.ready$.subscribe(() => {
//             component.buttons.map(btn => btn.nativeElement).forEach(btn => {
//                 assert.isTrue(btn.isLoaded, `Expected ${btn.id} to be loaded.`);
//                 assert.isFalse(
//                     btn.isLayoutValid,
//                     `Expected ${btn.id}'s layout to be invalid because it is uninitialized.`
//                 );

//                 assert.equal(
//                     btn.backgroundInternalSetNativeCount, 1,
//                     `Expected ${btn.id} backgroundInternalSetNativeCount to be called just once.`
//                 );
//                 assert.equal(
//                     btn.fontInternalSetNativeCount, 1,
//                     `Expected ${btn.id} fontInternalSetNativeCount to be called just once.`
//                 );
//                 const expectedBackgroundRedraws = isIOS ? 0 : 1;
//                 assert.equal(
//                     btn.nativeBackgroundRedraws, expectedBackgroundRedraws,
//                     `Expected ${btn.id} nativeBackgroundRedraws to be called after its layout pass.`
//                 );
//             });
//         });
//     });
// });
