Files
NativeScript/tests/app/ui/dependency-observable-tests.ts
Hristo Hristov 9ed1986d20 fix tslint
2016-06-08 18:21:08 +03:00

367 lines
16 KiB
TypeScript

// <snippet module="ui/core/dependency-observable" title="dependency-observable">
// # DependencyObservable
// DependencyObservable is a fundamental building block in the NativeScript visual tree (DOM).
// It provides enhanced property system allowing for various value modifiers on a per property basis.
// This enables cascading values - e.g. default vs. inherited vs. local.
// Load the module using the following code:
// ``` JavaScript
import dependencyObservableModule = require("ui/core/dependency-observable");
// ```
// </snippet>
import TKUnit = require("../TKUnit");
import types = require("utils/types");
import observableModule = require("data/observable");
var currentChangeData: dependencyObservableModule.PropertyChangeData;
var propertyNameCount = 0;
function generatePropertyName() {
var name = "test" + propertyNameCount++;
return name;
}
function onTestPropertyChanged(data: dependencyObservableModule.PropertyChangeData) {
currentChangeData = data;
}
function validateDOChangeData(obj: TestDO, property: dependencyObservableModule.Property, oldValue: any, newValue: any) {
TKUnit.assert(types.isDefined(currentChangeData), "metadata.onValueChanged function not called.");
TKUnit.assert(currentChangeData.object === obj, "metadata.onValueChanged function called with wrong object member.");
TKUnit.assert(currentChangeData.property === property, "metadata.onValueChanged method called with wrong property member");
TKUnit.assert(currentChangeData.newValue === newValue, "metadata.onValueChanged method called with wrong newValue member");
TKUnit.assert(currentChangeData.oldValue === oldValue, "metadata.onValueChanged method called with wrong oldValue member");
TKUnit.assert(currentChangeData.eventName === observableModule.Observable.propertyChangeEvent, "metadata.onValueChanged method called with wrong eventName member");
}
function validateChangeData(data: observableModule.PropertyChangeData, obj: observableModule.Observable, propertyName: string, newValue: any) {
TKUnit.assert(types.isDefined(data), "DependencyObservable.on for propertyChange not called.");
TKUnit.assert(data.object === obj, "DependencyObservable.on called with wrong object member.");
TKUnit.assert(data.propertyName === propertyName, "DependencyObservable.on called with wrong propertyName member");
TKUnit.assert(data.value === newValue, "DependencyObservable.on called with wrong value member");
TKUnit.assert(data.eventName === observableModule.Observable.propertyChangeEvent, "DependencyObservable.on method called with wrong eventName member");
}
// <snippet module="ui/core/dependency-observable" title="dependency-observable">
// ### Creating a Property
// The property backing mechanism in each DependencyObservable instance is implemented via the Property class.
// Basically you create a new Property for a class (type):
// ``` JavaScript
var testProperty = new dependencyObservableModule.Property(
"test",
"TestDO",
new dependencyObservableModule.PropertyMetadata(
false,
dependencyObservableModule.PropertyMetadataSettings.None /*0*/,
onTestPropertyChanged
)
);
// ```
// </snippet>
var testProperty1 = new dependencyObservableModule.Property(
"test1",
"TestDO",
new dependencyObservableModule.PropertyMetadata(
0,
dependencyObservableModule.PropertyMetadataSettings.None /*0*/,
onTestPropertyChanged
)
);
function validateProperty(value: any): boolean {
return types.isNumber(value) && value >= 0;
}
var testPropertyWithValidation = new dependencyObservableModule.Property(
"testWithValidation",
"TestDO",
new dependencyObservableModule.PropertyMetadata(
0,
dependencyObservableModule.PropertyMetadataSettings.None /*0*/,
onTestPropertyChanged,
validateProperty
)
);
class TestDO extends dependencyObservableModule.DependencyObservable {
get test(): boolean {
return this._getValue(testProperty);
}
set test(value: boolean) {
this._setValue(testProperty, value);
}
get test1(): number {
return this._getValue(testProperty1);
}
set test1(value: number) {
this._setValue(testProperty1, value);
}
get testWithValidation(): number {
return this._getValue(testPropertyWithValidation);
}
set testWithValidation(value: number) {
this._setValue(testPropertyWithValidation, value);
}
public _onPropertyChanged(property: dependencyObservableModule.Property, oldValue: any, newValue: any) {
super._onPropertyChanged(property, oldValue, newValue);
}
}
export function test_DO_Members_AreDefined() {
var obj = new dependencyObservableModule.DependencyObservable();
TKUnit.assert(types.isDefined(obj._setValue), "DependencyObservable._setValue is undefined.");
TKUnit.assert(types.isDefined(obj._getValue), "DependencyObservable._getValue is undefined.");
TKUnit.assert(types.isDefined(obj._getValueSource), "DependencyObservable._getValueSource is undefined.");
TKUnit.assert(types.isDefined(obj._resetValue), "DependencyObservable._resetValue is undefined.");
TKUnit.assert(types.isDefined(obj._onPropertyChanged), "DependencyObservable._resetValue is undefined.");
TKUnit.assert(types.isDefined(obj._eachSetProperty), "DependencyObservable._resetValue is undefined.");
}
export function test_NewProperty_WillThrow_If_Name_IsInvalid() {
var thrown = false;
try {
/* tslint:disable:no-unused-variable */
var p = new dependencyObservableModule.Property("", "", undefined);
/* tslint:enable:no-unused-variable */
}
catch (e) {
thrown = true;
TKUnit.assert(e.message === "Name should not be null or empty string.", "Invalid error message");
}
TKUnit.assert(thrown, "Should not create a Property with invalid name.");
}
export function test_NewProperty_WillThrow_If_OwnerType_IsInvalid() {
var thrown = false;
try {
/* tslint:disable:no-unused-variable */
var p = new dependencyObservableModule.Property(generatePropertyName(), "", undefined);
/* tslint:enable:no-unused-variable */
}
catch (e) {
thrown = true;
TKUnit.assert(e.message === "OwnerType should not be null or empty string.", "Invalid error message");
}
TKUnit.assert(thrown, "Should not create a Property with invalid owner type.");
}
export function test_NewProperty_WillThrow_If_Metadata_IsInvalid() {
var thrown = false;
var p;
try {
// check for undefined
p = new dependencyObservableModule.Property(generatePropertyName(), "testOwner", undefined);
}
catch (e) {
thrown = true;
TKUnit.assert(e.message === "Expected valid PropertyMetadata instance.", "Invalid error message");
}
TKUnit.assert(thrown, "Should not create a Property with undefined metadata.");
thrown = false;
try {
// check for invalid type
var metadata: any = {};
p = new dependencyObservableModule.Property(generatePropertyName(), "testOwner", metadata);
}
catch (e) {
thrown = true;
TKUnit.assert(e.message === "Expected valid PropertyMetadata instance.", "Invalid error message");
}
TKUnit.assert(thrown, "Should not create a Property with invalid metadata type.");
}
export function test_NewProperty_WillThrow_If_Key_AlreadyRegistered() {
var thrown = false;
try {
/* tslint:disable:no-unused-variable */
var p = new dependencyObservableModule.Property("test", "testOwner", new dependencyObservableModule.PropertyMetadata(0));
var p1 = new dependencyObservableModule.Property("test", "testOwner", new dependencyObservableModule.PropertyMetadata(0));
/* tslint:enable:no-unused-variable */
}
catch (e) {
thrown = true;
TKUnit.assert(e.message === "Property test already registered for type testOwner.", "Invalid error message");
}
TKUnit.assert(thrown, "Should not create a Property with invalid name.");
}
export function test_Property_Id_IsUnique() {
var p = new dependencyObservableModule.Property(generatePropertyName(), "testOwner", new dependencyObservableModule.PropertyMetadata(0));
var p1 = new dependencyObservableModule.Property(generatePropertyName(), "testOwner", new dependencyObservableModule.PropertyMetadata(0));
TKUnit.assert(p.id !== p1.id, "Property.id should be unique.");
}
export function test_PropertyMetadataSettings_HasValid_Memberes() {
TKUnit.assert(dependencyObservableModule.PropertyMetadataSettings.None === 0, "PropertyMetadataSettings.None not defined correctly.");
TKUnit.assert(dependencyObservableModule.PropertyMetadataSettings.AffectsLayout === 1, "PropertyMetadataSettings.AffectsLayout not defined correctly.");
TKUnit.assert(dependencyObservableModule.PropertyMetadataSettings.AffectsStyle === 2, "PropertyMetadataSettings.AffectsStyle not defined correctly.");
TKUnit.assert(dependencyObservableModule.PropertyMetadataSettings.Inheritable === 4, "PropertyMetadataSettings.Inheritable not defined correctly.");
}
export function test_ValueSource_HasValid_Memberes() {
TKUnit.assert(dependencyObservableModule.ValueSource.Default === 0, "ValueSource.None not defined correctly.");
TKUnit.assert(dependencyObservableModule.ValueSource.Inherited === 1, "ValueSource.Inherited not defined correctly.");
TKUnit.assert(dependencyObservableModule.ValueSource.Css === 2, "ValueSource.Css not defined correctly.");
TKUnit.assert(dependencyObservableModule.ValueSource.Local === 3, "ValueSource.Local not defined correctly.");
TKUnit.assert(dependencyObservableModule.ValueSource.VisualState === 4, "ValueSource.VisualState not defined correctly.");
}
export function test_PropertyMetadata_Options() {
var options =
dependencyObservableModule.PropertyMetadataSettings.AffectsLayout |
dependencyObservableModule.PropertyMetadataSettings.AffectsStyle |
dependencyObservableModule.PropertyMetadataSettings.Inheritable;
var p = new dependencyObservableModule.Property(generatePropertyName(), "testOwner", new dependencyObservableModule.PropertyMetadata(0, options));
TKUnit.assert(p.affectsLayout === true, "Property.affectsLayout not working as expected.");
TKUnit.assert(p.affectsStyle === true, "Property.affectsStyle not working as expected.");
TKUnit.assert(p.inheritable === true, "Property.inheritable not working as expected.");
TKUnit.assert(p.metadata.options === options, "PropertyMetadata.options not properly set.");
}
export function test_PropertyEntry_effectiveValue() {
var entry = new dependencyObservableModule.PropertyEntry();
// default value
TKUnit.assertEqual(entry.effectiveValue, undefined, "effectiveValue should be undefined.");
TKUnit.assertEqual(entry.valueSource, dependencyObservableModule.ValueSource.Default, "ValueSource.Default not working as expected.");
// local value
entry.localValue = 10;
entry.resetValue();
// default value
TKUnit.assertEqual(entry.effectiveValue, undefined, "ValueSource.Default not working as expected.");
TKUnit.assertEqual(entry.valueSource, dependencyObservableModule.ValueSource.Default, "ValueSource.Default not working as expected.");
}
export function test_DependencyObservable_get_set_AreOverriden() {
var dO = new TestDO();
dO.test = true;
TKUnit.assert(dO.get("test") === true, "DependencyObservable should override Observable.get");
dO.set("test", false);
TKUnit.assert(dO.test === false, "DependencyObservable should override Observable.set");
}
export function test_DependencyObservable_getValue_setValue() {
var dO = new TestDO();
// implicitly use ValueSource.Local when not specified
dO._setValue(testProperty1, 5);
TKUnit.assertEqual(dO.test1, 5, "expected true after _setValue.");
TKUnit.assertEqual(dO._getValueSource(testProperty1), dependencyObservableModule.ValueSource.Local, "_setValue without third parameter should use ValueSource.Local");
dO._setValue(testProperty1, 10, dependencyObservableModule.ValueSource.Inherited);
TKUnit.assertEqual(dO.test1, 5, "ValueSource.Local should have higher priority than Inherited.");
// revert to default value
dO._resetValue(testProperty1);
TKUnit.assertEqual(dO.test1, 10, "_resetValue should revert to inheritedValue");
// test the ValueSource parameter
dO._setValue(testProperty1, 10, dependencyObservableModule.ValueSource.Inherited);
TKUnit.assertEqual(dO.test1, 10, "_setValue with three parameters not working as expected.");
TKUnit.assertEqual(dO._getValueSource(testProperty1), dependencyObservableModule.ValueSource.Inherited, "expected ValueSource.Inherited");
dO._setValue(testProperty1, 20, dependencyObservableModule.ValueSource.Local);
TKUnit.assertEqual(dO.test1, 20, "_setValue with three parameters not working as expected.");
TKUnit.assertEqual(dO._getValueSource(testProperty1), dependencyObservableModule.ValueSource.Local, "expected ValueSource.Local");
// reset the Local value and verify the effectiveValue will be reverted to the Inherited one.
dO._resetValue(testProperty1, dependencyObservableModule.ValueSource.Local);
TKUnit.assertEqual(dO.test1, 10, "_resetValue for ValueSource not working as expected.");
TKUnit.assertEqual(dO._getValueSource(testProperty1), dependencyObservableModule.ValueSource.Inherited, "expected ValueSource.Inherited");
}
export function test_PropertyMetadata_onValueChanged_Callback_IsInvoked() {
currentChangeData = undefined;
var dO = new TestDO();
dO.test = true;
validateDOChangeData(dO, testProperty, false, true);
currentChangeData = undefined;
var dO1 = new TestDO();
dO1.test1 = 10;
validateDOChangeData(dO1, testProperty1, 0, 10);
// reset value
currentChangeData = undefined;
dO1._resetValue(testProperty1);
validateDOChangeData(dO1, testProperty1, 10, 0);
currentChangeData = undefined;
dO1._setValue(testProperty1, 10, dependencyObservableModule.ValueSource.Inherited);
validateDOChangeData(dO1, testProperty1, 0, 10);
currentChangeData = undefined;
dO1._setValue(testProperty1, 20, dependencyObservableModule.ValueSource.Local);
validateDOChangeData(dO1, testProperty1, 10, 20);
currentChangeData = undefined;
dO1._resetValue(testProperty1, dependencyObservableModule.ValueSource.Local);
validateDOChangeData(dO1, testProperty1, 20, 10);
}
export function test_Observable_on_propertyChange_IsRaised() {
var dO1 = new TestDO();
var changeData: observableModule.PropertyChangeData;
dO1.on(observableModule.Observable.propertyChangeEvent, function (data: observableModule.PropertyChangeData) {
changeData = data;
});
dO1.test1 = 10;
validateChangeData(changeData, dO1, "test1", 10);
// reset value
changeData = undefined;
dO1._resetValue(testProperty1);
validateChangeData(changeData, dO1, "test1", 0);
changeData = undefined;
dO1._setValue(testProperty1, 10, dependencyObservableModule.ValueSource.Inherited);
validateChangeData(changeData, dO1, "test1", 10);
changeData = undefined;
dO1._setValue(testProperty1, 20, dependencyObservableModule.ValueSource.Local);
validateChangeData(changeData, dO1, "test1", 20);
changeData = undefined;
dO1._resetValue(testProperty1, dependencyObservableModule.ValueSource.Local);
validateChangeData(changeData, dO1, "test1", 10);
}
export function test_setValue_WillThrow_If_ValueIsInvalid() {
var dO = new TestDO();
TKUnit.assertThrows(
() => {
dO.testWithValidation = -1;
},
"Set invalid value should throw",
"Invalid value -1 for property testWithValidation");
}
export function test_setValue_WillNotThrow_If_ValueIsValid() {
var dO = new TestDO();
// This should not throw.
dO.testWithValidation = 1;
}