UNPKG

@qooxdoo/framework

Version:

The JS Framework for Coders

1,504 lines (1,272 loc) 42.7 kB
/* ************************************************************************ qooxdoo - the new era of web development http://qooxdoo.org Copyright: 2004-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) ************************************************************************ */ /** * @asset(qx/test/*) * * @ignore(qx.data.model) * @ignore(qx.test.model.*) * @ignore(qx.Test) * @ignore(qx.test.Array) */ qx.Class.define("qx.test.data.marshal.Json", { extend: qx.dev.unit.TestCase, include: qx.dev.unit.MMock, members: { __marshaler: null, __data: null, __propertyNames: null, setUp() { this.__marshaler = new qx.data.marshal.Json(); this.__data = { s: "String", n: 12, b: true }; this.__propertyNames = ["s", "n", "b"]; }, tearDown() { this.__marshaler.dispose(); // remove the former created classes qx.data.model = {}; for (var name in qx.Class.$$registry) { if (name.search("qx.data.model") != -1) { delete qx.Class.$$registry[name]; } } }, test$$member() { var data = { $$a: "b" }; this.__marshaler.toClass(data); // check if the class is defined this.assertTrue( qx.Class.isDefined("qx.data.model.$$a"), "Class not created." ); var clazz = qx.Class.getByName("qx.data.model.$$a"); // check for the property for (var name in clazz.$$properties) { this.assertEquals( "$$a", name, "Property $$a does have the wrong name." ); this.assertEquals( "change" + qx.lang.String.firstUp("$$a"), clazz.$$properties[name].event, "event has a wrong name." ); } qx.Class.undefine("qx.data.model.$$a"); }, testLocalizedString() { var str = qx.locale.Manager.tr("test one"); var data = { a: str }; this.__marshaler.toClass(data); var model = this.__marshaler.toModel(data); this.assertEquals(str, model.getA()); model.dispose(); qx.Class.undefine("qx.data.model.a"); }, testClassCreationSingle() { this.__marshaler.toClass(this.__data); // check if the class is defined this.assertTrue( qx.Class.isDefined("qx.data.model.b|n|s"), "Class not created." ); var clazz = qx.Class.getByName("qx.data.model.b|n|s"); // check for the properties var i = 0; for (var name in clazz.$$properties) { this.assertEquals( this.__propertyNames[i], name, "Property " + i + "does have the wrong name." ); this.assertEquals( "change" + qx.lang.String.firstUp(this.__propertyNames[i]), clazz.$$properties[name].event, "event has a wrong name." ); i++; } }, testClassCreationArray() { this.__data = { a: ["a", "b", "c"] }; this.__marshaler.toClass(this.__data); // check if the class is defined this.assertTrue( qx.Class.isDefined("qx.data.model.a"), "Class not created." ); var clazz = qx.Class.getByName("qx.data.model.a"); // check for the property this.assertNotNull(clazz.$$properties.a, "Property does not exist."); }, testClassCreationObject() { this.__data = { a: { b: "test" } }; this.__marshaler.toClass(this.__data); // check if the classes are defined this.assertTrue( qx.Class.isDefined("qx.data.model.a"), "Class not created." ); this.assertTrue( qx.Class.isDefined("qx.data.model.b"), "Class not created." ); var clazz = qx.Class.getByName("qx.data.model.a"); var clazz2 = qx.Class.getByName("qx.data.model.b"); // check for the property this.assertNotNull(clazz.$$properties.a, "Property does not exist."); this.assertNotNull(clazz2.$$properties.b, "Property does not exist."); }, testClassCreationArrayWithObject() { this.__data = { a: [{ b: "test" }, { b: "test" }] }; this.__marshaler.toClass(this.__data); // check if the classes are defined this.assertTrue( qx.Class.isDefined("qx.data.model.a"), "Class not created." ); this.assertTrue( qx.Class.isDefined("qx.data.model.b"), "Class not created." ); var clazz = qx.Class.getByName("qx.data.model.a"); var clazz2 = qx.Class.getByName("qx.data.model.b"); // check for the property this.assertNotNull(clazz.$$properties.a, "Property does not exist."); this.assertNotNull(clazz2.$$properties.b, "Property does not exist."); }, testClassCreationAllSmoke() { this.__data = { a: [ { b: "test", c: ["f", "x", "e"] }, { b: "test", affe: false } ], t: { f: null, r: 152, q: true } }; this.__marshaler.toClass(this.__data); }, testModelWithNumber() { this.__data = { a: 10, b: -15, c: 10.5e10 }; // first create the classes before setting the data this.__marshaler.toClass(this.__data); // set the data var model = this.__marshaler.toModel(this.__data); // check the model this.assertEquals(10, model.getA(), "getA does not work."); this.assertEquals(-15, model.getB(), "getB does not work."); this.assertEquals(10.5e10, model.getC(), "getC does not work."); model.dispose(); }, testModelWithBoolean() { this.__data = { a: true, b: false }; // first create the classes before setting the data this.__marshaler.toClass(this.__data); // set the data var model = this.__marshaler.toModel(this.__data); // check the model this.assertEquals(true, model.getA(), "getA does not work."); this.assertEquals(false, model.getB(), "getB does not work."); model.dispose(); }, testModelWithString() { this.__data = { a: "affe", b: "AFFE" }; // first create the classes before setting the data this.__marshaler.toClass(this.__data); // set the data var model = this.__marshaler.toModel(this.__data); // check the model this.assertEquals("affe", model.getA(), "getA does not work."); this.assertEquals("AFFE", model.getB(), "getB does not work."); model.dispose(); }, testModelWithPrimitive() { this.__data = { a: "affe", b: true, c: 156 }; // first create the classes before setting the data this.__marshaler.toClass(this.__data); // set the data var model = this.__marshaler.toModel(this.__data); // check the model this.assertEquals("affe", model.getA(), "getA does not work."); this.assertEquals(true, model.getB(), "getB does not work."); this.assertEquals(156, model.getC(), "getC does not work."); model.dispose(); }, testModelWithArrayPrimitive() { this.__data = { a: ["affe", "affen", "AFFE"] }; // first create the classes before setting the data this.__marshaler.toClass(this.__data); // set the data var model = this.__marshaler.toModel(this.__data); // check the model var a = model.getA(); this.assertNotNull(a, "Nothing stored in the property a."); this.assertEquals("qx.data.Array", a.classname, "Its not an data array."); this.assertEquals("affe", a.getItem(0), "Item 0 is wrong"); this.assertEquals("affen", a.getItem(1), "Item 1 is wrong"); this.assertEquals("AFFE", a.getItem(2), "Item 2 is wrong"); model.dispose(); }, testModelWithArrayArray() { this.__data = { a: [ [true, false], [10, 15] ] }; // first create the classes before setting the data this.__marshaler.toClass(this.__data); // set the data var model = this.__marshaler.toModel(this.__data); // check the model var a = model.getA(); this.assertNotNull(a, "Nothing stored in the property a."); this.assertEquals("qx.data.Array", a.classname, "Its not an data array."); var a0 = a.getItem(0); this.assertEquals( "qx.data.Array", a0.classname, "Its not an data array." ); this.assertEquals(true, a0.getItem(0), "Item 0 is wrong"); this.assertEquals(false, a0.getItem(1), "Item 1 is wrong"); var a1 = a.getItem(1); this.assertEquals( "qx.data.Array", a1.classname, "Its not an data array." ); this.assertEquals(10, a1.getItem(0), "Item 0 is wrong"); this.assertEquals(15, a1.getItem(1), "Item 1 is wrong"); model.dispose(); }, testModelWithObjectPrimitive() { this.__data = { a: { b: true, bb: false }, aa: { c: 15, cc: -89 } }; // first create the classes before setting the data this.__marshaler.toClass(this.__data); // set the data var model = this.__marshaler.toModel(this.__data); // check the model var a = model.getA(); this.assertNotNull(a, "Nothing stored in the property a."); this.assertEquals(true, a.getB(), "b is not set"); this.assertEquals(false, a.getBb(), "bb is not set"); var aa = model.getAa(); this.assertNotNull(aa, "Nothing stored in the property a."); this.assertEquals(15, aa.getC(), "c is not set"); this.assertEquals(-89, aa.getCc(), "cc is not set"); model.dispose(); }, testModelWithObjectArray() { this.__data = { a: { b: ["affe", "AFFE"] } }; // first create the classes before setting the data this.__marshaler.toClass(this.__data); // set the data var model = this.__marshaler.toModel(this.__data); // check the model var a = model.getA(); this.assertNotNull(a, "Nothing stored in the property a."); var b = a.getB(); this.assertNotNull(b, "Nothing stored in the property b."); this.assertEquals("qx.data.Array", b.classname, "b is not an data array"); this.assertEquals("affe", b.getItem(0), "Item 0 is wrong."); this.assertEquals("AFFE", b.getItem(1), "Item 1 is wrong."); model.dispose(); }, testModelWithArrayObject() { this.__data = { a: [{ a: 15 }, { a: true }] }; // first create the classes before setting the data this.__marshaler.toClass(this.__data); // set the data var model = this.__marshaler.toModel(this.__data); // check the model var a = model.getA(); this.assertNotNull(a, "Nothing stored in the property a."); this.assertEquals("qx.data.Array", a.classname, "b is not an data array"); this.assertEquals(15, a.getItem(0).getA(), "Item 0 is wrong."); this.assertEquals(true, a.getItem(1).getA(), "Item 1 is wrong."); // check if only one class is created and used this.assertEquals( model.classname, a.getItem(0).classname, "Differen classes" ); this.assertEquals( model.classname, a.getItem(1).classname, "Differen classes" ); this.assertEquals( a.getItem(0).classname, a.getItem(1).classname, "Differen classes" ); model.dispose(); }, testModelWithObjectObject() { this.__data = { a: { a: { a: "affe" } } }; // first create the classes before setting the data this.__marshaler.toClass(this.__data); // set the data var model = this.__marshaler.toModel(this.__data); // check the model this.assertEquals( "affe", model.getA().getA().getA(), "No affe is there!" ); model.dispose(); }, testModelWithAllSmoke() { this.__data = { a: [{ aa: ["affe"], ab: false, ac: [] }, {}, true, 15, "affe"], b: "Affe", c: { ca: 156, cb: [null, null], cc: true } }; // first create the classes before setting the data this.__marshaler.toClass(this.__data); // set the data var model = this.__marshaler.toModel(this.__data); this.assertNotNull(model, "No model set."); model.dispose(); }, testBubbleEventsDepth1() { this.__data = { a: 10, b: -15, c: 10.5e10 }; // first create the classes before setting the data this.__marshaler.toClass(this.__data, true); // set the data var model = this.__marshaler.toModel(this.__data); // check the event for a var self = this; this.assertEventFired( model, "changeBubble", function () { model.setA(0); }, function (e) { self.assertEquals( 0, e.getData().value, "Not the right value in the event." ); self.assertEquals( 10, e.getData().old, "Not the right old value in the event." ); self.assertEquals( "a", e.getData().name, "Not the right name in the event." ); self.assertString(e.getData().name, "name is not a String."); self.assertEquals( model, e.getData().item, "Not the right item in the event." ); }, "Change event not fired!" ); // check the event for b this.assertEventFired( model, "changeBubble", function () { model.setB(0); }, function (e) { self.assertEquals( 0, e.getData().value, "Not the right value in the event." ); self.assertEquals( -15, e.getData().old, "Not the right old value in the event." ); self.assertEquals( "b", e.getData().name, "Not the right name in the event." ); self.assertString(e.getData().name, "name is not a String."); self.assertEquals( model, e.getData().item, "Not the right item in the event." ); }, "Change event not fired!" ); model.dispose(); }, testBubbleEventsDepth2() { this.__data = { a: { b: 10, c: 20 } }; // first create the classes before setting the data this.__marshaler.toClass(this.__data, true); // set the data var model = this.__marshaler.toModel(this.__data); // check the event for b var self = this; this.assertEventFired( model, "changeBubble", function () { model.getA().setB(0); }, function (e) { self.assertEquals( 0, e.getData().value, "Not the right value in the event." ); self.assertEquals( 10, e.getData().old, "Not the right old value in the event." ); self.assertEquals( "a.b", e.getData().name, "Not the right name in the event." ); self.assertString(e.getData().name, "name is not a String."); self.assertEquals( model.getA(), e.getData().item, "Not the right item in the event." ); }, "Change event not fired!" ); model.getA().dispose(); // check the event for a this.assertEventFired( model, "changeBubble", function () { model.setA(true); }, function (e) { self.assertEquals( true, e.getData().value, "Not the right value in the event." ); self.assertEquals( "a", e.getData().name, "Not the right name in the event." ); self.assertString(e.getData().name, "name is not a String."); self.assertEquals( model, e.getData().item, "Not the right item in the event." ); }, "Change event not fired!" ); model.dispose(); }, testBubbleEventsDepth3() { this.__data = { a: { b: { c: 10 } } }; // first create the classes before setting the data this.__marshaler.toClass(this.__data, true); // set the data var model = this.__marshaler.toModel(this.__data); // check the event for c var self = this; this.assertEventFired( model, "changeBubble", function () { model.getA().getB().setC(0); }, function (e) { self.assertEquals( 0, e.getData().value, "Not the right value in the event." ); self.assertEquals( 10, e.getData().old, "Not the right old value in the event." ); self.assertEquals( "a.b.c", e.getData().name, "Not the right name in the event." ); self.assertString(e.getData().name, "name is not a String."); self.assertEquals( model.getA().getB(), e.getData().item, "Not the right item in the event." ); }, "Change event not fired!" ); model.dispose(); }, testBubbleEventsArrayDepth1() { this.__data = { a: [12, 23, 34] }; // first create the classes before setting the data this.__marshaler.toClass(this.__data, true); // set the data var model = this.__marshaler.toModel(this.__data); // check the event for the first array element var self = this; this.assertEventFired( model, "changeBubble", function () { model.getA().setItem(0, 1); }, function (e) { self.assertEquals( 1, e.getData().value, "Not the right value in the event." ); self.assertEquals( "a[0]", e.getData().name, "Not the right name in the event." ); self.assertString(e.getData().name, "name is not a String."); self.assertEquals( model.getA(), e.getData().item, "Not the right item in the event." ); }, "Change event not fired!" ); model.dispose(); }, testBubbleEventsArrayDepth2() { this.__data = { a: [{ b: 10 }, { b: 11 }] }; // first create the classes before setting the data this.__marshaler.toClass(this.__data, true); // set the data var model = this.__marshaler.toModel(this.__data); // check the event for the first array element var self = this; this.assertEventFired( model, "changeBubble", function () { model.getA().getItem(0).setB(0); }, function (e) { self.assertEquals( 0, e.getData().value, "Not the right value in the event." ); self.assertEquals( "a[0].b", e.getData().name, "Not the right name in the event." ); self.assertString(e.getData().name, "name is not a String."); self.assertEquals( model.getA().getItem(0), e.getData().item, "Not the right item in the event." ); }, "Change event not fired!" ); model.dispose(); }, testBubbleEventsArrayDepthAlot() { this.__data = { a: [[[[{ b: 10 }]]]] }; // first create the classes before setting the data this.__marshaler.toClass(this.__data, true); // set the data var model = this.__marshaler.toModel(this.__data); // check the event for the first array element var self = this; this.assertEventFired( model, "changeBubble", function () { model.getA().getItem(0).getItem(0).getItem(0).getItem(0).setB(0); }, function (e) { self.assertEquals( 0, e.getData().value, "Not the right value in the event." ); self.assertEquals( "a[0][0][0][0].b", e.getData().name, "Not the right name in the event." ); self.assertString(e.getData().name, "name is not a String."); self.assertEquals( model.getA().getItem(0).getItem(0).getItem(0).getItem(0), e.getData().item, "Not the right item in the event." ); }, "Change event not fired!" ); model.dispose(); }, testBubbleEventsArrayDepthAlotMix() { this.__data = { a: [{ b: [[{ c: { d: [0, 1] } }]] }] }; // first create the classes before setting the data this.__marshaler.toClass(this.__data, true); // set the data var model = this.__marshaler.toModel(this.__data); // check the event for the first array element var self = this; this.assertEventFired( model, "changeBubble", function () { model .getA() .getItem(0) .getB() .getItem(0) .getItem(0) .getC() .getD() .setItem(1, 12); }, function (e) { self.assertEquals( 12, e.getData().value, "Not the right value in the event." ); self.assertEquals( "a[0].b[0][0].c.d[1]", e.getData().name, "Not the right name in the event." ); self.assertString(e.getData().name, "name is not a String."); self.assertEquals( model.getA().getItem(0).getB().getItem(0).getItem(0).getC().getD(), e.getData().item, "Not the right item in the event." ); }, "Change event not fired!" ); model.dispose(); }, testBubbleEventsArrayLong() { this.__data = { a: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }; // first create the classes before setting the data this.__marshaler.toClass(this.__data, true); // set the data var model = this.__marshaler.toModel(this.__data); // check the event for the first array element var self = this; this.assertEventFired( model, "changeBubble", function () { model.getA().setItem(10, "AFFE"); }, function (e) { self.assertEquals( "AFFE", e.getData().value, "Not the right value in the event." ); self.assertEquals( "a[10]", e.getData().name, "Not the right name in the event." ); self.assertString(e.getData().name, "name is not a String."); self.assertEquals( model.getA(), e.getData().item, "Not the right item in the event." ); }, "Change event not fired!" ); model.dispose(); }, testBubbleEventsArrayReorder() { this.__data = { a: [11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }; // first create the classes before setting the data this.__marshaler.toClass(this.__data, true); // set the data var model = this.__marshaler.toModel(this.__data); model.getA().sort(); // check the event for the first array element var self = this; this.assertEventFired( model, "changeBubble", function () { model.getA().setItem(0, "AFFE"); }, function (e) { self.assertEquals( "AFFE", e.getData().value, "Not the right value in the event." ); self.assertEquals( "a[0]", e.getData().name, "Not the right name in the event." ); self.assertString(e.getData().name, "name is not a String."); self.assertEquals( model.getA(), e.getData().item, "Not the right item in the event." ); }, "Change event not fired!" ); model.dispose(); }, testBubbleEventsWithRemove() { qx.Class.define("qx.Test", { extend: qx.core.Object, include: qx.data.marshal.MEventBubbling, properties: { fonts: { event: "changeFonts", check: "qx.data.Array", apply: "_applyEventPropagation" } } }); var model = new qx.Test(); var fonts = new qx.data.Array(); model.setFonts(fonts); model.getFonts().push("one", "two", "three"); model.addListener("changeBubble", e => { this.assertEquals("fonts[0-2]", e.getData().name, "Wrong name"); this.assertString(e.getData().name, "name is not a String."); this.assertArrayEquals( ["one", "two", "three"], e.getData().old, "Wrong old data" ); this.assertEquals(0, e.getData().value.length, "Wrong data"); }); // remove all model.getFonts().removeAll(); this.assertEquals(0, model.getFonts().length, "The remove did not work."); fonts.dispose(); model.dispose(); }, "test model with and without bubble"() { var data = { pi: 1 }; // 1st create explicit *without* changeBubble var model1 = qx.data.marshal.Json.createModel(data, false); // 2nd create implicit *without* changeBubble var model2 = qx.data.marshal.Json.createModel(data); // 3rd create explicit *with* changeBubble var model3 = qx.data.marshal.Json.createModel(data, true); // 4th model is again *without* changeBubble // (should nevertheless result in a model-class *with* changeBubble) var model4 = qx.data.marshal.Json.createModel(data, false); // Check whether the above assumptions are correct this.assertFalse(qx.util.OOUtil.supportsEvent(model1, "changeBubble")); this.assertFalse(qx.util.OOUtil.supportsEvent(model2, "changeBubble")); this.assertTrue(qx.util.OOUtil.supportsEvent(model3, "changeBubble")); this.assertTrue(qx.util.OOUtil.supportsEvent(model4, "changeBubble")); // Check if bubble event really fires for models 3 & 4 [model3, model4].forEach(function (model) { this.assertEventFired( model, "changeBubble", function () { model.setPi(0); }, function (e) { var data = e.getData(); this.assertEquals( 0, data.value, "Not the right value in the event." ); this.assertEquals( 1, data.old, "Not the right old value in the event." ); this.assertEquals( "pi", data.name, "Not the right name in the event." ); this.assertEquals( model, data.item, "Not the right item in the event." ); }.bind(this), "Change event not fired!" ); }, this); }, "test toClass() toModel() match/mismatch"() { var data = { foo: "foo", bar: "bar" }; var marshaler = new qx.data.marshal.Json(); // // toClass *without*, toModel *with* should FAIL! // marshaler.toClass(data, false); this.assertException( function () { marshaler.toModel(data, true); }, Error, "Class 'qx.data.model.bar|foo' found, but it does not support changeBubble event." ); // // toClass *with*, toModel *without* should work // marshaler.toClass(data, true); marshaler.toModel(data, false); // // "auto" // var data2 = { foo2: "foo", bar2: "bar" }; marshaler.toClass(data2); // implicit *without* (auto) marshaler.toModel(data2); marshaler.toModel(data2, false); this.assertException( function () { marshaler.toModel(data2, true); }, Error, "Class 'qx.data.model.bar2|foo2' found, but it does not support changeBubble event." ); }, testAddValidationRule() { var propertiesSaved; var valN = function (data) { if (data < 10) { throw new qx.core.ValidationError("NNN"); } }; var valS = function (data) { if (data.length > 10) { throw new qx.core.ValidationError("SSS"); } }; var delegate = { getValidationRule(properties, propertyName) { if (propertyName == "n") { return valN; } else if (propertyName == "s") { return valS; } propertiesSaved = properties; } }; this.__marshaler.dispose(); this.__marshaler = new qx.data.marshal.Json(delegate); this.__marshaler.toClass(this.__data); var model = this.__marshaler.toModel(this.__data); // check for the right class hash this.assertEquals("b|n|s", propertiesSaved); // set working values model.setS("123456789"); model.setN(20); // set not working values this.assertException(function () { model.setS("01234567890123456789"); }, qx.core.ValidationError); this.assertException(function () { model.setN(1); }, qx.core.ValidationError); model.dispose(); }, testCustomValidator() { var delegate = { getJsonHash(data, includeBubbleEvents) { return ( Object.keys(data) .sort() .map(function (name) { return qx.lang.String.firstUp(name); }) .join("") + (includeBubbleEvents === true ? "#" : "") ); } }; this.__marshaler.dispose(); this.__marshaler = new qx.data.marshal.Json(delegate); this.__marshaler.toClass({ custom: 1, props: true }); this.assertTrue( qx.Class.isDefined("qx.data.model.CustomProps"), "Class not created." ); }, testQooxdooObject() { var qxObject = new qx.core.Object(); this.__data = { a: { b: qxObject } }; this.__marshaler.toClass(this.__data); // set the data var model = this.__marshaler.toModel(this.__data); // check the model this.assertEquals(qxObject, model.getA().getB(), "wrong qx object!"); model.dispose(); }, testDisposeListModel() { var model = qx.data.marshal.Json.createModel([{ name: "a" }]); var item = model.getItem(0); model.dispose(); this.assertTrue(item.isDisposed()); }, testValidIdentifier() { // its a debug warning so only check on debug if (qx.core.Environment.get("qx.debug")) { var data = { "#affe": 1 }; this.assertException( function () { // just check if the creation worked qx.data.marshal.Json.createModel(data).dispose(); }, null, "The key '#affe' is not a valid JavaScript identifier.", "1" ); data = { 1: 1, true: false }; // just check if the creation worked qx.data.marshal.Json.createModel(data).dispose(); data = { "''''": 1 }; this.assertException( function () { // just check if the creation worked qx.data.marshal.Json.createModel(data).dispose(); }, null, "The key '''''' is not a valid JavaScript identifier.", "3" ); data = { "§AFFE": 1 }; this.assertException( function () { // just check if the creation worked qx.data.marshal.Json.createModel(data).dispose(); }, null, "The key '§AFFE' is not a valid JavaScript identifier.", "4" ); data = { "ja!": 1 }; this.assertException( function () { // just check if the creation worked qx.data.marshal.Json.createModel(data).dispose(); }, null, "The key 'ja!' is not a valid JavaScript identifier.", "5" ); } }, /** * @ignore(qx.test.model) */ testGetModelClass() { qx.Class.define("qx.test.model.C", { extend: qx.core.Object, properties: { s: { event: "s" }, b: { event: "b" }, n: { event: "n" } } }); var self = this; var delegate = { getModelClass(properties) { self.assertEquals("b|n|s", properties); return qx.test.model.C; } }; this.__marshaler.dispose(); this.__marshaler = new qx.data.marshal.Json(delegate); this.__marshaler.toClass(this.__data); var model = this.__marshaler.toModel(this.__data); this.assertTrue(model instanceof qx.test.model.C); this.assertEquals("String", model.getS()); this.assertEquals(12, model.getN()); this.assertTrue(model.getB()); model.dispose(); qx.Class.undefine("qx.test.model.C"); }, testGetModelClassDepth() { var called = 0; var delegate = { getModelClass: function (properties, object, parentProperty, depth) { called++; if (properties == "a") { this.assertEquals(data, object); this.assertNull(parentProperty); this.assertEquals(0, depth); } else if (properties == "b") { this.assertEquals(data.a, object); this.assertEquals("a", parentProperty); this.assertEquals(1, depth); } else if (properties == "c") { this.assertEquals(data.a.b[0], object); this.assertEquals("b[0]", parentProperty); this.assertEquals(3, depth); } else { this.fail("Unknown property in the marshaler."); } }.bind(this) }; this.__marshaler.dispose(); var data = { a: { b: [{ c: 1 }] } }; this.__marshaler = new qx.data.marshal.Json(delegate); this.__marshaler.toClass(data); this.assertEquals(3, called); var model = this.__marshaler.toModel(data); this.assertEquals(6, called); model.dispose(); }, testGetModelClassIgnore() { qx.Class.define("qx.test.model.C", { extend: qx.core.Object, properties: { b: { event: "b" } } }); var self = this; var delegate = { getModelClass(properties) { self.assertEquals("b|n|s", properties); return qx.test.model.C; } }; this.__marshaler.dispose(); this.__marshaler = new qx.data.marshal.Json(delegate); this.__marshaler.toClass(this.__data); var model = this.__marshaler.toModel(this.__data); this.assertTrue(model instanceof qx.test.model.C); this.assertUndefined(model.getS); this.assertUndefined(model.getN); this.assertTrue(model.getB()); model.dispose(); qx.Class.undefine("qx.test.model.C"); }, testGetModelSuperClass() { var called = 0; var delegate = { getModelSuperClass: function (properties, parentProperty, depth) { called++; if (properties == "a") { this.assertNull(parentProperty); this.assertEquals(0, depth); } else if (properties == "b") { this.assertEquals("a", parentProperty); this.assertEquals(1, depth); } else if (properties == "c") { this.assertEquals("b[0]", parentProperty); this.assertEquals(3, depth); } else { this.fail("Unknown property in the marshaler."); } }.bind(this) }; this.__marshaler.dispose(); var data = { a: { b: [{ c: 1 }] } }; this.__marshaler = new qx.data.marshal.Json(delegate); this.__marshaler.toClass(data); this.assertEquals(3, called); }, testGetModelMixins() { var called = 0; var delegate = { getModelMixins: function (properties, parentProperty, depth) { called++; if (properties == "a") { this.assertNull(parentProperty); this.assertEquals(0, depth); } else if (properties == "b") { this.assertEquals("a", parentProperty); this.assertEquals(1, depth); } else if (properties == "c") { this.assertEquals("b[0]", parentProperty); this.assertEquals(3, depth); } else { this.fail("Unknown property in the marshaler."); } }.bind(this) }; this.__marshaler.dispose(); var data = { a: { b: [{ c: 1 }] } }; this.__marshaler = new qx.data.marshal.Json(delegate); this.__marshaler.toClass(data); this.assertEquals(3, called); }, testGetPropertyMapping() { var delegate = { getPropertyMapping(property, properties) { return property + property + property; } }; this.__marshaler.dispose(); this.__marshaler = new qx.data.marshal.Json(delegate); this.__marshaler.toClass(this.__data); var model = this.__marshaler.toModel(this.__data); this.assertEquals("String", model.getSss()); this.assertEquals(12, model.getNnn()); this.assertTrue(model.getBbb()); model.dispose(); }, testIgnoreParent() { var called = 0; var delegate = { ignore: function (properties, parentProperty, depth) { called++; if (properties == "a") { this.assertNull(parentProperty); this.assertEquals(0, depth); } else if (properties == "b") { this.assertEquals("a", parentProperty); this.assertEquals(1, depth); } else if (properties == "c") { this.assertEquals("b[0]", parentProperty); this.assertEquals(3, depth); } else { this.fail("Unknown property in the marshaler."); } }.bind(this) }; this.__marshaler.dispose(); var data = { a: { b: [{ c: 1 }] } }; this.__marshaler = new qx.data.marshal.Json(delegate); this.__marshaler.toClass(data); this.assertEquals(3, called); }, testIgnoreDepth() { var delegate = { ignore(properties, parentProperty, depth) { return depth >= 1; } }; this.__marshaler.dispose(); this.__marshaler = new qx.data.marshal.Json(delegate); var data = { a: [0], b: { x: 1 }, c: { y: 2 } }; this.__marshaler.toClass(data); var model = this.__marshaler.toModel(data); this.assertEquals(0, model.getA()[0]); this.assertEquals(1, model.getB().x); this.assertEquals(2, model.getC().y); model.dispose(); }, testIgnoreProperties() { var delegate = { ignore(properties, parentProperty, depth) { return properties == "x"; } }; this.__marshaler.dispose(); this.__marshaler = new qx.data.marshal.Json(delegate); var data = { a: [], b: { x: 1 }, c: { y: 2 } }; this.__marshaler.toClass(data); var model = this.__marshaler.toModel(data); this.assertInstance(model.getA(), qx.data.Array); this.assertEquals(1, model.getB().x); this.assertInstance(model.getC(), qx.core.Object); this.assertEquals(2, model.getC().getY()); model.dispose(); }, testBubbleSpliceRemoveAndAdd() { var data = [{ label: "Desktop" }]; var model = qx.data.marshal.Json.createModel(data, true); var spy = this.spy(); model.addListener("changeBubble", spy); model.splice(1, 1, model.getItem(0)); this.assertCalledOnce(spy); model.getItem(0).setLabel("pistole"); this.assertCalledTwice(spy); }, testGetArrayClassSimple() { qx.Class.define("qx.test.Array", { extend: qx.data.Array }); var delegate = { getArrayClass: function (parentProperty, depth) { this.assertNull(parentProperty); this.assertEquals(0, depth, "'depth' property is wrong"); return qx.test.Array; }.bind(this) }; this.__marshaler.dispose(); this.__marshaler = new qx.data.marshal.Json(delegate); var data = ["a", "b"]; this.__marshaler.toClass(data); var model = this.__marshaler.toModel(data); this.assertInstance(model, qx.test.Array); model.dispose(); qx.Class.undefine("qx.test.Array"); }, testGetArrayClassAdvanced() { qx.Class.define("qx.test.Array", { extend: qx.data.Array }); var called = 0; var delegate = { getArrayClass: function (parentProperty, depth) { called++; if (parentProperty == "a") { this.assertEquals(1, depth, "'depth' property is wrong"); return null; } else if (parentProperty == "b") { this.assertEquals(1, depth, "'depth' property is wrong"); return qx.test.Array; } else if (parentProperty == "e") { this.assertEquals(2, depth, "'depth' property is wrong"); return qx.test.Array; } else if (parentProperty == "f") { this.assertEquals(2, depth, "'depth' property is wrong"); return null; } else { this.fail("Unknown 'parentProperty' in the marshaler."); } }.bind(this) }; this.__marshaler.dispose(); this.__marshaler = new qx.data.marshal.Json(delegate); var data = { a: [], b: [], c: { d: "d", e: [], f: [] } }; this.__marshaler.toClass(data); var model = this.__marshaler.toModel(data); this.assertInstance(model.getA(), qx.data.Array); this.assertInstance(model.getB(), qx.test.Array); this.assertInstance(model.getC().getE(), qx.test.Array); this.assertInstance(model.getC().getF(), qx.data.Array); this.assertEquals(4, called); model.dispose(); qx.Class.undefine("qx.test.Array"); } } });