From 56131d812c4da541c32f71f1d30aae7023d67892 Mon Sep 17 00:00:00 2001 From: Panayot Cankov Date: Tue, 23 May 2017 10:40:00 +0300 Subject: [PATCH] Add tests to ensure native setters are called exactly once when components are instantiated --- tests/app/logo.png | Bin 0 -> 4918 bytes tests/app/tests/renderer-tests.ts | 93 +++++++++++++++++++++++++++++- tests/app/tests/test-app.ts | 2 +- 3 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 tests/app/logo.png diff --git a/tests/app/logo.png b/tests/app/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..add1ce15d7477b400746e55468e587caa12c17f1 GIT binary patch literal 4918 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 literal 0 HcmV?d00001 diff --git a/tests/app/tests/renderer-tests.ts b/tests/app/tests/renderer-tests.ts index 3c2ccd506..ebb9091ee 100644 --- a/tests/app/tests/renderer-tests.ts +++ b/tests/app/tests/renderer-tests.ts @@ -1,6 +1,6 @@ // make sure you import mocha-config before @angular/core import { assert } from "./test-config"; -import { Component, ElementRef, Renderer2, NgZone } from "@angular/core"; +import { Component, ElementRef, Renderer2, NgZone, ViewChild } from "@angular/core"; import { ProxyViewContainer } from "ui/proxy-view-container"; import { Red } from "color/known-colors"; import { dumpView } from "./test-utils"; @@ -10,6 +10,9 @@ import { StackLayout } from "ui/layouts/stack-layout"; import { ContentView } from "ui/content-view"; import { Button } from "ui/button"; import { NgView } from "nativescript-angular/element-registry"; +import { registerElement } from "nativescript-angular/element-registry"; +import * as button from "tns-core-modules/ui/button"; +import * as view from "tns-core-modules/ui/core/view"; @Component({ template: `` @@ -169,6 +172,60 @@ export class NgIfThenElseComponent { } } +export class ButtonCounter extends button.Button { + nativeBackgroundRedraws = 0; + backgroundInternalSetNativeCount = 0; + fontInternalSetNativeCount = 0; + + [view.backgroundInternalProperty.setNative](value) { + this.backgroundInternalSetNativeCount++; + return super[view.backgroundInternalProperty.setNative](value); + } + [view.fontInternalProperty.setNative](value) { + this.fontInternalSetNativeCount++; + return super[view.fontInternalProperty.setNative](value); + } + _redrawNativeBackground(value: any): void { + this.nativeBackgroundRedraws++; + super["_redrawNativeBackground"](value); + } +} +registerElement("ButtonCounter", () => ButtonCounter); + +@Component({ + selector: "ng-control-setters-count", + template: ` + + + + + + + `, + styles: [` + #btn2, #btn3, #btn4 { + border-width: 2; + border-color: teal; + border-radius: 20; + font-weight: 400; + font-size: 32; + }`] +}) +export class NgControlSettersCount { + @ViewChild("btn1") btn1: ElementRef; + @ViewChild("btn2") btn2: ElementRef; + @ViewChild("btn3") btn3: ElementRef; + @ViewChild("btn3") btn4: ElementRef; + + get buttons(): ElementRef[] { return [this.btn1, this.btn2, this.btn3, this.btn4]; } + + isAfterViewInit: boolean = false; + + ngAfterViewInit() { + this.isAfterViewInit = true; + } +} + @Component({ selector: "ng-for-label", template: `` @@ -488,7 +545,6 @@ describe("Renderer createElement", () => { }); }); - describe("Renderer attach/detach", () => { let testApp: TestApp = null; let renderer: Renderer2 = null; @@ -545,3 +601,36 @@ describe("Renderer attach/detach", () => { }); }); +describe("Renderer lifecycle", () => { + let testApp: TestApp = null; + let renderer: Renderer2 = null; + + before(() => { + return TestApp.create([], [NgControlSettersCount]).then((app) => { + testApp = app; + renderer = testApp.renderer; + }); + }); + + after(() => { + testApp.dispose(); + }); + + afterEach(() => { + testApp.disposeComponents(); + }); + + it("view native setters are called once on startup", () => { + return testApp.loadComponent(NgControlSettersCount).then((componentRef) => { + assert.isTrue(componentRef.instance.isAfterViewInit, "Expected the NgControlSettersCount to have passed its ngAfterViewInit."); + componentRef.instance.buttons.map(btn => btn.nativeElement).forEach(btn => { + assert.isTrue(btn.isLoaded, `Expected ${btn.id} to be allready loaded.`); + assert.isFalse(btn.isLayoutValid, `Expected ${btn.id}'s layout to be invalid.`); + + 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.`); + assert.equal(btn.nativeBackgroundRedraws, 0, `Expected ${btn.id} nativeBackgroundRedraws to be called after its layout pass.`); + }); + }); + }); +}); diff --git a/tests/app/tests/test-app.ts b/tests/app/tests/test-app.ts index 33399903a..fd481c67c 100644 --- a/tests/app/tests/test-app.ts +++ b/tests/app/tests/test-app.ts @@ -30,7 +30,7 @@ export class TestApp { registerTestApp(TestApp, this, appRef); } - public loadComponent(componentType: Type): Promise> { + public loadComponent(componentType: Type): Promise> { const factory = this.resolver.resolveComponentFactory(componentType); const componentRef = this.containerRef.createComponent( factory, this.containerRef.length, this.containerRef.parentInjector);