@qooxdoo/framework
Version:
The JS Framework for Coders
623 lines (504 loc) • 13.9 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:
* Fabian Jakobs (fjakobs)
************************************************************************ */
/**
* @ignore(qx.test.i.*)
*/
qx.Class.define("qx.test.Interface",
{
extend : qx.dev.unit.TestCase,
members :
{
setUp : function() {
qx.Interface.define("qx.test.i.ICar",
{
members :
{
startEngine : function() {
return true;
}
},
properties : { color : {} }
});
},
tearDown : function() {
qx.Class.undefine("qx.test.i.ICar");
},
testClassImplements : function()
{
// test correct implementations
qx.Class.define("qx.test.i.Audi",
{
extend : Object,
construct : function() {},
implement : [ qx.test.i.ICar ],
members :
{
startEngine : function() {
return "start";
}
},
statics :
{
honk : function() {
return "honk";
}
},
properties : { color : { } }
});
var audi = new qx.test.i.Audi("audi");
this.assertTrue(qx.Interface.classImplements(qx.test.i.Audi, qx.test.i.ICar));
qx.Class.undefine("qx.test.i.Audi");
},
testEverythingImplemented : function() {
qx.Class.define("qx.test.i.Bmw1",
{
extend : Object,
construct : function() {},
members :
{
startEngine : function() {
return "start";
}
},
statics :
{
honk : function() {
return "honk";
}
},
properties : { color : { } }
});
this.assertTrue(qx.Interface.classImplements(qx.test.i.Bmw1, qx.test.i.ICar));
qx.Class.undefine("qx.test.i.Bmw1");
},
testMissingMembers : function() {
qx.Class.define("qx.test.i.Bmw2",
{
extend : Object,
construct : function() {},
statics :
{
honk : function() {
return "honk";
}
},
properties : { color : { } }
});
this.assertFalse(qx.Interface.classImplements(qx.test.i.Bmw2, qx.test.i.ICar));
qx.Class.undefine("qx.test.i.Bmw2");
},
testMissingStatics : function() {
// (ie it does implement all necessary)
qx.Class.define("qx.test.i.Bmw3",
{
extend : Object,
construct : function() {},
members :
{
startEngine : function() {
return "start";
}
},
properties : { color : { } }
});
this.assertTrue(qx.Interface.classImplements(qx.test.i.Bmw3, qx.test.i.ICar));
qx.Class.undefine("qx.test.i.Bmw3");
},
testMissingProperties : function() {
qx.Class.define("qx.test.i.Bmw4",
{
extend : Object,
construct : function() {},
members :
{
startEngine : function() {
return "start";
}
},
statics :
{
honk : function() {
return "honk";
}
}
});
this.assertFalse(qx.Interface.classImplements(qx.test.i.Bmw4, qx.test.i.ICar));
qx.Class.undefine("qx.test.i.Bmw4");
},
testWithDebug : function() {
if (this.isDebugOn())
{
this.assertException(function() {
var i = new qx.test.i.ICar();
}, Error);
// nothing defined
this.assertException(function()
{
qx.Class.define("qx.test.i.Audi1",
{
extend : Object,
construct : function() {},
implement : [ qx.test.i.ICar ]
});
},
Error, new RegExp('Implementation of method .* is missing'));
// members not defined
this.assertException(function()
{
qx.Class.define("qx.test.i.Audi2",
{
extend : Object,
construct : function() {},
implement : [ qx.test.i.ICar ],
statics :
{
honk : function() {
return "honk";
}
},
properties : { color : { } }
});
},
Error, 'Implementation of method "startEngine" is missing');
// property not defined
this.assertException(function()
{
qx.Class.define("qx.test.i.Audi4",
{
extend : Object,
construct : function() {},
implement : [ qx.test.i.ICar ],
members :
{
startEngine : function() {
return "start";
}
},
statics :
{
honk : function() {
return "honk";
}
}
});
},
Error, new RegExp("property .* not supported"));
}
},
testAssertions : function()
{
qx.Interface.define("qx.test.i.IComplex",
{
members :
{
add : function(a) {
this.assertArgumentsCount(arguments, 1, 1);
this.assertInterface(a.constructor, qx.test.i.IComplex);
},
setReal : function(r) {
this.assertArgumentsCount(arguments, 1, 1);
this.assertType(r, "number");
},
abs : function() {
this.assert(arguments[0] == undefined);
}
}
});
qx.Class.define("qx.test.i.Complex",
{
extend : qx.core.Object,
implement : qx.test.i.IComplex,
construct : function(real, imag)
{
this._real = real;
this._imag = imag;
},
members :
{
add : function(a)
{
this._real += a._real;
this._imag += a._imag;
},
setReal : function(r) {
this._real = r;
},
abs : function() {
return Math.sqrt((this._real * this._real) + (this._imag + this._imag));
},
toString : function() {
return this._real + "+" + this._imag + "i";
}
}
});
var a = new qx.test.i.Complex(1, 1);
var b = new qx.test.i.Complex(2, -3.4);
// valid usage
a.add(b);
a.setReal(20);
a.abs();
// invalid usage
if (this.isDebugOn())
{
this.assertException(function() {
a.add(b, b);
}, qx.core.AssertionError, null, "a");
this.assertException(function() {
a.setReal();
}, qx.core.AssertionError, null, "b");
this.assertException(function() {
a.setReal(1, 2);
}, qx.core.AssertionError, null, "c");
this.assertException(function() {
a.setReal("Juhu");
}, qx.core.AssertionError, null, "d");
this.assertException(function() {
a.abs({});
}, qx.core.AssertionError, null, "e");
this.assertException(function() {
a.add("Juhu");
}, qx.core.AssertionError, null, "f");
};
},
testProperties : function()
{
qx.Interface.define("qx.test.i.IProperties1", {
properties : {
value : {}
}
});
qx.Class.define("qx.test.i.Properties1",
{
extend : qx.core.Object,
implement : [qx.test.i.IProperties1],
properties :
{
value : { check : "Integer"}
}
});
if (this.isDebugOn())
{
this.assertException(function() {
qx.Class.define("qx.test.i.Properties2",
{
extend : qx.core.Object,
implement : [qx.test.i.IProperties1],
members :
{
getValue : function() {},
setValue : function(value) {}
}
});
});
};
qx.Interface.define("qx.test.i.IProperties2",
{
members :
{
getValue : function() {},
setValue : function(value) {}
}
});
qx.Class.define("qx.test.i.Properties3",
{
extend : qx.core.Object,
implement : [qx.test.i.IProperties2],
properties :
{
value : { check : "Integer"}
}
});
qx.Class.define("qx.test.i.Properties4",
{
extend : qx.core.Object,
implement : [qx.test.i.IProperties2],
members :
{
getValue : function() {},
setValue : function(value) {}
}
});
},
testEvents : function()
{
qx.Interface.define("qx.test.i.IEvents1",
{
events : {
"change" : "qx.event.type.Event"
}
});
qx.Class.define("qx.test.i.Event1",
{
extend : qx.core.Object,
implement : [qx.test.i.IEvents1],
events : {
change : "qx.event.type.Event"
}
});
if (this.isDebugOn())
{
this.assertException(function() {
qx.Class.define("qx.test.i.Event2",
{
extend : qx.core.Object,
implement : [qx.test.i.IEvents1]
});
});
};
},
testIncludes : function()
{
qx.Interface.define("qx.test.i.IMember",
{
members :
{
sayJuhu : function() {
return true;
}
}
});
qx.Interface.define("qx.test.i.IProperties",
{
properties :
{
"color" : {},
"name" : {}
}
});
qx.Interface.define("qx.test.i.IAll", { extend : [ qx.test.i.IMember, qx.test.i.IProperties ] });
qx.Interface.define("qx.test.i.IOther",
{
members :
{
bar : function() {
return true;
}
}
});
var classDef =
{
extend : Object,
implement : qx.test.i.IAll,
members :
{
sayJuhu : function() {}
},
statics :
{
sayHello : function() {
return true;
}
},
properties :
{
"color" : { },
"name" : { }
}
};
// all implemented
var def = qx.lang.Object.clone(classDef);
qx.Class.define("qx.test.i.Implement1", def);
this.assertTrue(qx.Class.implementsInterface(qx.test.i.Implement1, qx.test.i.IAll), "implements IAll");
this.assertTrue(qx.Class.implementsInterface(qx.test.i.Implement1, qx.test.i.IMember), "implements IMember");
this.assertTrue(qx.Class.implementsInterface(qx.test.i.Implement1, qx.test.i.IProperties), "implements IProperties");
this.assertFalse(qx.Class.implementsInterface(qx.test.i.Implement1, qx.test.i.IOther), "not implements IOther");
// no members
var def = qx.lang.Object.clone(classDef);
delete (def.members);
if (this.isDebugOn())
{
this.assertException(function() {
qx.Class.define("qx.test.i.Implement2", def);
}, Error, "Implementation of method", "No members defined.");
};
// no properties
var def = qx.lang.Object.clone(classDef);
delete (def.properties);
if (this.isDebugOn())
{
this.assertException(function() {
qx.Class.define("qx.test.i.Implement4", def);
}, Error, new RegExp("property .* is not supported"), "No properties defined.");
};
},
/**
* abstract classes may define an interface and implement it only partially
* sub classes must implement the missing methods
*/
testAbstractClass : function()
{
qx.Interface.define("qx.test.i.IJuhu",
{
members :
{
sayJuhu : function() {},
sayKinners : function() {}
}
});
// should not raise an exception
qx.Class.define("qx.test.i.AbstractJuhu1", {
extend : qx.core.Object,
implement : qx.test.i.IJuhu,
type : "abstract"
});
// should not raise an exception
qx.Class.define("qx.test.i.AbstractJuhu2", {
extend : qx.core.Object,
implement : qx.test.i.IJuhu,
type : "abstract",
members :
{
sayJuhu : function() { return "Juhu"; }
}
});
// should raise an exception
if (this.isDebugOn())
{
this.assertException(function() {
qx.Class.define("qx.test.i.Juhu1", {
extend : qx.test.i.AbstractJuhu1,
members :
{
sayJuhu : function() { return "Juhu"; }
}
});
}, Error, '.*Implementation of method "sayKinners" is missing in class "qx.test.i.Juhu1" required by interface "qx.test.i.IJuhu"');
};
qx.Class.define("qx.test.i.Juhu1", {
extend : qx.test.i.AbstractJuhu2,
members :
{
sayKinners : function() { return "Kinners"; }
}
});
},
testGeneratedIsMethods: function() {
qx.Interface.define("qx.test.i.IIs",
{
members :
{
isProp : function() {}
}
});
qx.Class.define("qx.test.i.Is", {
extend : qx.core.Object,
implement : qx.test.i.IIs,
properties : {
prop : {
check : "Boolean",
init : true
}
}
});
}
}
});