@qooxdoo/framework
Version:
The JS Framework for Coders
1,504 lines (1,272 loc) • 42.7 kB
JavaScript
/* ************************************************************************
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");
}
}
});