base.html revision 0709cd166604645c5511b892413b44ad6bce6b64
<html>
<head>
<title>Base Tests</title>
#console .yui3-console-entry {
padding:2px;
margin:0px;
min-height:0;
}
#console .yui3-console-entry-fail .yui3-console-entry-cat {
background-color:red;
}
#console .yui3-console-entry-pass .yui3-console-entry-cat {
background-color:green;
}
#console .yui3-console-entry-perf .yui3-console-entry-cat {
background-color:blue;
}
#console {
position:static;
}
html, body {
height:100%;
}
</style>
</head>
<body class="yui3-skin-sam">
<div id="testbed" class="yui3-skin-foo"></div>
<script>
YUI({useBrowserConsole:false, filter:"raw"}).use('test', 'base', 'console', function (Y) {
// NOTE: Attribute's unit tests cover a large section of Base's functionality when it comes to dealing with attributes.
var suite = new Y.Test.Suite("Base Tests");
suite.add(new Y.Test.Case({
name : "BaseBuild",
"test:create-basic": function () {
var expectedMethodCalls = [
"ext1::constructor",
"myClass::initializer",
"ext1::constructor",
"myClass::initializer",
"myClass::methodOne",
"myClass::methodOne",
"ext1::extOne",
"ext1::extOne"],
actualMethodCalls = [];
function Ext1() {
actualMethodCalls.push("ext1::constructor");
}
Ext1.prototype.extOne = function() {
actualMethodCalls.push("ext1::extOne");
};
var MyClass = Y.Base.create("myClass", Y.Base, [Ext1], {
initializer: function() {
actualMethodCalls.push("myClass::initializer");
},
methodOne: function() {
actualMethodCalls.push("myClass::methodOne");
}
}, {
STATIC_ONE: "static_one"
});
// using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
var o1 = new MyClass({foo:true});
var o2 = new MyClass({foo:true});
Y.Assert.isFunction(o1.extOne, "Extension method extOne not found on o1");
Y.Assert.isFunction(o2.extOne, "Extension method extOne not found on o2");
Y.Assert.isFunction(o1.methodOne, "Prototype method methodOne not found on o1");
Y.Assert.isFunction(o2.methodOne, "Prototype method methodOne not found on o2");
Y.Assert.areEqual(o1.constructor.STATIC_ONE, "static_one", "STATIC_ONE not found on o1's constructor");
Y.Assert.areEqual(o2.constructor.STATIC_ONE, "static_one", "STATIC_ONE not found on o2's constructor");
Y.Assert.areEqual(o1.constructor.NAME, "myClass", "NAME not found on o1's constructor");
Y.Assert.areEqual(o2.constructor.NAME, "myClass", "NAME not found on o2's constructor");
o1.methodOne();
o2.methodOne();
o1.extOne();
o2.extOne();
Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
},
"test:mix-basic": function() {
var expectedMethodCalls = [
"myClass::constructor",
"ext1::constructor",
"myClass::initializer",
"myClass::constructor",
"ext1::constructor",
"myClass::initializer",
"myClass::methodOne",
"myClass::methodOne",
"ext1::extOne",
"ext1::extOne"],
actualMethodCalls = [];
function Ext1() {
actualMethodCalls.push("ext1::constructor");
}
Ext1.prototype.extOne = function() {
actualMethodCalls.push("ext1::extOne");
};
function MyClass(config) {
actualMethodCalls.push("myClass::constructor");
MyClass.superclass.constructor.apply(this, arguments);
}
initializer: function() {
actualMethodCalls.push("myClass::initializer");
},
methodOne: function() {
actualMethodCalls.push("myClass::methodOne");
}
}, {
STATIC_ONE: "static_one",
NAME: "myClass"
});
Y.Base.mix(MyClass, [Ext1]);
// using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
var o1 = new MyClass();
var o2 = new MyClass();
Y.Assert.isFunction(o1.extOne, "Extension method extOne not found on o1");
Y.Assert.isFunction(o2.extOne, "Extension method extOne not found on o2");
Y.Assert.isFunction(o1.methodOne, "Prototype method methodOne not found on o1");
Y.Assert.isFunction(o2.methodOne, "Prototype method methodOne not found on o2");
Y.Assert.areEqual(o1.constructor.STATIC_ONE, "static_one", "STATIC_ONE not found on o1's constructor");
Y.Assert.areEqual(o2.constructor.STATIC_ONE, "static_one", "STATIC_ONE not found on o2's constructor");
o1.methodOne();
o2.methodOne();
o1.extOne();
o2.extOne();
Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
},
"test:initializer": function() {
var expectedMethodCalls = [
"ext1::constructor",
"myClass::initializer",
"ext1::initializer",
"ext1::constructor",
"myClass::initializer",
"ext1::initializer"],
actualMethodCalls = [];
function Ext1(cfg) {
actualMethodCalls.push("ext1::constructor");
Y.Assert.isNotUndefined(cfg);
}
Ext1.prototype.initializer = function(cfg) {
actualMethodCalls.push("ext1::initializer");
Y.Assert.isNotUndefined(cfg);
};
var MyClass = Y.Base.create("myClass", Y.Base, [Ext1], {
initializer: function(cfg) {
actualMethodCalls.push("myClass::initializer");
Y.Assert.isNotUndefined(cfg);
}
});
// using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
var o1 = new MyClass({foo:true});
var o2 = new MyClass({foo:true});
Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
},
"test:destructor": function() {
var expectedMethodCalls = [
"ext1::destructor",
"myClass::destructor",
"ext1::destructor",
"myClass::destructor"],
actualMethodCalls = [];
function Ext1(cfg) {}
Ext1.prototype.destructor = function(cfg) {
actualMethodCalls.push("ext1::destructor");
};
var MyClass = Y.Base.create("myClass", Y.Base, [Ext1], {
destructor: function(cfg) {
actualMethodCalls.push("myClass::destructor");
}
});
// using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
var o1 = new MyClass({foo:true});
var o2 = new MyClass({foo:true});
o1.destroy();
o2.destroy();
Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
},
"test:attrs" : function() {
var actualMethodCalls = [],
expectedMethodCalls = [
"ext1::attr2::setter", // once for lazy o1 - This was news to me: we should optimize it as part off Attr performance
"ext1::attr2::setter", // once for set o1
"ext1::attr2::setter", // once for lazy o2
"ext1::attr2::setter" // once for set o2
];
function Ext1() {}
Ext1.ATTRS = {
attr1 : {
value:"attr1-ext1"
},
attr2 : {
value:"attr2-ext1",
setter: function(val) {
actualMethodCalls.push("ext1::attr2::setter");
return val;
}
},
attr3: {
value:"attr3-ext1"
}
};
var MyClass = Y.Base.create("myClass", Y.Base, [Ext1]);
// using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
var o1 = new MyClass();
var o2 = new MyClass();
o1.set("attr2", "foo");
o2.set("attr2", "foo");
Y.Assert.areEqual("attr1-ext1", o1.get("attr1"), "o1 attr1 incorrect");
Y.Assert.areEqual("attr1-ext1", o2.get("attr1"), "o2 attr1 incorrect");
Y.Assert.areEqual("foo", o1.get("attr2"), "o1 attr2 incorrect");
Y.Assert.areEqual("foo", o2.get("attr2"), "o2 attr2 incorrect");
Y.Assert.areEqual("attr3-ext1", o1.get("attr3"), "o1 attr3 incorrect");
Y.Assert.areEqual("attr3-ext1", o2.get("attr3"), "o2 attr3 incorrect");
Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
},
"test:aggregates" : function() {
function Ext1() {}
Ext1.HTML_PARSER = {
a:"aa",
b:"bb"
};
function MyWidget(config) {
MyWidget.superclass.constructor.apply(this, arguments);
}
HTML_PARSER : {
a:"a"
},
_buildCfg : {
aggregates : ["HTML_PARSER"]
}
});
var MyClass = Y.Base.create("myClass", MyWidget, [Ext1]);
// using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
var o1 = new MyClass();
var o2 = new MyClass();
Y.ObjectAssert.areEqual({a:"aa", b:"bb"}, o1.constructor.HTML_PARSER, "o1 HTML_PARSER not aggregated correctly");
Y.ObjectAssert.areEqual({a:"aa", b:"bb"}, o2.constructor.HTML_PARSER, "o2 HTML_PARSER not aggregated correctly");
},
"test:overrides-ext-wins" : function() {
var actualMethodCalls = [],
expectedMethodCalls = [
"ext1::attr2::setter", // once for lazy o1
"ext1::attr2::setter", // once for set o1
"ext1::attr2::setter", // once for lazy o2
"ext1::methodOne",
"ext1::methodOne"
];
function Ext1() {}
Ext1.prototype.methodOne = function() {
actualMethodCalls.push("ext1::methodOne");
};
Ext1.ATTRS = {
attr1 : {
value:"attr1-ext1"
},
attr2 : {
value:"attr2-ext1",
setter: function(val) {
actualMethodCalls.push("ext1::attr2::setter");
return val;
}
},
attr3: {
value:"attr3-ext1"
}
};
function MyClass() {
MyClass.superclass.constructor.apply(this, arguments);
}
MyClass.NAME = "myClass";
MyClass.ATTRS = {
attr1 : {
value:"attr1-myClass"
},
attr2 : {
value:"attr2-myClass",
setter: function(val) {
actualMethodCalls.push("myClass::attr2::setter");
return val;
}
},
attr4 : {
value:"attr4-myClass"
}
};
methodOne : function() {
actualMethodCalls.push("myClass::methodOne");
}
});
Y.Base.mix(MyClass, [Ext1]);
// using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
var o1 = new MyClass();
var o2 = new MyClass();
// only set o1
o1.set("attr2", "foo");
Y.Assert.areEqual("attr1-ext1", o1.get("attr1"), "o1 attr1 incorrect");
Y.Assert.areEqual("attr1-ext1", o2.get("attr1"), "o2 attr1 incorrect");
Y.Assert.areEqual("foo", o1.get("attr2"), "o1 attr2 incorrect");
Y.Assert.areEqual("attr2-ext1", o2.get("attr2"), "o2 attr2 incorrect");
Y.Assert.areEqual("attr3-ext1", o1.get("attr3"), "o1 attr3 incorrect");
Y.Assert.areEqual("attr3-ext1", o2.get("attr3"), "o2 attr3 incorrect");
Y.Assert.areEqual("attr4-myClass", o1.get("attr4"), "o1 attr4 incorrect");
Y.Assert.areEqual("attr4-myClass", o2.get("attr4"), "o2 attr4 incorrect");
o1.methodOne();
o2.methodOne();
Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
},
"test:overrides-host-wins" : function() {
var actualMethodCalls = [],
expectedMethodCalls = [
"myClass::attr2::setter", // once for lazy o1
"myClass::attr2::setter", // once for set o1
"myClass::attr2::setter", // once for lazy o2
"myClass::methodOne",
"myClass::methodOne"
];
function Ext1() {}
Ext1.prototype.methodOne = function() {
actualMethodCalls.push("ext1::methodOne");
};
Ext1.ATTRS = {
attr1 : {
value:"attr1-ext1"
},
attr2 : {
value:"attr2-ext1",
setter: function(val) {
actualMethodCalls.push("ext1::attr2::setter");
return val;
}
},
attr3: {
value:"attr3-ext1"
}
};
var MyClass = Y.Base.create("myClass", Y.Base, [Ext1], {
methodOne : function() {
actualMethodCalls.push("myClass::methodOne");
}
}, {
ATTRS : {
attr1 : {
value:"attr1-myClass"
},
attr2 : {
value:"attr2-myClass",
setter: function(val) {
actualMethodCalls.push("myClass::attr2::setter");
return val;
}
},
attr4 : {
value:"attr4-myClass"
}
}
});
// Using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
var o1 = new MyClass();
var o2 = new MyClass();
// only set o1
o1.set("attr2", "foo");
Y.Assert.areEqual("attr1-myClass", o1.get("attr1"), "o1 attr1 incorrect");
Y.Assert.areEqual("attr1-myClass", o2.get("attr1"), "o2 attr1 incorrect");
Y.Assert.areEqual("foo", o1.get("attr2"), "o1 attr2 incorrect");
Y.Assert.areEqual("attr2-myClass", o2.get("attr2"), "o2 attr2 incorrect");
Y.Assert.areEqual("attr3-ext1", o1.get("attr3"), "o1 attr3 incorrect");
Y.Assert.areEqual("attr3-ext1", o2.get("attr3"), "o2 attr3 incorrect");
Y.Assert.areEqual("attr4-myClass", o1.get("attr4"), "o1 attr4 incorrect");
Y.Assert.areEqual("attr4-myClass", o2.get("attr4"), "o2 attr4 incorrect");
o1.methodOne();
o2.methodOne();
Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
},
"test:multiext-complex" : function() {
var actualMethodCalls = [],
expectedMethodCalls = [
"ext1::constructor",
"ext2::constructor",
"myClass::initializer",
"ext1::initializer",
"ext2::initializer",
"ext1::constructor",
"ext2::constructor",
"myClass::initializer",
"ext1::initializer",
"ext2::initializer",
"ext2::attr3::setter",
"ext2::attr3::setter",
"myClass::methodOne",
"myClass::methodOne",
"myClass::methodTwo",
"myClass::methodTwo",
"ext2::methodThree",
"ext2::methodThree",
"ext2::methodFour",
"ext2::methodFour",
"myClass::methodFive",
"myClass::methodFive"
];
function Ext1() {
actualMethodCalls.push("ext1::constructor");
}
Ext1.prototype.initializer = function() {
actualMethodCalls.push("ext1::initializer");
};
Ext1.prototype.methodTwo = function() {
actualMethodCalls.push("ext1::methodTwo");
};
Ext1.prototype.methodThree = function() {
actualMethodCalls.push("ext1::methodThree");
};
Ext1.ATTRS = {
attr2 : {
value:"ext1-attr2"
},
attr3 : {
value:"ext1-attr3",
setter: function(val) {
actualMethodCalls.push("ext1::attr3::setter");
return val;
}
},
attr4: {
value:"ext1-attr4"
}
};
function Ext2() {
actualMethodCalls.push("ext2::constructor");
}
Ext2.prototype.initializer = function() {
actualMethodCalls.push("ext2::initializer");
};
Ext2.prototype.methodThree = function() {
actualMethodCalls.push("ext2::methodThree");
};
Ext2.prototype.methodFour = function() {
actualMethodCalls.push("ext2::methodFour");
};
Ext2.ATTRS = {
attr3 : {
value:"ext2-attr3",
setter: function(val) {
actualMethodCalls.push("ext2::attr3::setter");
return val;
}
},
attr4 : {
value:"ext2-attr4"
}
};
var MyClass = Y.Base.create("myClass", Y.Base, [Ext1, Ext2], {
initializer: function() {
actualMethodCalls.push("myClass::initializer");
},
methodOne : function() {
actualMethodCalls.push("myClass::methodOne");
},
methodTwo : function() {
actualMethodCalls.push("myClass::methodTwo");
},
methodFive : function() {
actualMethodCalls.push("myClass::methodFive");
}
}, {
ATTRS : {
attr1 : {
value:"myClass-attr1"
},
attr5 : {
value:"myClass-attr5"
}
}
});
var o1 = new MyClass();
var o2 = new MyClass();
Y.Assert.areEqual("myClass-attr1", o1.get("attr1"), "o1 attr1 incorrect");
Y.Assert.areEqual("myClass-attr1", o2.get("attr1"), "o2 attr1 incorrect");
Y.Assert.areEqual("ext1-attr2", o1.get("attr2"), "o1 attr2 incorrect");
Y.Assert.areEqual("ext1-attr2", o2.get("attr2"), "o2 attr2 incorrect");
Y.Assert.areEqual("ext2-attr3", o1.get("attr3"), "o1 attr3 incorrect");
Y.Assert.areEqual("ext2-attr3", o2.get("attr3"), "o2 attr3 incorrect");
Y.Assert.areEqual("ext2-attr4", o1.get("attr4"), "o1 attr4 incorrect");
Y.Assert.areEqual("ext2-attr4", o2.get("attr4"), "o2 attr4 incorrect");
Y.Assert.areEqual("myClass-attr5", o1.get("attr5"), "o1 attr5 incorrect");
Y.Assert.areEqual("myClass-attr5", o2.get("attr5"), "o2 attr5 incorrect");
o1.methodOne();
o2.methodOne();
o1.methodTwo();
o2.methodTwo();
Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
},
"test:classstructure" : function() {
function Ext1() {}
Ext1.prototype.extOne = function() {};
function Ext2() {}
Ext2.prototype.extTwo = function() {};
var MyClassTwo = Y.Base.create("myClassTwo", Y.Base, [Ext1, Ext2], {
initializer: function() {},
methodOne: function() {}
});
var MyClassOne = Y.Base.create("myClassOne", Y.Base, [Ext1], {
initializer: function() {},
methodOne: function() {}
});
var o1 = new MyClassOne();
var o2 = new MyClassTwo();
Y.Assert.isTrue(o1.hasImpl(Ext1), "o1 should pass hasImpl(Ext1)");
Y.Assert.isFalse(o1.hasImpl(Ext2), "o1 should fail hasImpl(Ext2)");
Y.Assert.isTrue(o2.hasImpl(Ext1), "o2 should pass hasImpl(Ext1)");
Y.Assert.isTrue(o2.hasImpl(Ext2), "o2 should pass hasImpl(Ext1)");
Y.Assert.isTrue(o1 instanceof MyClassOne, "o1 should be an instanceof MyClassOne");
Y.Assert.isTrue(o1 instanceof Y.Base, "o1 should be an instanceof Base");
Y.Assert.isTrue(o2 instanceof MyClassTwo, "o2 should be an instanceof MyClassTwo");
Y.Assert.isTrue(o2 instanceof Y.Base, "o2 should be an instanceof Base");
Y.Assert.isFalse(o1 instanceof MyClassTwo, "o1 should NOT be an instanceof MyClassTwo");
Y.Assert.isFalse(o2 instanceof MyClassOne, "o2 should NOT be an instanceof MyClassOne");
Y.Assert.isFunction(o1.methodOne, "o1 should have a methodOne method");
Y.Assert.isFunction(o1.extOne, "o1 should have an extOne method");
Y.Assert.isUndefined(o1.extTwo, "o1 should not have an extTwo method");
Y.Assert.isFunction(o2.methodOne, "o2 should have a methodOne method");
Y.Assert.isFunction(o2.extOne, "o2 should have an extOne method");
Y.Assert.isFunction(o2.extTwo, "o2 should have an extTwo method");
Y.Assert.isTrue(MyClassOne.superclass.constructor === Y.Base, "MyClassOne should have superclass set to Base");
Y.Assert.isTrue(MyClassTwo.superclass.constructor === Y.Base, "MyClassTwo should have superclass set to Base");
// Make sure Y.Base was untouched.
var b = new Y.Base();
Y.Assert.isUndefined(b.methodOne, "Base should not have extension methods");
Y.Assert.isUndefined(b.extOne, "Base should not have extension methods");
Y.Assert.isUndefined(b.extTwo, "Base should not have extension methods");
Y.Assert.isFalse(MyClassOne === Y.Base);
Y.Assert.isFalse(MyClassTwo === Y.Base);
},
"test:extend" : function() {
var actualMethodCalls = [],
expectedMethodCalls = [
"ext1::constructor",
"myClassOne::initializer",
"ext1::initializer",
"ext2::constructor",
"myClassTwo::initializer",
"ext2::initializer",
"myClassOne::methodOne",
"myClassTwo::methodTwo",
"ext1::extOne",
"ext2::extTwo"
];
function Ext1() {
actualMethodCalls.push("ext1::constructor");
}
Ext1.prototype.extOne = function() {
actualMethodCalls.push("ext1::extOne");
};
Ext1.prototype.initializer = function() {
actualMethodCalls.push("ext1::initializer");
};
function Ext2() {
actualMethodCalls.push("ext2::constructor");
}
Ext2.prototype.extTwo = function() {
actualMethodCalls.push("ext2::extTwo");
};
Ext2.prototype.initializer = function() {
actualMethodCalls.push("ext2::initializer");
};
var MyClassOne = Y.Base.create("myClassOne", Y.Base, [Ext1], {
initializer: function() {
actualMethodCalls.push("myClassOne::initializer");
},
methodOne: function() {
actualMethodCalls.push("myClassOne::methodOne");
}
});
var MyClassTwo = Y.Base.create("myClassTwo", MyClassOne, [Ext2], {
initializer: function() {
actualMethodCalls.push("myClassTwo::initializer");
},
methodTwo: function() {
actualMethodCalls.push("myClassTwo::methodTwo");
}
});
var o = new MyClassTwo();
o.methodOne();
o.methodTwo();
o.extOne();
o.extTwo();
Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
}
}));
Y.Test.Runner.setName("Base Tests");
Y.Test.Runner.add(suite);
var console;
Y.one("#btnRun").set("disabled", false).on("click", function() {
if (!console) {
console = new Y.Console({
id:"console",
width:"100%",
height:"90%",
verbose : false,
printTimeout: 0,
newestOnTop : false,
entryTemplate: '<pre class="{entry_class} {cat_class} {src_class}">'+
'<span class="{entry_cat_class}">{label}</span>'+
'<span class="{entry_content_class}">{message}</span>'+
'</pre>'
}).render();
}
});
});
</script>
<p><input type="button" value="Run Tests" id="btnRun" disabled=true></p>
</body>
</html>