@qooxdoo/framework
Version:
The JS Framework for Coders
729 lines (572 loc) • 24.8 kB
JavaScript
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
Copyright:
2007-2008 1&1 Internet AG, Germany, http://www.1und1.de
License:
MIT: https://opensource.org/licenses/MIT
See the LICENSE file in the project's top-level directory for details.
Authors:
* Martin Wittemann (martinwittemann)
************************************************************************ */
/**
* Test-Class for testing the single value binding
*
* @ignore(qx.test.SVB)
* @ignore(qx.test.TwoProperties)
* @ignore(qx.Target)
* @ignore(qx.Test)
*/
qx.Class.define("qx.test.data.singlevalue.Simple",
{
extend : qx.dev.unit.TestCase,
include : qx.dev.unit.MRequirements,
members :
{
__a : null,
__b: null,
setUp : function() {
// create the widgets
this.__a = new qx.test.data.singlevalue.TextFieldDummy();
this.__b = new qx.test.data.singlevalue.TextFieldDummy();
},
tearDown : function() {
qx.data.SingleValueBinding.removeAllBindingsForObject(this.__a);
qx.data.SingleValueBinding.removeAllBindingsForObject(this.__b);
this.__a.dispose();
this.__b.dispose();
},
testStringPropertyBinding : function()
{
qx.data.SingleValueBinding.bind(this.__a, "appearance", this.__b, "appearance");
this.__a.setAppearance("affe");
this.assertEquals("affe", this.__b.getAppearance(), "String binding does not work!");
var affe = new qx.test.data.singlevalue.TextFieldDummy();
affe.setAppearance("Jonny");
qx.data.SingleValueBinding.bind(affe, "appearance", this.__b, "appearance");
this.assertEquals("Jonny", this.__b.getAppearance(), "String binding does not work!");
qx.data.SingleValueBinding.removeAllBindingsForObject(affe);
affe.dispose();
},
testBooleanPropertyBinding : function()
{
qx.data.SingleValueBinding.bind(this.__a, "enabled", this.__b, "enabled");
this.__a.setEnabled(false);
this.assertFalse(this.__b.getEnabled(), "Boolean binding does not work!");
},
testNumberPropertyBinding : function()
{
qx.data.SingleValueBinding.bind(this.__a, "zIndex", this.__b, "zIndex");
this.__a.setZIndex(2456);
this.assertEquals(2456, this.__b.getZIndex(), "Number binding does not work!");
},
testColorPropertyBinding : function()
{
qx.data.SingleValueBinding.bind(this.__a, "backgroundColor", this.__b, "backgroundColor");
this.__a.setBackgroundColor("red");
this.assertEquals("red", this.__b.getBackgroundColor(), "Color binding does not work!");
},
testWrongPropertyNames : function()
{
if (qx.core.Environment.get("qx.debug")) {
var a = this.__a;
var b = this.__b;
// only in source version
if (qx.core.Environment.get("qx.debug")) {
// wrong source
this.assertException(function() {
qx.data.SingleValueBinding.bind(a, "BacccccckgroundColor", b, "backgroundColor");
}, qx.core.AssertionError, null, "Not a wrong property name? (source)");
}
}
},
testWrongEventType : function()
{
if (qx.core.Environment.get("qx.debug")) {
var a = this.__a;
var b = this.__b;
// only in source version
if (qx.core.Environment.get("qx.debug")) {
// wrong eventName
this.assertException(function() {
qx.data.SingleValueBinding.bind(a, "affe", b, "backgroundColor");
}, null, null, "Not a wrong event name? (source)");
}
}
},
testDefaultConversion : function()
{
// String to number
this.__a.setAppearance("0");
qx.data.SingleValueBinding.bind(this.__a, "appearance", this.__b, "zIndex");
this.__a.setAppearance("4879");
this.assertEquals(4879, this.__b.getZIndex(), "String --> Number does not work!");
// number to String
this.__a.setZIndex(568);
qx.data.SingleValueBinding.bind(this.__a, "zIndex", this.__b, "appearance");
this.__a.setZIndex(1234);
this.assertEquals("1234", this.__b.getAppearance(), "Number --> String does not work!");
// boolean to string
qx.data.SingleValueBinding.bind(this.__a, "enabled", this.__b, "appearance");
this.__a.setEnabled(true);
this.assertEquals("true", this.__b.getAppearance(), "Boolean --> String does not work!");
// string to float
var s = new qx.test.data.singlevalue.TextFieldDummy();
s.setFloatt(0);
qx.data.SingleValueBinding.bind(s, "floatt", this.__b, "appearance");
s.setFloatt(13.5);
this.assertEquals("13.5", this.__b.getAppearance(), "Float --> String does not work!");
qx.data.SingleValueBinding.removeAllBindingsForObject(s);
s.dispose();
},
testRemoveBinding: function(){
// remove all bindings
qx.data.SingleValueBinding.removeAllBindings();
// add a binding
var id = qx.data.SingleValueBinding.bind(this.__a, "appearance", this.__b, "appearance");
// set and chech the name
this.__a.setAppearance("hans");
this.assertEquals("hans", this.__b.getAppearance(), "String binding does not work!");
// remove the binding
qx.data.SingleValueBinding.removeBindingFromObject(this.__a, id);
// set and chech the name
this.__a.setAppearance("hans2");
this.assertEquals("hans", this.__b.getAppearance(), "Did not remove the binding!");
// test if the binding is not listed anymore
var bindings = qx.data.SingleValueBinding.getAllBindingsForObject(this.__a);
this.assertEquals(0, bindings.length, "Binding still in the registry!");
// only in source version
if (qx.core.Environment.get("qx.debug")) {
// test wrong binding id
var a = this.__a;
this.assertException(function() {
qx.data.SingleValueBinding.removeBindingFromObject(a, null);
}, Error, null, "No exception thrown.");
}
},
testGetAllBindingsForObject: function(){
// remove all old bindings
qx.data.SingleValueBinding.removeAllBindings();
// add two binding
var id = qx.data.SingleValueBinding.bind(this.__a, "appearance", this.__b, "appearance");
var id2 = qx.data.SingleValueBinding.bind(this.__a, "zIndex", this.__b, "zIndex");
// set and chech the binding
this.__a.setAppearance("hans");
this.assertEquals("hans", this.__b.getAppearance(), "String binding does not work!");
this.__a.setZIndex(89);
this.assertEquals(89, this.__b.getZIndex(), "Number binding does not work!");
// check the method
var bindings = qx.data.SingleValueBinding.getAllBindingsForObject(this.__a);
this.assertEquals(2, bindings.length, "There are more than 2 bindings!");
this.assertEquals(id, bindings[0][0], "Binding 1 not in the array.");
this.assertEquals(id2, bindings[1][0], "Binding 2 not in the array.");
// check for a non existing binding
var noBindings = qx.data.SingleValueBinding.getAllBindingsForObject(this);
this.assertEquals(0, noBindings.length, "There are bindings for this?");
},
testRemoveAllBindingsForObject: function() {
// add two bindings
qx.data.SingleValueBinding.bind(this.__a, "appearance", this.__b, "appearance");
qx.data.SingleValueBinding.bind(this.__a, "zIndex", this.__b, "zIndex");
// set and check the binding
this.__a.setAppearance("hans");
this.assertEquals("hans", this.__b.getAppearance(), "String binding does not work!");
this.__a.setZIndex(89);
this.assertEquals(89, this.__b.getZIndex(), "Number binding does not work!");
// remove the bindings at once
qx.data.SingleValueBinding.removeAllBindingsForObject(this.__a);
// set and check the binding
this.__a.setAppearance("hans2");
this.assertEquals("hans", this.__b.getAppearance(), "String binding not removed!");
this.__a.setZIndex(892);
this.assertEquals(89, this.__b.getZIndex(), "Number binding not removed!");
// check if they are internally removed
var bindings = qx.data.SingleValueBinding.getAllBindingsForObject(this.__a);
this.assertEquals(0, bindings.length, "Still bindings there!");
// check if a remove of an object without a binding works
var o = new qx.core.Object();
qx.data.SingleValueBinding.removeAllBindings();
o.dispose();
// only test in the source version
if (qx.core.Environment.get("qx.debug")) {
// test for null object
this.assertException(function() {
qx.data.SingleValueBinding.removeAllBindingsForObject(null);
}, qx.core.AssertionError, null, "Null is not possible!");
}
},
testGetAllBindings: function(){
// remove all bindings
qx.data.SingleValueBinding.removeAllBindings();
// add three bindings
var id1 = qx.data.SingleValueBinding.bind(this.__a, "appearance", this.__b, "appearance");
var id2 = qx.data.SingleValueBinding.bind(this.__a, "zIndex", this.__b, "zIndex");
var id3 = qx.data.SingleValueBinding.bind(this.__b, "zIndex", this.__a, "zIndex");
// get all bindings
var allBindings = qx.data.SingleValueBinding.getAllBindings();
// check if only the added hashs are in the object
var hashArray = [this.__a.toHashCode(), this.__b.toHashCode()];
var i = 0;
for (var hash in allBindings) {
this.assertInArray(hash, hashArray, "This hash should be in!");
i++;
}
this.assertEquals(2, i, "Too much or too less objects in the array!");
// check for the binding ids
this.assertEquals(id1, allBindings[this.__a.toHashCode()][0][0], "This id should be in!");
this.assertEquals(id2, allBindings[this.__a.toHashCode()][1][0], "This id should be in!");
this.assertEquals(id3, allBindings[this.__b.toHashCode()][0][0], "This id should be in!");
// check for the length
this.assertEquals(2, allBindings[this.__a.toHashCode()].length, "Not the right amount in the data!");
this.assertEquals(1, allBindings[this.__b.toHashCode()].length, "Not the right amount in the data!");
},
testDebugStuff: function(){
// just a test if the method runs threw without an exception
var id1 = qx.data.SingleValueBinding.bind(this.__a, "appearance", this.__b, "appearance");
qx.data.SingleValueBinding.bind(this.__a, "zIndex", this.__b, "zIndex");
qx.data.SingleValueBinding.bind(this.__b, "appearance", this.__a, "appearance");
qx.data.SingleValueBinding.bind(this.__b, "zIndex", this.__a, "zIndex");
// test the single log
qx.data.SingleValueBinding.showBindingInLog(this.__a, id1);
// test the all log
qx.data.SingleValueBinding.showAllBindingsInLog();
},
testMixinSupport: function() {
// remove all bindings
qx.data.SingleValueBinding.removeAllBindings();
// create a new Binding
var id1 = this.__a.bind("appearance", this.__b, "appearance");
this.__a.setAppearance("hulk");
this.assertEquals("hulk", this.__b.getAppearance(), "String binding does not work!");
// remove the binding
this.__a.removeBinding(id1);
this.__a.setAppearance("hulk2");
this.assertEquals("hulk", this.__b.getAppearance(), "Unbinding does not work!");
// add another two bindings
var id1 = this.__a.bind("changeAppearance", this.__b, "appearance");
var id2 = this.__a.bind("zIndex", this.__b, "zIndex");
// get the current bindings
var bindings = this.__a.getBindings();
this.assertEquals(id1, bindings[0][0], "First binding is not there.");
this.assertEquals(id2, bindings[1][0], "Second binding is not there.");
// remove all bindings
this.__a.removeAllBindings();
var bindings = this.__a.getBindings();
this.assertEquals(0, bindings.length, "Still bindings there?");
},
testDebugListenerMessages: function() {
// enable debugging
qx.data.SingleValueBinding.DEBUG_ON = true;
// just do some bindings and invoke the changes
qx.data.SingleValueBinding.bind(this.__a, "appearance", this.__b, "appearance");
this.__a.setAppearance("affe");
this.assertEquals("affe", this.__b.getAppearance(), "String binding does not work!");
var affe = new qx.test.data.singlevalue.TextFieldDummy();
affe.setAppearance("Jonny");
qx.data.SingleValueBinding.bind(affe, "appearance", this.__b, "appearance");
this.assertEquals("Jonny", this.__b.getAppearance(), "String binding does not work!");
qx.data.SingleValueBinding.removeAllBindingsForObject(affe);
affe.dispose();
},
testFallback: function() {
// change + "name" binding
this.__a.bind("value", this.__b, "value");
this.__a.setValue("affe");
this.assertEquals(this.__a.getValue(), this.__b.getValue(), "change event binding is not working.");
// event binding
this.__a.bind("changeZIndex", this.__b, "zIndex");
this.__a.setZIndex(123);
this.assertEquals(this.__a.getZIndex(), this.__b.getZIndex(), "Event binding is not working.");
},
testNullWithConverter: function() {
// create a test class
qx.Class.define("qx.Test", {
extend : qx.core.Object,
members : {
__a : null,
setA : function(data) {
this.__a = data;
},
getA : function() {
return this.__a;
}
}
});
var t = new qx.Test();
// define the converter
var options = {
converter : function(data) {
if (data == null) {
return "affe";
}
return data + "";
}
};
// starting point
this.__a.setZIndex(null);
this.__a.bind("zIndex", t, "a", options);
this.assertEquals("affe", t.getA(), "Converter will not be executed.");
this.__a.setZIndex(10);
this.assertEquals(this.__a.getZIndex() + "", t.getA(), "Wrong start binding.");
// set the zIndex to null
this.__a.setZIndex(null);
this.assertEquals("affe", t.getA(), "Converter will not be executed.");
t.dispose();
},
testCallbacksOnInitialSet: function() {
// create a test class
qx.Class.define("qx.Target",
{
extend : qx.core.Object,
properties :
{
value : {
init: "Some String!",
validate: qx.util.Validate.string()
}
}
});
var target = new qx.Target();
// some test flags
var ok = false;
var fail = false;
// callback methods
var that = this;
var options = {
onUpdate : function(sourceObject, targetObject, value) {
ok = true;
that.assertEquals(sourceObject, that.__a, "Wrong source object.");
that.assertEquals(targetObject, target, "Wrong target object.");
that.assertEquals(value, "affe", "Wrong value.");
},
onSetFail : function() {
fail = true;
}
};
// set a valid initial value
this.__a.setValue("affe");
this.__a.bind("value", target, "value", options);
this.assertEquals("affe", target.getValue(), "Binding not set anyway!");
this.assertTrue(ok, "onUpdate not called.");
this.assertFalse(fail, "onSetFail called?!");
// reset the checks
this.__a.removeAllBindings();
ok = false;
fail = false;
// set an invalid initial value
this.__a.setZIndex(10);
this.__a.bind("zIndex", target, "value", options);
this.assertTrue(fail, "onSetFail not called.");
this.assertFalse(ok, "onUpdate called?!");
target.dispose();
},
testConversionClass : function()
{
qx.Class.define("qx.test.TwoProperties", {
extend : qx.core.Object,
properties :
{
a : { event : "changeA", nullable : true },
b : { event : "changeB", nullable : true }
}
});
var o = new qx.test.TwoProperties();
// number to string
var id = qx.data.SingleValueBinding.bind(
o, "a", o, "b", qx.data.Conversion.TOSTRINGOPTIONS
);
o.setA(10);
this.assertEquals("10", o.getB(), "Number -> String");
qx.data.SingleValueBinding.removeBindingFromObject(o, id);
// boolean to string
var id = qx.data.SingleValueBinding.bind(
o, "a", o, "b", qx.data.Conversion.TOSTRINGOPTIONS
);
o.setA(true);
this.assertEquals("true", o.getB(), "Boolean -> String");
qx.data.SingleValueBinding.removeBindingFromObject(o, id);
// date to string
var id = qx.data.SingleValueBinding.bind(
o, "a", o, "b", qx.data.Conversion.TOSTRINGOPTIONS
);
o.setA(new Date());
this.assertTrue(qx.lang.Type.isString(o.getB()), "Date -> String");
qx.data.SingleValueBinding.removeBindingFromObject(o, id);
// string to number
var id = qx.data.SingleValueBinding.bind(
o, "a", o, "b", qx.data.Conversion.TONUMBEROPTIONS
);
o.setA("123");
this.assertEquals(123, o.getB(), "String -> Number");
qx.data.SingleValueBinding.removeBindingFromObject(o, id);
// string to boolean
var id = qx.data.SingleValueBinding.bind(
o, "a", o, "b", qx.data.Conversion.TOBOOLEANOPTIONS
);
o.setA("123");
this.assertEquals(true, o.getB(), "String -> Boolean");
qx.data.SingleValueBinding.removeBindingFromObject(o, id);
// number to boolean
var id = qx.data.SingleValueBinding.bind(
o, "a", o, "b", qx.data.Conversion.TOBOOLEANOPTIONS
);
o.setA(0);
this.assertEquals(false, o.getB(), "Number -> Boolean");
qx.data.SingleValueBinding.removeBindingFromObject(o, id);
o.dispose();
},
testResetNotNull : function() {
qx.Class.define("qx.test.SVB", {
extend : qx.core.Object,
properties : {
x : {
nullable: true,
init: "affe",
event: "changeX"
}
}
});
var a = new qx.test.SVB();
var b = new qx.test.SVB();
a.bind("x", b, "x");
a.setX("x");
this.assertEquals(a.getX(), b.getX());
a.setX(null);
this.assertEquals(a.getX(), b.getX());
qx.data.SingleValueBinding.removeAllBindingsForObject(a);
qx.data.SingleValueBinding.removeAllBindingsForObject(b);
a.dispose();
b.dispose();
qx.Class.undefine("qx.test.SVB");
},
testResetNotNullInit : function() {
qx.Class.define("qx.test.SVB", {
extend : qx.core.Object,
properties : {
x : {
nullable: true,
init: "affe",
event: "changeX"
}
}
});
var a = new qx.test.SVB();
var b = new qx.test.SVB();
a.setX(null);
b.setX("x");
qx.data.SingleValueBinding.bind(a, "x", b, "x");
this.assertEquals(a.getX(), b.getX());
qx.data.SingleValueBinding.removeAllBindingsForObject(a);
qx.data.SingleValueBinding.removeAllBindingsForObject(b);
a.dispose();
b.dispose();
qx.Class.undefine("qx.test.SVB");
},
testChangeEventMissing : function() {
qx.Class.define("qx.test.SVB", {
extend : qx.core.Object,
properties : {
x : {
nullable: true,
init: "affe"
}
}
});
var a = new qx.test.SVB();
var b = new qx.test.SVB();
this.assertException(function() {
qx.data.SingleValueBinding.bind(a, "x", b, "x");
}, qx.core.AssertionError, "Binding property x of object qx.test.SVB");
qx.data.SingleValueBinding.removeAllBindingsForObject(a);
qx.data.SingleValueBinding.removeAllBindingsForObject(b);
a.dispose();
b.dispose();
qx.Class.undefine("qx.test.SVB");
},
testConverterParam : function() {
var self = this;
var options = {converter : function(data, model, source, target) {
// will be called twice (init and set)
self.assertEquals(self.__a, source);
self.assertEquals(self.__b, target);
return data;
}};
qx.data.SingleValueBinding.bind(
this.__a, "appearance", this.__b, "appearance", options
);
this.__a.setAppearance("affe");
this.assertEquals("affe", this.__b.getAppearance(), "String binding does not work!");
},
testWrongArguments : function() {
this.require(["qx.debug"]);
this.assertException(function() {
qx.data.SingleValueBinding.bind(this.__a, "appearance", this.__b, undefined);
}, qx.core.AssertionError, "");
this.assertException(function() {
qx.data.SingleValueBinding.bind(this.__a, "appearance", undefined, "appearance");
}, qx.core.AssertionError, "");
this.assertException(function() {
qx.data.SingleValueBinding.bind(this.__a, undefined, this.__b, "appearance");
}, qx.core.AssertionError, "");
this.assertException(function() {
qx.data.SingleValueBinding.bind(undefined, "appearance", this.__b, "appearance");
}, qx.core.AssertionError, "");
},
testRemoveRelatedBindings: function(){
var c = new qx.test.data.singlevalue.TextFieldDummy();
// add three bindings
qx.data.SingleValueBinding.bind(this.__a, "appearance", this.__b, "appearance");
qx.data.SingleValueBinding.bind(this.__a, "zIndex", this.__b, "zIndex");
qx.data.SingleValueBinding.bind(this.__b, "zIndex", this.__a, "zIndex");
// add another binding to __a, which should not be affected
qx.data.SingleValueBinding.bind(c, "appearance", this.__a, "appearance");
// add another binding to __b, which should not be affected
qx.data.SingleValueBinding.bind(c, "appearance", this.__b, "appearance");
// check if the bindings are there
var bindingsA = qx.data.SingleValueBinding.getAllBindingsForObject(this.__a);
var bindingsB = qx.data.SingleValueBinding.getAllBindingsForObject(this.__b);
this.assertEquals(4, bindingsA.length, "There are more than 4 bindings!");
this.assertEquals(4, bindingsB.length, "There are more than 3 bindings!");
// remove related bindings between __a and __b, do not affect bindings to c
qx.data.SingleValueBinding.removeRelatedBindings(this.__a, this.__b);
// __a object should have one binding to object c
bindingsA = qx.data.SingleValueBinding.getAllBindingsForObject(this.__a);
this.assertEquals(1, bindingsA.length, "There must be one binding!");
this.assertTrue(bindingsA[0][1] === c, "Source object of the binding must be object 'c'!");
// __b object should have one binding to object c
bindingsB = qx.data.SingleValueBinding.getAllBindingsForObject(this.__b);
this.assertEquals(1, bindingsB.length, "There must be one binding!");
this.assertTrue(bindingsA[0][1] === c, "Source object of the binding must be object 'c'!");
},
testNonExistingSetup: function() {
var a = qx.data.marshal.Json.createModel({b: {}, target: null});
qx.data.SingleValueBinding.bind(a, "b.c", a, "target");
this.assertNull(a.getTarget());
a.setB(qx.data.marshal.Json.createModel({c: "txt"}));
this.assertEquals("txt", a.getTarget());
},
testNonExistingSetupDeep: function() {
var a = qx.data.marshal.Json.createModel({b: {c: {d: {e: {}}}}, target: null});
qx.data.SingleValueBinding.bind(a, "b.c.d.e.f", a, "target");
this.assertNull(a.getTarget());
a.getB().setC(qx.data.marshal.Json.createModel({d: {e: {f: "txt"}}}));
this.assertEquals("txt", a.getTarget());
},
testNonExistingChange: function() {
var a = qx.data.marshal.Json.createModel({b: {c: "txt"}, bb: {}, target: null});
qx.data.SingleValueBinding.bind(a, "b.c", a, "target");
this.assertEquals("txt", a.getTarget());
a.setB(a.getBb());
this.assertNull(a.getTarget());
},
testNonExistingChangeDeep: function() {
var a = qx.data.marshal.Json.createModel({b: {c: {d: {e: {f: "txt"}}}}, target: null});
qx.data.SingleValueBinding.bind(a, "b.c.d.e.f", a, "target");
this.assertEquals("txt", a.getTarget());
a.getB().setC(qx.data.marshal.Json.createModel({d: {e: {}}}));
this.assertNull(a.getTarget());
a.getB().setC(qx.data.marshal.Json.createModel({d: {}}));
this.assertNull(a.getTarget());
}
}
});