Files
NativeScript/tests/app/ui/view/view-tests-common.ts
Hristo Hristov 0f14101238 recycling now happens only if nativeView and android properties are not accessed. (#4627)
recycleNativeView filed now accepts: "always" | "never" | "auto". Always will recycle the nativeView no matter if its nativeView or android proprties are accessed. Never will disable recycling. Auto will recycle it only if nativeView and android properties are not accessed.
2017-08-01 15:04:16 +03:00

1083 lines
38 KiB
TypeScript

import * as TKUnit from "../../TKUnit";
import { View, eachDescendant, getViewById, InheritedProperty, CssProperty, CssAnimationProperty, ShorthandProperty, Property, Style } from "tns-core-modules/ui/core/view";
import { topmost } from "tns-core-modules/ui/frame";
import { Page } from "tns-core-modules/ui/page";
import { Button } from "tns-core-modules/ui/button";
import { Label } from "tns-core-modules/ui/label";
import { Color } from "tns-core-modules/color";
import { Layout } from "tns-core-modules/ui/layouts/layout";
import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout";
import { AbsoluteLayout } from "tns-core-modules/ui/layouts/absolute-layout";
import * as utils from "tns-core-modules/utils/utils";
import * as types from "tns-core-modules/utils/types";
import * as helper from "../../ui/helper";
import * as observable from "tns-core-modules/data/observable";
import * as bindable from "tns-core-modules/ui/core/bindable";
import * as definition from "./view-tests";
import { isIOS, isAndroid } from "tns-core-modules/platform";
export function test_eachDescendant() {
const test = function (views: Array<View>) {
// traverse the visual tree and verify the hierarchy
let counter = 0;
const callback = function (child: View): boolean {
TKUnit.assert(child === views[counter]);
counter++;
return true;
};
eachDescendant(topmost(), callback);
// Descendants: page, actionBar, button
TKUnit.assertEqual(counter, 3, "descendants");
};
helper.do_PageTest_WithButton(test);
};
export function test_getViewById_Static() {
const test = function (views: Array<View>) {
views[1].id = "myLayout";
// traverse the visual tree and verify the hierarchy
const result = getViewById(topmost(), "myLayout");
TKUnit.assert(result === views[1]);
};
helper.do_PageTest_WithButton(test);
};
export function test_getViewById_Instance() {
const test = function (views: Array<View>) {
views[1].id = "myLayout";
// traverse the visual tree and verify the hierarchy
const result = topmost().getViewById<View>("myLayout");
TKUnit.assert(result === views[1]);
};
helper.do_PageTest_WithButton(test);
};
export function test_eachDescendant_Break_Iteration() {
const test = function (views: Array<View>) {
// traverse the visual tree and verify the hierarchy
let counter = 0;
const callback = function (child: View): boolean {
TKUnit.assert(child === views[0]);
counter++;
return false;
};
eachDescendant(topmost(), callback);
TKUnit.assert(counter === 1);
};
helper.do_PageTest_WithButton(test);
};
export function test_parent_IsValid_WhenAttached_ToVisualTree() {
const test = function (views: Array<View>) {
// views[0] is a Page instance, its parent should be the topmost frame
TKUnit.assert(types.isDefined(views[0].parent));
TKUnit.assert(views[0].parent === topmost());
// views[1] is a Button instance, its parent should be the Page (views[0])
TKUnit.assert(types.isDefined(views[1].parent));
TKUnit.assert(views[1].parent === views[0]);
};
helper.do_PageTest_WithButton(test);
};
export function test_parent_IsReset_WhenDetached_FromVisualTree() {
let cachedViews: Array<View>;
const test = function (views: Array<View>) {
cachedViews = views;
};
helper.do_PageTest_WithStackLayout_AndButton(test);
TKUnit.assert(types.isUndefined(cachedViews[1].parent));
TKUnit.assert(types.isDefined(cachedViews[2].parent));
TKUnit.assert(cachedViews[2].parent === cachedViews[1]);
};
export function test_domId_IsUnique() {
const btn = new Button();
const topframe = topmost();
TKUnit.assert(btn._domId !== topframe._domId);
TKUnit.assert(btn._domId !== topframe.currentPage._domId);
};
export function test_Id_WillNotCrash_WhenSetToNumber() {
const btn = new Button();
btn.id = "1";
TKUnit.assert(btn.id === "1");
};
export function test_event_LoadedUnloaded_IsRaised() {
const test = function (views: Array<View>) {
let i;
for (i = 0; i < views.length; i++) {
TKUnit.assert(views[i].isLoaded);
}
// change the page's content and verify the proper events
let layoutUnloaded = false;
let buttonUnloaded = false;
views[1].on(View.unloadedEvent, (data) => {
layoutUnloaded = true;
});
views[2].on(View.unloadedEvent, (data) => {
buttonUnloaded = true;
});
const newButton = new Button();
let buttonLoaded = false;
newButton.on(View.loadedEvent, (data) => {
buttonLoaded = true;
});
(<Page>views[0]).content = newButton;
TKUnit.assert(layoutUnloaded);
TKUnit.assert(buttonUnloaded);
TKUnit.assert(buttonLoaded);
};
helper.do_PageTest_WithStackLayout_AndButton(test);
};
export function test_bindingContext_IsInherited() {
const context = {};
const test = function (views: Array<View>) {
views[0].bindingContext = context;
for (let i = 0; i < views.length; i++) {
TKUnit.assertEqual(views[i].bindingContext, context);
}
};
helper.do_PageTest_WithStackLayout_AndButton(test);
topmost().bindingContext = undefined;
}
export function test_isAddedToNativeVisualTree_IsUpdated() {
const test = function (views: Array<View>) {
for (let i = 0; i < views.length; i++) {
TKUnit.assert(views[i]._isAddedToNativeVisualTree, `View ${views[i]} not initially added`);
}
const newButton = new Button();
TKUnit.assert(!newButton._isAddedToNativeVisualTree, "Button is not added initially");
views[1]._addView(newButton);
TKUnit.assert(newButton._isAddedToNativeVisualTree, "Button is not added after _addView");
views[1]._removeView(newButton);
TKUnit.assert(!newButton._isAddedToNativeVisualTree, "Button is removed after _removeView");
};
helper.do_PageTest_WithStackLayout_AndButton(test);
};
export function test_addView_WillThrow_IfView_IsAlreadyAdded() {
const test = function (views: Array<View>) {
const newButton = new Button();
views[1]._addView(newButton);
let thrown = false;
try {
views[1]._addView(newButton);
} catch (e) {
thrown = true;
TKUnit.assert(e.message.indexOf("View already has a parent.") >= 0);
}
TKUnit.assert(thrown);
};
helper.do_PageTest_WithStackLayout_AndButton(test);
};
export function test_addToNativeVisualTree_WillThrow_IfView_IsAlreadyAdded() {
const test = function (views: [Page, StackLayout, View, View]) {
const newButton = new Button();
views[1]._addView(newButton);
let thrown = false;
try {
views[1]._addViewToNativeVisualTree(newButton);
} catch (e) {
thrown = true;
TKUnit.assert(e.message === "Child already added to the native visual tree.");
}
TKUnit.assert(thrown);
};
helper.do_PageTest_WithStackLayout_AndButton(test);
};
export function test_InheritableStyleProperties_AreInherited() {
helper.do_PageTest_WithStackLayout_AndButton((views) => {
const redColor = new Color("red");
views[0].style.color = redColor;
const newButton = new Button();
views[1].addChild(newButton);
TKUnit.assertEqual(newButton.style.color, redColor, "Color should be inherited");
});
};
export class TestButton extends Button {
}
export function test_InheritableStylePropertiesWhenUsedWithExtendedClass_AreInherited() {
let page = topmost().currentPage;
let redColor = new Color("red");
page.style.color = redColor;
let newButton = new TestButton();
page.content = newButton;
TKUnit.assertEqual(newButton.style.color, redColor);
}
// TestView definition START
const customCssProperty = new CssProperty<Style, string>({ name: "customCssProperty", cssName: "custom-css-property" });
const customCssAnimationProperty = new CssAnimationProperty<Style, string>({ name: "customCssAnimationProperty", cssName: "custom-css-animation-property" });
const customViewProperty = new Property<TestView, string>({ name: "custom" });
const customCssAProperty = new CssProperty<Style, string>({
name: "customCssA",
cssName: "custom-css-a",
valueChanged(target, oldValue, newValue) {
if ((<any>target).customCssAPropertyChanged) {
(<any>target).customCssAPropertyChanged(oldValue, newValue);
}
}
});
customCssAProperty.register(Style);
const customCssBProperty = new CssProperty<Style, string>({
name: "customCssB",
cssName: "custom-css-b",
valueChanged(target, oldValue, newValue) {
if ((<any>target).customCssBPropertyChanged) {
(<any>target).customCssBPropertyChanged(oldValue, newValue);
}
}
});
customCssBProperty.register(Style);
const customShortHandProperty = new ShorthandProperty<Style, string>({
name: "customShortHand",
cssName: "custom-short-hand",
converter(value: string): [CssProperty<any, any>, any][] {
console.log("Convert: " + value);
const values = value.split(",");
return [
[customCssAProperty, values[0]],
[customCssBProperty, values[1]]
];
},
getter(this: Style): string {
return `${(<any>this).customCssA},${(<any>this).customCssB}`;
}
});
customShortHandProperty.register(Style);
class TestView extends Layout {
public inheritanceTest: number;
public booleanInheritanceTest: boolean;
public dummy: number;
public viewPropGetDefaultCounter: number = 0;
public viewPropCounter: number = 0;
public viewPropNativeValue: string;
public cssPropGetDefaultCounter: number = 0;
public cssPropCounter: number = 0;
public cssPropNativeValue: string;
public cssAnimPropGetDefaultCounter: number = 0;
public cssAnimPropCounter: number = 0;
public cssAnimPropNativeValue: string;
public custom: string;
get customCssProperty(): string {
return this.style["customCssProperty"];
}
set customCssProperty(value: string) {
this.style["customCssProperty"] = value;
}
get customCssAnimationProperty(): string {
return this.style["customCssAnimationProperty"];
}
set customCssAnimationProperty(value: string) {
this.style["customCssAnimationProperty"] = value;
}
get customCssA(): string {
return (<any>this.style).customCssA;
}
set customCssA(value: string) {
(<any>this.style).customCssA = value;
}
get customCssB(): string {
return (<any>this.style).customCssB;
}
set customCssB(value: string) {
(<any>this.style).customCssB = value;
}
get customShortHand(): string {
return (<any>this.style).customShortHand;
}
set customShortHand(value: string) {
console.log("Setting style's customShortHand: " + value);
(<any>this.style).customShortHand = value;
}
private _nativeView;
constructor(public name: string) {
super();
this._nativeView = this.nativeViewProtected;
this.nativeViewProtected = undefined;
}
public createNativeView() {
if (isIOS) {
return this._nativeView;
}
return super.createNativeView();
}
public toString() {
return super.toString() + "." + this.name;
}
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
this.setMeasuredDimension(100, 100);
}
[customViewProperty.getDefault](): string {
this.viewPropGetDefaultCounter++;
return "customViewPropertyDefaultValue";
}
[customViewProperty.setNative](value: string) {
this.viewPropCounter++;
this.viewPropNativeValue = value;
}
[customCssProperty.getDefault](): string {
this.cssPropGetDefaultCounter++;
return "customCssPropertyDefaultValue";
}
[customCssProperty.setNative](value: string) {
this.cssPropCounter++;
this.cssPropNativeValue = value;
}
[customCssAnimationProperty.getDefault](): string {
this.cssAnimPropGetDefaultCounter++;
return "customCssAnimationPropertyDefaultValue";
}
[customCssAnimationProperty.setNative](value: string) {
this.cssAnimPropCounter++;
this.cssAnimPropNativeValue = value;
}
}
customCssProperty.register(Style);
customCssAnimationProperty.register(Style);
customViewProperty.register(TestView);
const inheritanceTestDefaultValue = 42;
const inheritanceTestProperty = new InheritedProperty<TestView, number>({ name: "inheritanceTest", defaultValue: inheritanceTestDefaultValue });
inheritanceTestProperty.register(TestView);
const booleanInheritanceTestDefaultValue = true;
const booleanInheritanceTestProperty = new InheritedProperty<TestView, boolean>({ name: "booleanInheritanceTest", defaultValue: booleanInheritanceTestDefaultValue });
booleanInheritanceTestProperty.register(TestView);
const dummyProperty = new InheritedProperty<TestView, number>({ name: "dummy", defaultValue: 0 });
dummyProperty.register(TestView);
/////// TestView definition END
export function test_NativeSetter_not_called_when_property_is_not_set() {
const testView = new TestView("view");
helper.buildUIAndRunTest(testView, () => {
TKUnit.assertEqual(testView.viewPropCounter, 0, "Native setter should not be called if value is not set.");
TKUnit.assertEqual(testView.cssPropCounter, 0, "Native setter should not be called if value is not set.");
TKUnit.assertEqual(testView.cssAnimPropCounter, 0, "Native setter should not be called if value is not set.");
});
};
export function test_GetDefault_not_called_when_property_is_not_set() {
const testView = new TestView("view");
helper.buildUIAndRunTest(testView, () => {
TKUnit.assertEqual(testView.viewPropGetDefaultCounter, 0, "Get default should not be called if value is not set.");
TKUnit.assertEqual(testView.cssPropGetDefaultCounter, 0, "Get default should not be called if value is not set.");
TKUnit.assertEqual(testView.cssAnimPropGetDefaultCounter, 0, "Get default should not be called if value is not set.");
});
};
export function test_NativeSetter_called_only_once_with_localValue() {
const testView = new TestView("view");
testView.customCssProperty = "testCssValue";
testView.customCssAnimationProperty = "testCssAnimValue";
testView.custom = "testViewValue";
helper.buildUIAndRunTest(testView, () => {
TKUnit.assertEqual(testView.cssPropNativeValue, "testCssValue", "Native value");
TKUnit.assertEqual(testView.cssAnimPropNativeValue, "testCssAnimValue", "Native value");
TKUnit.assertEqual(testView.viewPropNativeValue, "testViewValue", "Native value");
TKUnit.assertEqual(testView.cssPropCounter, 1, "NativeSetter count called once");
TKUnit.assertEqual(testView.cssAnimPropCounter, 1, "NativeSetter count called once");
TKUnit.assertEqual(testView.viewPropCounter, 1, "NativeSetter count called once");
TKUnit.assertEqual(testView.cssPropGetDefaultCounter, 1, "GetDefault count called once");
TKUnit.assertEqual(testView.cssAnimPropGetDefaultCounter, 1, "GetDefault count called once");
TKUnit.assertEqual(testView.viewPropGetDefaultCounter, 1, "GetDefault count called once");
});
};
export function test_NativeSetter_called_only_once_with_localValue_after_added_to_visual_tree() {
const testView = new TestView("view");
helper.buildUIAndRunTest(testView, () => {
testView.customCssProperty = "testCssValue";
testView.customCssAnimationProperty = "testCssAnimValue";
testView.custom = "testViewValue";
TKUnit.assertEqual(testView.cssPropNativeValue, "testCssValue", "Native value");
TKUnit.assertEqual(testView.cssAnimPropNativeValue, "testCssAnimValue", "Native value");
TKUnit.assertEqual(testView.viewPropNativeValue, "testViewValue", "Native value");
TKUnit.assertEqual(testView.cssPropCounter, 1, "NativeSetter count called once");
TKUnit.assertEqual(testView.cssAnimPropCounter, 1, "NativeSetter count called once");
TKUnit.assertEqual(testView.viewPropCounter, 1, "NativeSetter count called once");
TKUnit.assertEqual(testView.cssPropGetDefaultCounter, 1, "GetDefault count called once");
TKUnit.assertEqual(testView.cssAnimPropGetDefaultCounter, 1, "GetDefault count called once");
TKUnit.assertEqual(testView.viewPropGetDefaultCounter, 1, "GetDefault count called once");
});
};
export function test_NativeSetter_called_only_once_with_cssValue() {
const testView = new TestView("view");
testView.id = "myID";
const pageCSS = `
#myID {
custom: testViewValue;
custom-css-property: testCssValue;
custom-css-animation-property: testCssAnimValue;
}`;
helper.buildUIAndRunTest(testView, () => {
TKUnit.assertEqual(testView.cssPropCounter, 1, "CssNativeSetter count called once");
TKUnit.assertEqual(testView.viewPropCounter, 1, "ViewNativeSetter count called once");
TKUnit.assertEqual(testView.cssAnimPropCounter, 1, "CssAnimationNativeSetter count called once");
TKUnit.assertEqual(testView.cssPropNativeValue, "testCssValue", "Native value");
TKUnit.assertEqual(testView.cssAnimPropNativeValue, "testCssAnimValue", "Native value");
TKUnit.assertEqual(testView.viewPropNativeValue, "testViewValue", "Native value");
}, pageCSS);
};
export function test_NativeSetter_called_only_once_with_cssValue_and_localValue() {
const testView = new TestView("view");
testView.id = "myID";
testView.customCssProperty = "testCssValueLocal";
testView.customCssAnimationProperty = "testCssAnimationValueLocal";
testView.custom = "testViewValueLocal";
const pageCSS = `
#myID {
custom-css-property: testCssValueCSS;
custom: testViewValueCSS;
custom-css-animation-property: testCssAnimValueCSS;
}`;
helper.buildUIAndRunTest(testView, () => {
TKUnit.assertEqual(testView.cssPropCounter, 1, "CssNativeSetter count called once");
TKUnit.assertEqual(testView.viewPropCounter, 1, "ViewNativeSetter count called once");
TKUnit.assertEqual(testView.cssAnimPropCounter, 1, "CssAnimNativeSetter count called once");
// CSS property set form css has CSS value source, which is weaker than local value
TKUnit.assertEqual(testView.cssPropNativeValue, "testCssValueLocal", "Native value");
TKUnit.assertEqual(testView.cssAnimPropNativeValue, "testCssAnimationValueLocal", "Native value");
// View property set from CSS sets local value
TKUnit.assertEqual(testView.viewPropNativeValue, "testViewValueCSS", "Native value");
}, pageCSS);
};
export function test_NativeSetter_called_only_once_with_multiple_sets() {
const testView = new TestView("view");
testView.custom = "testViewValue1";
testView.custom = "testViewValue2";
testView.customCssProperty = "testCssValue1";
testView.customCssProperty = "testCssValue2";
testView.customCssAnimationProperty = "testCssAnimValue1";
testView.customCssAnimationProperty = "testCssAnimValue2";
helper.buildUIAndRunTest(testView, () => {
TKUnit.assertEqual(testView.cssPropCounter, 1, "NativeSetter count called once");
TKUnit.assertEqual(testView.cssAnimPropCounter, 1, "NativeSetter count called once");
TKUnit.assertEqual(testView.viewPropCounter, 1, "NativeSetter count called once");
TKUnit.assertEqual(testView.cssPropNativeValue, "testCssValue2", "Native value");
TKUnit.assertEqual(testView.cssAnimPropNativeValue, "testCssAnimValue2", "Native value");
TKUnit.assertEqual(testView.viewPropNativeValue, "testViewValue2", "Native value");
});
};
export function test_NativeSetter_called_when_add_and_remove() {
const firstView = new TestView("firstView");
const secondView = new TestView("secondView");
secondView.customCssProperty = "testCssValue";
secondView.custom = "testViewValue";
helper.buildUIAndRunTest(firstView, () => {
TKUnit.assertEqual(secondView.cssPropCounter, 0, "1");
TKUnit.assertEqual(secondView.viewPropCounter, 0, "2");
// Add to visual tree
firstView.addChild(secondView);
TKUnit.assertEqual(secondView.cssPropCounter, 1, "3");
TKUnit.assertEqual(secondView.viewPropCounter, 1, "4");
// Set new value
secondView.customCssProperty = "test2";
secondView.custom = "test2";
TKUnit.assertEqual(secondView.cssPropCounter, 2, "5");
TKUnit.assertEqual(secondView.viewPropCounter, 2, "6");
// Remove from visual tree
firstView.removeChild(secondView);
TKUnit.assertEqual(secondView.cssPropCounter, 2, "7");
TKUnit.assertEqual(secondView.viewPropCounter, 2, "8");
});
};
export function test_NativeSetter_called_when_add_and_remove_and_recycled() {
const firstView = new TestView("firstView");
const secondView = new TestView("secondView");
secondView.recycleNativeView = isAndroid ? "always" : "never";
secondView.customCssProperty = "testCssValue";
secondView.custom = "testViewValue";
helper.buildUIAndRunTest(firstView, () => {
TKUnit.assertEqual(secondView.cssPropCounter, 0, "1");
TKUnit.assertEqual(secondView.viewPropCounter, 0, "2");
// Add to visual tree
firstView.addChild(secondView);
TKUnit.assertEqual(secondView.cssPropCounter, 1, "3");
TKUnit.assertEqual(secondView.viewPropCounter, 1, "4");
// Set new value
secondView.customCssProperty = "test2";
secondView.custom = "test2";
TKUnit.assertEqual(secondView.cssPropCounter, 2, "5");
TKUnit.assertEqual(secondView.viewPropCounter, 2, "6");
// Remove from visual tree
firstView.removeChild(secondView);
// we don't recycle nativeViews on iOS yet so reset is not called.
TKUnit.assertEqual(secondView.cssPropCounter, isIOS ? 2 : 3, "7");
TKUnit.assertEqual(secondView.viewPropCounter, isIOS ? 2 : 3, "8");
});
};
export function test_InheritableProperties_getValuesFromParent() {
const testValue = 35;
const test = function (views: Array<View>) {
const bottomView = <TestView>views[3];
TKUnit.assert(bottomView.inheritanceTest === testValue, "Expected: " + testValue + " Actual: " + bottomView.inheritanceTest);
};
const firstView = new TestView("firstView");
firstView.inheritanceTest = testValue;
const secondView = new TestView("secondView");
const thirdView = new TestView("thirdView");
firstView.addChild(secondView);
secondView.addChild(thirdView);
helper.do_PageTest(test, firstView, secondView, thirdView);
};
export function test_BooleanInheritableProperties_getValuesFromParent() {
const testValue = false;
const test = function (views: Array<View>) {
const bottomView = <TestView>views[3];
TKUnit.assert(bottomView.booleanInheritanceTest === testValue, "Expected: " + testValue + " Actual: " + bottomView.booleanInheritanceTest);
};
const firstView = new TestView("firstView");
firstView.booleanInheritanceTest = testValue;
const secondView = new TestView("secondView");
const thirdView = new TestView("thirdView");
firstView.addChild(secondView);
secondView.addChild(thirdView);
helper.do_PageTest(test, firstView, secondView, thirdView);
};
export function test_InheritableProperties_resetValuesOnRemoveFromVisualTree() {
const testValue = 35;
const test = function (views: Array<View>) {
const bottomView = <TestView>views[3];
TKUnit.assert(bottomView.inheritanceTest === testValue, "Expected: " + testValue + " Actual: " + bottomView.inheritanceTest);
(<TestView>views[2]).removeChild(bottomView);
TKUnit.assert(bottomView.inheritanceTest === inheritanceTestDefaultValue, "Expected: " + inheritanceTestDefaultValue + " Actual: " + bottomView.inheritanceTest);
};
const firstView = new TestView("firstView");
firstView.inheritanceTest = testValue;
const secondView = new TestView("secondView");
const thirdView = new TestView("thirdView");
firstView.addChild(secondView);
secondView.addChild(thirdView);
helper.do_PageTest(test, firstView, secondView, thirdView);
};
export function test_InheritableProperties_DefaultValue() {
const test = function (views: Array<View>) {
const bottomView = <TestView>views[3];
TKUnit.assert(bottomView.inheritanceTest === inheritanceTestDefaultValue, "Expected: " + inheritanceTestDefaultValue + " Actual: " + bottomView.inheritanceTest);
};
const firstView = new TestView("firstView");
const secondView = new TestView("secondView");
const thirdView = new TestView("thirdView");
secondView.addChild(thirdView);
firstView.addChild(secondView);
helper.do_PageTest(test, firstView, secondView, thirdView);
};
export function test_InheritableProperties_ChangeNotification() {
const testValue = 35;
const test = function (views: Array<View>) {
const topView = <TestView>views[1];
topView.inheritanceTest = testValue;
const bottomView = <TestView>views[3];
bottomView.bind({ targetProperty: "dummy", sourceProperty: "inheritanceTest" }, bottomView);
TKUnit.assert(bottomView.dummy === testValue, "Expected: " + testValue + " Actual: " + bottomView.dummy);
};
const firstView = new TestView("firstView");
const secondView = new TestView("secondView");
const thirdView = new TestView("thirdView");
secondView.addChild(thirdView);
firstView.addChild(secondView);
helper.do_PageTest(test, firstView, secondView, thirdView);
};
function property_binding_test(propName: string, firstValue: any, secondValue: any, view?: View) {
let actualResult;
const model = new observable.Observable();
model.set(propName, firstValue);
const options: bindable.BindingOptions = {
sourceProperty: propName,
targetProperty: propName
};
if (!view) {
view = new TestView("view");
}
view.bind(options, model);
actualResult = view.get(propName);
TKUnit.assertEqual(actualResult, firstValue);
model.set(propName, secondValue);
actualResult = view.get(propName);
TKUnit.assertEqual(actualResult, secondValue);
}
function property_binding_style_test(propName: string, firstValue: any, secondValue: any, view?: View) {
let actualResult;
const model = new observable.Observable();
model.set(propName, firstValue);
const options: bindable.BindingOptions = {
sourceProperty: propName,
targetProperty: "style." + propName
};
if (!view) {
view = new TestView("view");
}
view.bind(options, model);
actualResult = view.style.get(propName);
TKUnit.assertEqual(actualResult, firstValue);
model.set(propName, secondValue);
actualResult = view.style.get(propName);
TKUnit.assertEqual(actualResult, secondValue);
}
export function test_binding_width() {
property_binding_test("width", 42, 43);
};
export function test_binding_height() {
property_binding_test("height", 42, 43);
};
export function test_binding_minWidth() {
property_binding_test("minWidth", 42, 43);
};
export function test_binding_minHeight() {
property_binding_test("minHeight", 42, 43);
};
export function test_binding_horizontalAlignment() {
property_binding_test("horizontalAlignment", "left", "right");
};
export function test_binding_verticalAlignment() {
property_binding_test("verticalAlignment", "top", "bottom");
};
export function test_binding_marginLeft() {
property_binding_test("marginLeft", 42, 43);
};
export function test_binding_marginTop() {
property_binding_test("marginTop", 42, 43);
};
export function test_binding_marginRight() {
property_binding_test("marginRight", 42, 43);
};
export function test_binding_marginBottom() {
property_binding_test("marginBottom", 42, 43);
};
export function test_binding_visibility() {
property_binding_test("visibility", "collapse", "visible");
};
export function test_binding_isEnabled() {
property_binding_test("isEnabled", false, true);
};
export function test_binding_isUserInteractionEnabled() {
property_binding_test("isUserInteractionEnabled", false, true);
};
export function test_binding_id() {
property_binding_test("id", "id1", "id2");
};
export function test_binding_cssClass() {
property_binding_test("cssClass", "class1", "class2");
};
export function test_binding_className() {
property_binding_test("className", "class1", "class2");
};
export function test_binding_style_color() {
property_binding_style_test("color", new Color("#FF0000"), new Color("#00FF00"));
};
export function test_binding_style_backgroundColor() {
property_binding_style_test("backgroundColor", new Color("#FF0000"), new Color("#00FF00"));
};
export function test_binding_style_fontSize() {
property_binding_style_test("fontSize", 5, 10);
};
export function test_binding_style_textAlignment() {
property_binding_style_test("textAlignment", "right", "center");
};
export function test_binding_style_width() {
property_binding_style_test("width", 42, 43);
};
export function test_binding_style_height() {
property_binding_style_test("height", 42, 43);
};
export function test_binding_style_minWidth() {
property_binding_style_test("minWidth", 42, 43);
};
export function test_binding_style_minHeight() {
property_binding_style_test("minHeight", 42, 43);
};
export function test_binding_style_margin() {
property_binding_style_test("margin", "1 2 3 4", "2 3 2 3");
};
export function test_binding_style_marginLeft() {
property_binding_style_test("marginLeft", 42, 43);
};
export function test_binding_style_marginTop() {
property_binding_style_test("marginTop", 42, 43);
};
export function test_binding_style_marginRight() {
property_binding_style_test("marginRight", 42, 43);
};
export function test_binding_style_marginBottom() {
property_binding_style_test("marginBottom", 42, 43);
};
export function test_binding_style_padding() {
property_binding_style_test("padding", "1 2 3 4", "2 3 2 3");
};
export function test_binding_style_paddingLeft() {
property_binding_style_test("paddingLeft", 42, 43);
};
export function test_binding_style_paddingTop() {
property_binding_style_test("paddingTop", 42, 43);
};
export function test_binding_style_paddingRight() {
property_binding_style_test("paddingRight", 42, 43);
};
export function test_binding_style_paddingBottom() {
property_binding_style_test("paddingBottom", 42, 43);
};
export function test_binding_style_horizontalAlignment() {
property_binding_style_test("horizontalAlignment", "left", "right");
};
export function test_binding_style_verticalAlignment() {
property_binding_style_test("verticalAlignment", "top", "bottom");
};
export function test_binding_style_visibility() {
property_binding_style_test("visibility", "collapse", "visible");
};
export function test_binding_style_opacity() {
property_binding_style_test("opacity", 0.5, 0.6);
};
function _createLabelWithBorder(): View {
const lbl = new Label();
lbl.borderRadius = 10;
lbl.borderWidth = 2;
lbl.borderColor = new Color("#FF0000");
lbl.backgroundColor = new Color("#FFFF00");
return lbl;
}
export function testIsVisible() {
const lbl = new Label();
helper.buildUIAndRunTest(lbl, function (views: Array<View>) {
TKUnit.assertEqual(lbl.visibility, "visible");
TKUnit.assertEqual(lbl.isCollapsed, false);
lbl.visibility = "collapse";
TKUnit.assertEqual(lbl.visibility, "collapse");
TKUnit.assertEqual(lbl.isCollapsed, true);
});
};
export function testSetInlineStyle() {
const lbl = new Label();
const expectedColor = "#FF0000";
const expectedBackgroundColor = "#FF0000";
lbl.setInlineStyle(`color: ${expectedColor};background-color: ${expectedBackgroundColor};`);
helper.buildUIAndRunTest(lbl, function (views: Array<View>) {
TKUnit.assertEqual(lbl.color.hex, expectedColor);
TKUnit.assertEqual((<Color>lbl.backgroundColor).hex, expectedBackgroundColor);
});
};
export function testBackgroundColor() {
helper.buildUIAndRunTest(_createLabelWithBorder(), function (views: Array<View>) {
const lbl = views[0];
helper.waitUntilLayoutReady(lbl);
TKUnit.assertEqual(definition.checkNativeBackgroundColor(lbl), true, "BackgroundColor not applied correctly!");
});
};
export function testBackgroundImage() {
const lbl = _createLabelWithBorder();
lbl.className = "myClass";
helper.buildUIAndRunTest(lbl, function (views: Array<View>) {
const page = <Page>views[1];
page.css = ".myClass { background-image: url('~/logo.png') }";
TKUnit.assertEqual(definition.checkNativeBackgroundImage(lbl), true, "Style background-image not loaded correctly.");
});
};
export function testBackgroundShorthand_With_EmptyBorder() {
// Related to issue https://github.com/NativeScript/NativeScript/issues/4415
const lbl = new Label();
lbl.className = "test";
const css = ".test { border-width: 0; background: transparent; }";
helper.buildUIAndRunTest(lbl, (views: Array<View>) => {
helper.waitUntilLayoutReady(lbl);
}, css);
};
export function test_automation_text_default_value() {
let view = new Button();
TKUnit.assertTrue(view.automationText === undefined, "AutomationText default value should be UNDEFINED.");
}
export function test_getLocationInWindow_IsUndefinedWhenNotInTheVisualTree() {
const label = new Label();
TKUnit.assertNull(label.getLocationInWindow());
};
export function test_getLocationOnScreen_IsUndefinedWhenNotInTheVisualTree() {
const label = new Label();
TKUnit.assertNull(label.getLocationOnScreen());
};
const delta = 1;
export function test_getLocationRelativeToOtherView() {
const a1 = new AbsoluteLayout();
a1.width = 200;
a1.height = 200;
a1.backgroundColor = new Color("red");
const a2 = new AbsoluteLayout();
a2.width = 100;
a2.height = 100;
AbsoluteLayout.setLeft(a2, 10);
AbsoluteLayout.setTop(a2, 10);
a2.backgroundColor = new Color("green");
const label = new Label();
label.text = "label";
label.id = "label";
label.width = 70;
label.height = 30;
AbsoluteLayout.setLeft(label, 10);
AbsoluteLayout.setTop(label, 10);
a2.backgroundColor = new Color("yellow");
a2.addChild(label);
a1.addChild(a2);
helper.buildUIAndRunTest(a1, function (views: Array<View>) {
helper.waitUntilLayoutReady(a1);
const labelInA2 = label.getLocationRelativeTo(a2);
const labelInA1 = label.getLocationRelativeTo(a1);
const a2InA1 = a2.getLocationRelativeTo(a1);
TKUnit.assertAreClose(labelInA2.x, 10, delta, "labelInA2.x");
TKUnit.assertAreClose(labelInA2.y, 10, delta, "labelInA2.y");
TKUnit.assertAreClose(labelInA1.x, 20, delta, "labelInA1.x");
TKUnit.assertAreClose(labelInA1.y, 20, delta, "labelInA1.y");
TKUnit.assertAreClose(a2InA1.x, 10, delta, "a2InA1.x");
TKUnit.assertAreClose(a2InA1.y, 10, delta, "a2InA1.y");
});
};
export function test_getActualSize() {
const label = new Label();
label.width = 100;
label.height = 200;
helper.buildUIAndRunTest(label, function (views: Array<View>) {
helper.waitUntilLayoutReady(label);
const actualSize = label.getActualSize();
TKUnit.assertAreClose(actualSize.width, 100, delta, "actualSize.width");
TKUnit.assertAreClose(actualSize.height, 200, delta, "actualSize.height");
});
};
export function test_background_image_doesnt_throw() {
var btn = new Button();
// There is no need to wait until image is downloaded.
// It was throwing an exception when starting the download...
btn.style.backgroundImage = 'https://www.bodybuilding.com/images/2016/june/8-benefits-to-working-out-in-the-morning-header-v2-830x467.jpg';
helper.buildUIAndRunTest(btn, function (views: Array<View>) {
helper.waitUntilLayoutReady(btn);
});
}
export function test_shorthand_property_sets_composite_properties() {
var view = new TestView("view1");
view.customShortHand = "left,right";
TKUnit.assertEqual(view.customCssA, "left", "Expected customCssAProperty to be 'left'.");
TKUnit.assertEqual(view.customCssB, "right", "Expected customCssAProperty to be 'right'.");
}
export function test_shorthand_property_is_set_by_composite_properties() {
var view = new TestView("view1");
view.customCssA = "left";
view.customCssB = "right";
TKUnit.assertEqual(view.customShortHand, "left,right");
}
export function test_shorthand_property_doesnt_cache() {
var view = new TestView("view1");
view.customShortHand = "left,right";
TKUnit.assertEqual(view.customCssA, "left", "Expected customCssA to be 'left' the first time.");
TKUnit.assertEqual(view.customCssB, "right", "Expected customCssA to be 'right' the second time.");
view.customCssA = "top";
view.customCssB = "bottom";
TKUnit.assertEqual(view.customShortHand, "top,bottom", "Expected customShortHand to be 'top,bottom' calculated from the composite properties.");
// This used to fail in https://github.com/NativeScript/NativeScript/issues/4450 the customShortHand would cache "left,right" when initially set,
// And won't run internal logic as the new value is "same" as the previous value, not taking into account that meanwhile the composite properties were set.
view.customShortHand = "left,right";
TKUnit.assertEqual(view.customCssA, "left", "Expected customCssA to be 'left' the second time.");
TKUnit.assertEqual(view.customCssB, "right", "Expected customCssA to be 'right' the second time.");
}