UNPKG

@qooxdoo/framework

Version:

The JS Framework for Coders

679 lines (510 loc) 20.6 kB
/* ************************************************************************ 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.MultiBinding) */ qx.Class.define("qx.test.data.singlevalue.Deep", { extend : qx.dev.unit.TestCase, include : [qx.dev.unit.MMock], construct : function() { this.base(arguments); // define a test class qx.Class.define("qx.test.MultiBinding", { extend : qx.core.Object, properties : { child : { check : "qx.test.MultiBinding", event : "changeChild", nullable : true }, childWithout : { check : "qx.test.MultiBinding", nullable : true }, name : { check : "String", nullable: true, init : "Juhu", event : "changeName" }, array : { init : null, event: "changeArray" }, lab : { event: "changeLable" } }, destruct : function() { if (this.getLab()) { this.getLab().dispose(); } if (this.getArray()) { this.getArray().dispose(); } } }); }, members : { __a : null, __b1 : null, __b2 : null, __label : null, setUp : function() { this.__a = new qx.test.MultiBinding().set({ name: "a", lab: new qx.test.data.singlevalue.TextFieldDummy(""), array: new qx.data.Array(["one", "two", "three"]) }); this.__b1 = new qx.test.MultiBinding().set({ name: "b1", lab: new qx.test.data.singlevalue.TextFieldDummy(""), array: new qx.data.Array(["one", "two", "three"]) }); this.__b2 = new qx.test.MultiBinding().set({ name: "b2", lab: new qx.test.data.singlevalue.TextFieldDummy(""), array: new qx.data.Array(["one", "two", "three"]) }); this.__label = new qx.test.data.singlevalue.TextFieldDummy(); // remove all bindings qx.data.SingleValueBinding.removeAllBindings(); }, tearDown : function() { this.__b1.dispose(); this.__b2.dispose(); this.__a.dispose(); this.__label.dispose(); }, testConverterChainBroken : function() { var m = qx.data.marshal.Json.createModel({a: {a: 1}, b: 2}); var called = 0; m.bind("a.a", m, "b", {converter : function(data) { called++; return 3; }}); // check the init values this.assertEquals(1, called); this.assertEquals(3, m.getB()); // set the binding leaf to null m.getA().setA(null); this.assertEquals(2, called); this.assertEquals(3, m.getB()); // set the binding root to null m.setA(null); this.assertEquals(3, called); this.assertEquals(3, m.getB()); m.dispose(); }, testConverterChainBrokenInitialNull : function() { var m = qx.data.marshal.Json.createModel({a: null}); var t = qx.data.marshal.Json.createModel({a: null}); var spy = this.spy(function() { return 123; }); m.bind("a.b", t, "a", {converter : spy}); this.assertCalledOnce(spy); this.assertCalledWith(spy, undefined, undefined, m, t); this.assertEquals(123, t.getA()); m.dispose(); t.dispose(); }, testDepthOf2: function() { // create a hierarchy // a --> b1 this.__a.setChild(this.__b1); // create the binding // a --> b1 --> label qx.data.SingleValueBinding.bind(this.__a, "child.name", this.__label, "value"); // just set the name of the second component this.__b1.setName("B1"); this.assertEquals("B1", this.__label.getValue(), "Deep binding does not work with updating the first parameter."); // change the second component // a --> b2 --> label this.__a.setChild(this.__b2); this.assertEquals("b2", this.__label.getValue(), "Deep binding does not work with updating the first parameter."); // check for the null value // a --> null this.__a.setChild(null); this.assertNull(this.__label.getValue(), "Binding does not work with null."); }, testDepthOf3: function(attribute) { // create a hierarchy var c1 = new qx.test.MultiBinding().set({ name: "c1" }); var c2 = new qx.test.MultiBinding().set({ name: "c2" }); // a --> b1 --> c1 --> label // b2 --> c2 this.__a.setChild(this.__b1); this.__b1.setChild(c1); this.__b2.setChild(c2); // create the binding qx.data.SingleValueBinding.bind(this.__a, "child.child.name", this.__label, "value"); // just set the name of the last component c1.setName("C1"); this.assertEquals("C1", this.__label.getValue(), "Deep binding does not work with updating the third parameter."); // change the middle child // a --> b2 --> c2 --> label this.__a.setChild(this.__b2); this.assertEquals("c2", this.__label.getValue(), "Deep binding does not work with updating the second parameter."); // set the middle child to null // a --> null this.__a.setChild(null); this.assertNull(this.__label.getValue(), "Deep binding does not work with first null child."); // set only two childs // a --> b1 --> null this.__b1.setChild(null); this.__a.setChild(this.__b1); this.assertNull(this.__label.getValue(), "Deep binding does not work with second null child."); // set the childs in a row // a --> b1 --> c1 --> label this.__b1.setChild(c1); this.assertEquals("C1", this.__label.getValue(), "Deep binding does not work with updating the third parameter."); }, testDepthOf5: function(attribute) { // create a hierarchy var c = new qx.test.MultiBinding().set({ name: "c" }); var d = new qx.test.MultiBinding().set({ name: "d" }); var e = new qx.test.MultiBinding().set({ name: "e" }); // a --> b1 --> c --> d --> e --> label this.__a.setChild(this.__b1); this.__b1.setChild(c); c.setChild(d); d.setChild(e); // create the binding qx.data.SingleValueBinding.bind(this.__a, "child.child.child.child.name", this.__label, "value"); // test if the binding did work this.assertEquals("e", this.__label.getValue(), "Deep binding does not work with updating the third parameter."); }, testWrongDeep: function() { // create a hierarchy this.__a.setChild(this.__b1); var a = this.__a; var label = this.__label; // only in source version if (qx.core.Environment.get("qx.debug")) { // set a wrong first parameter in the chain this.assertException(function() { qx.data.SingleValueBinding.bind(a, "chiild.name", label, "value"); }, qx.core.AssertionError, null, "Wrong property name."); // set a complete wrong chain this.assertException(function() { qx.data.SingleValueBinding.bind(a, "affe", label, "value"); }, qx.core.AssertionError, null, "Wrong property name."); } }, testSingle: function() { // set only one property in the chain qx.data.SingleValueBinding.bind(this.__a, "name", this.__label, "value"); // chech the initial value this.assertEquals("a", this.__label.getValue(), "Single property names don't work!"); // check the binding this.__a.setName("A"); this.assertEquals("A", this.__label.getValue(), "Single property names don't work!"); }, testDebug: function(attribute) { // build the structure this.__a.setChild(this.__b1); // bind the stuff together var id = qx.data.SingleValueBinding.bind(this.__a, "child.name", this.__label, "value"); // log this binding in the console qx.data.SingleValueBinding.showBindingInLog(this.__a, id); }, testRemove: function() { // build the structure this.__a.setChild(this.__b1); // bind the stuff together var id = qx.data.SingleValueBinding.bind(this.__a, "child.name", this.__label, "value"); // check the binding this.__b1.setName("A"); this.assertEquals("A", this.__label.getValue(), "Single property names don't work!"); // remove the binding qx.data.SingleValueBinding.removeBindingFromObject(this.__a, id); // check the binding again this.__a.setName("A2"); this.assertEquals("A", this.__label.getValue(), "Removing does not work!"); // smoke Test for the remove qx.data.SingleValueBinding.bind(this.__a, "child.name", this.__label, "value"); qx.data.SingleValueBinding.bind(this.__a, "child.name", this.__label, "value"); qx.data.SingleValueBinding.bind(this.__a, "child.name", this.__label, "value"); qx.data.SingleValueBinding.removeAllBindings(); }, testArrayDeep: function() { this.__a.getArray().dispose(); this.__a.setArray(new qx.data.Array([this.__b1])); this.__b1.setChild(this.__b2); this.__b2.setChild(this.__b1); qx.data.SingleValueBinding.bind(this.__a, "array[0].child.name", this.__label, "value"); this.assertEquals("b2", this.__label.getValue(), "Deep binding does not work."); this.__a.getArray().pop(); this.assertNull(this.__label.getValue(), "Deep binding does not work."); this.__a.getArray().push(this.__b2); this.assertEquals("b1", this.__label.getValue(), "Deep binding does not work."); this.__b1.setName("B1"); this.assertEquals("B1", this.__label.getValue(), "Deep binding does not work."); }, testDeepTarget: function() { qx.data.SingleValueBinding.bind(this.__a, "name", this.__b1, "lab.value"); this.assertEquals("a", this.__b1.getLab().getValue(), "Deep binding on the target does not work."); }, testDeepTarget2: function() { this.__b2.setChild(this.__b1); qx.data.SingleValueBinding.bind(this.__a, "name", this.__b2, "child.lab.value"); this.assertEquals("a", this.__b1.getLab().getValue(), "Deep binding on the target does not work."); }, testDeepTargetNull: function() { qx.data.SingleValueBinding.bind(this.__a, "name", this.__b2, "child.lab.value"); this.assertEquals("", this.__b1.getLab().getValue(), "Deep binding on the target does not work."); }, testDeepTargetArray: function() { this.__a.getArray().dispose(); this.__a.setArray(new qx.data.Array([this.__b1])); qx.data.SingleValueBinding.bind(this.__a, "name", this.__a, "array[0].lab.value"); this.assertEquals("a", this.__b1.getLab().getValue(), "Deep binding on the target does not work."); }, testDeepTargetArrayLast: function() { this.__a.getArray().dispose(); this.__a.setArray(new qx.data.Array([this.__b1])); qx.data.SingleValueBinding.bind(this.__a, "name", this.__a, "array[last].lab.value"); this.assertEquals("a", this.__b1.getLab().getValue(), "Deep binding on the target does not work."); }, testDeepTargetChange : function() { var oldLabel = this.__b1.getLab(); var newLabel = new qx.test.data.singlevalue.TextFieldDummy("x"); qx.data.SingleValueBinding.bind(this.__a, "name", this.__b1, "lab.value"); this.__b1.setLab(newLabel); this.assertEquals("a", this.__b1.getLab().getValue()); this.__a.setName("l"); this.assertEquals("a", oldLabel.getValue()); this.assertEquals("l", this.__b1.getLab().getValue()); newLabel.dispose(); oldLabel.dispose(); }, testDeepTargetChangeConverter : function() { var oldLabel = this.__b1.getLab(); var newLabel = new qx.test.data.singlevalue.TextFieldDummy("x"); qx.data.SingleValueBinding.bind( this.__a, "name", this.__b1, "lab.value", {converter : function(data) {return data + "...";}} ); this.__b1.setLab(newLabel); this.assertEquals("a...", this.__b1.getLab().getValue()); this.__a.setName("l"); this.assertEquals("a...", oldLabel.getValue()); this.assertEquals("l...", this.__b1.getLab().getValue()); newLabel.dispose(); oldLabel.dispose(); }, testDeepTargetChange3 : function() { // set up the target chain this.__a.setChild(this.__b1); this.__b1.setChild(this.__b2); this.__b2.setChild(this.__b1); qx.data.SingleValueBinding.bind(this.__label, "value", this.__a, "child.child.lab.value"); // check the default set this.__label.setValue("123"); this.assertEquals("123", this.__b2.getLab().getValue()); // change the child of __a this.__a.setChild(this.__b2); this.assertEquals("123", this.__b1.getLab().getValue()); // set another label value this.__label.setValue("456"); this.assertEquals("123", this.__b2.getLab().getValue()); this.assertEquals("456", this.__b1.getLab().getValue()); }, testDeepTargetChange3Remove : function() { // set up the target chain this.__a.setChild(this.__b1); this.__b1.setChild(this.__b2); this.__b2.setChild(this.__b1); var id = qx.data.SingleValueBinding.bind(this.__label, "value", this.__a, "child.child.lab.value"); // check the default set this.__label.setValue("123"); this.assertEquals("123", this.__b2.getLab().getValue(), "0"); qx.data.SingleValueBinding.removeBindingFromObject(this.__label, id); // change the child of __a this.__a.setChild(this.__b2); this.assertEquals("", this.__b1.getLab().getValue(), "listener still there"); // set another label value this.__label.setValue("456"); this.assertEquals("123", this.__b2.getLab().getValue(), "1"); this.assertEquals("", this.__b1.getLab().getValue(), "2"); }, testDeepTargetChangeArray : function() { qx.data.SingleValueBinding.bind(this.__label, "value", this.__a,"array[0]"); this.__label.setValue("123"); this.assertEquals("123", this.__a.getArray().getItem(0)); var newArray = new qx.data.Array([0, 1, 0]); var oldArray = this.__a.getArray(); this.__a.setArray(newArray); this.assertEquals("123", this.__a.getArray().getItem(0), "initial set"); this.__label.setValue("456"); this.assertEquals("456", newArray.getItem(0)); this.assertEquals("123", oldArray.getItem(0)); oldArray.dispose(); newArray.dispose(); }, testDeepTargetChangeArrayLast : function() { qx.data.SingleValueBinding.bind(this.__label, "value", this.__a,"array[last]"); this.__label.setValue("123"); this.assertEquals("123", this.__a.getArray().getItem(2)); var newArray = new qx.data.Array([0, 1, 0]); var oldArray = this.__a.getArray(); this.__a.setArray(newArray); this.assertEquals("123", this.__a.getArray().getItem(2), "initial set"); this.__label.setValue("456"); this.assertEquals("456", newArray.getItem(2)); this.assertEquals("123", oldArray.getItem(2)); oldArray.dispose(); newArray.dispose(); }, testDeepTargetChange3Array : function() { // set up the target chain this.__a.setChild(this.__b1); this.__b1.setChild(this.__b2); this.__b2.setChild(this.__b1); qx.data.SingleValueBinding.bind(this.__label, "value", this.__a, "child.child.array[0]"); // check the default set this.__label.setValue("123"); this.assertEquals("123", this.__b2.getArray().getItem(0)); // change the child of __a this.__a.setChild(this.__b2); this.assertEquals("123", this.__b1.getArray().getItem(0)); // set another label value this.__label.setValue("456"); this.assertEquals("456", this.__b1.getArray().getItem(0)); this.assertEquals("123", this.__b2.getArray().getItem(0), "binding still exists"); }, testDeepTargetChangeMiddleArray : function() { var oldArray = this.__a.getArray(); var array = new qx.data.Array([this.__b1, this.__b2]); this.__a.setArray(array); oldArray.dispose(); qx.data.SingleValueBinding.bind(this.__label, "value", this.__a, "array[0].lab.value"); this.__label.setValue("123"); this.assertEquals("123", this.__b1.getLab().getValue()); array.reverse(); this.assertEquals("123", this.__b2.getLab().getValue()); this.__label.setValue("456"); this.assertEquals("456", this.__b2.getLab().getValue()); this.assertEquals("123", this.__b1.getLab().getValue()); }, testDeepTargetChangeMiddleArrayLast : function() { var oldArray = this.__a.getArray(); var array = new qx.data.Array([this.__b2, this.__b1]); this.__a.setArray(array); oldArray.dispose(); qx.data.SingleValueBinding.bind(this.__label, "value", this.__a, "array[last].lab.value"); this.__label.setValue("123"); this.assertEquals("123", this.__b1.getLab().getValue()); array.reverse(); this.assertEquals("123", this.__b2.getLab().getValue()); this.__label.setValue("456"); this.assertEquals("456", this.__b2.getLab().getValue()); this.assertEquals("123", this.__b1.getLab().getValue()); }, testDeepTargetChangeWithoutEvent : function() { this.__a.setChildWithout(this.__b1); qx.data.SingleValueBinding.bind(this.__label, "value", this.__a, "childWithout.name"); this.__label.setValue("123"); this.assertEquals("123", this.__b1.getName()); this.__a.setChildWithout(this.__b2); this.assertEquals("b2", this.__b2.getName()); this.__label.setValue("456"); this.assertEquals("456", this.__b2.getName()); this.assertEquals("123", this.__b1.getName()); }, testDeepTargetChangeWithoutEvent3 : function() { this.__a.setChild(this.__b1); this.__b1.setChildWithout(this.__b2); this.__b2.setChildWithout(this.__b1); qx.data.SingleValueBinding.bind(this.__label, "value", this.__a, "child.childWithout.name"); this.__label.setValue("123"); this.assertEquals("123", this.__b2.getName()); this.__a.setChild(this.__b2); this.assertEquals("123", this.__b1.getName()); this.__b2.setChildWithout(this.__a); this.assertEquals("a", this.__a.getName()); this.__label.setValue("456"); this.assertEquals("456", this.__a.getName()); this.assertEquals("123", this.__b1.getName()); }, testDeepTargetChange3ResetNotNull : function() { // set up the target chain this.__a.setChild(this.__b1); this.__b1.setChild(this.__b2); this.__b2.setChild(this.__b1); this.__a.setName(null); qx.data.SingleValueBinding.bind(this.__a, "name", this.__a, "child.child.name"); this.assertEquals(this.__a.getName(), this.__b2.getName()); this.__a.setName("nnnnn"); this.assertEquals(this.__a.getName(), this.__b2.getName()); this.__a.setName(null); this.assertEquals(this.__a.getName(), this.__b2.getName()); }, /** * Remove a deep binding that has a class in its binding that does not have a property in the chain. */ testRemoveIncompleteBinding : function () { var source = qx.data.marshal.Json.createModel({a: null}); var a = qx.data.marshal.Json.createModel({}); // a class that does not contain a property with name "b" var target = qx.data.marshal.Json.createModel({result: null}); try { source.bind('a.b', target, 'result'); source.setA(a); source.removeAllBindings(); } catch (e) { this.error(e); this.assertTrue(false, e.message); } source = qx.data.marshal.Json.createModel({a: null}); source.setA(a); try { source.bind('a.b', target, 'result'); source.removeAllBindings(); } catch (e) { this.error(e); this.assertTrue(false, e.message); } } } });