@qooxdoo/framework
Version:
The JS Framework for Coders
1,032 lines (869 loc) • 26.4 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() {
// create the widgets
this.__a = new qx.test.data.singlevalue.TextFieldDummy();
this.__b = new qx.test.data.singlevalue.TextFieldDummy();
},
tearDown() {
qx.data.SingleValueBinding.removeAllBindingsForObject(this.__a);
qx.data.SingleValueBinding.removeAllBindingsForObject(this.__b);
this.__a.dispose();
this.__b.dispose();
},
testStringPropertyBinding() {
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() {
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() {
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() {
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() {
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() {
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() {
// 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() {
// 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() {
// 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() {
// 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();
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() {
// 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 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() {
// 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);
},
testMixinSupport() {
// 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() {
// 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() {
// 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() {
// create a test class
qx.Class.define("qx.Test", {
extend: qx.core.Object,
members: {
__a: null,
setA(data) {
this.__a = data;
},
getA() {
return this.__a;
}
}
});
var t = new qx.Test();
// define the converter
var options = {
converter(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() {
// 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(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() {
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() {
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() {
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() {
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() {
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() {
var self = this;
var options = {
converter(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() {
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() {
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() {
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() {
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() {
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() {
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());
}
}
});