<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>JS.Class tests</title>
<script src="prototype.js" type="text/javascript" charset="utf-8"></script>
<script src="unittest.js" type="text/javascript" charset="utf-8"></script>
<script src="class.js" type="text/javascript" charset="utf-8"></script>
<link rel="stylesheet" href="test.css" type="text/css" media="screen" title="no title" charset="utf-8">
<script type="text/javascript" charset="utf-8">
var Animal = JS.Class({
extend: {
find: function(thing) { return 'Animal finds ' + thing; },
create: function(thing) { return this.find(thing) + ' and Animal creates ' + thing; }
},
initialize: function(name) {
this.name = String(name);
},
speak: function(stuff) {
return 'My name is ' + this.name + ' and I like ' + stuff;
}
});
var Bear = JS.Class(Animal, {
extend: {
create: function(thing) {
return this._super(thing) + ', but Bear creates other stuff'
}
},
speak: function(stuff) {
return this._super(stuff).toUpperCase();
}
});
var NoSuperBear = JS.Class(Bear, {
speak: function() { return this.name.toUpperCase(); }
});
var Koala = JS.Class(Bear, {
speak: function(stuff) {
return "I'm not really a Bear, but I do like " + stuff;
}
});
var Dog = JS.Class(Animal, {
bindMethods: true,
bark: function() { return this.name + ' says WOOF!'; }
});
var Pitbull = JS.Class(Dog, {
speak: function() {
return this._super();
}
});
// Let's implement the classes from here: http://www.ajaxpath.com/javascript-inheritance
// and make sure Crockford's problems aren't encountered.
var BaseClass = JS.Class({
getName: function() { return 'BaseClass(' + this.getId() + ')'; },
getId: function() { return 1; }
});
var SubClass = JS.Class(BaseClass, {
getName: function() {
return 'SubClass(' + this.getId() + ') extends ' + this._super();
},
getId: function() { return 2; }
});
var TopClass = JS.Class(SubClass, {
getName: function() {
return 'TopClass(' + this.getId() + ') extends ' + this._super();
},
getId: function() {
return this._super();
}
});
var NativeClass = function() {};
NativeClass.prototype = {
getName: function() { return 'Native'; }
};
var ChildOfNativeClass = JS.Class(NativeClass, {
getName: function() {
return this._super();
}
});
var Paginator = JS.Class({
initialize: function(n) {
this.count = n;
this.createItems(n);
},
createItems: function(n) {
this.items = this.items || [];
for (var i = 0; i < n; i++)
this.items.push(new this.klass.Item(i));
}
});
Paginator.Item = JS.Class({
initialize: function(n) {
this.name = 'Item';
this.number = n;
},
getName: function() {
return this.name + ' ' + this.getNumber();
},
getNumber: function() {
return this.number;
}
});
var Gallery = JS.Class(Paginator, {
createItems: function(n) { this._super(4 * n); }
});
var ItemInheritor = JS.Class(Gallery);
ItemInheritor.Item = JS.Class(Gallery.Item, {
getNumber: function() { return this._super() + 7; }
});
</script>
</head>
<body>
<div id="testlog"></div>
<script type="text/javascript" charset="utf-8">
new Test.Unit.Runner({
testSuperSpeed: function() { with(this) {
var yogi = new Bear('Yogi');
benchmark(function() {
yogi.speak();
}, 3000);
var bobo = new NoSuperBear('Bobo');
benchmark(function() {
bobo.speak();
}, 3000);
}},
testClassDefinition: function() { with(this) {
var frog = new Animal('Kermit');
assertEqual('My name is Kermit and I like Ms. Piggy', frog.speak('Ms. Piggy'));
assertEqual('Animal finds food', Animal.find('food'));
assertEqual('Animal finds shelter and Animal creates shelter', Animal.create('shelter'));
}},
testInheritance: function() { with(this) {
var yogi = new Bear('Yogi');
assertEqual('MY NAME IS YOGI AND I LIKE PICNICS', yogi.speak('picnics'));
assertEqual('Animal finds honey', Bear.find('honey'));
assertEqual('Animal finds nothing and Animal creates nothing, but Bear creates other stuff', Bear.create('nothing'));
}},
testSuperWithNoArguments: function() { with(this) {
var brutus = new Pitbull('Brutus');
assertEqual('My name is Brutus and I like biting', brutus.speak('biting'));
}},
// Avoid Crockford's problem: http://www.ajaxpath.com/javascript-inheritance
testReassignedSuper: function() { with(this) {
var top = new TopClass();
assertEqual('TopClass(2) extends SubClass(2) extends BaseClass(2)', top.getName());
}},
testInheritanceFromNativeClass: function() { with(this) {
var nat = new NativeClass();
assertEqual('Native', nat.getName());
var child = new ChildOfNativeClass();
assertEqual('Native', child.getName());
NativeClass.prototype.shout = function() { return 'Shouting!!'; };
assertEqual('Shouting!!', child.shout());
assert(child.is_a(ChildOfNativeClass));
assert(child.is_a(NativeClass));
assert(child.is_a(Object));
assert(!child.is_a(Dog));
}},
testBinding: function() { with(this) {
var rex = new Dog('Rex');
var bark = rex.bark;
assertEqual('Rex says WOOF!', bark());
var brutus = new Pitbull('Brutus');
assertEqual('Brutus says WOOF!', brutus.bark());
bark = brutus.bark;
assertEqual(' says WOOF!', bark());
}},
testHierarchy: function() { with(this) {
var rex = new Dog('Rex');
assert(rex.is_a(Dog));
assert(rex.is_a(Animal));
assert(rex.is_a(Object));
assert(!rex.is_a(Bear));
var yogi = new rex.klass.superclass.subclasses[0]('Yogi');
assertEqual('Yogi', yogi.name);
assert(yogi.is_a(Bear));
assert(!yogi.is_a(Dog));
}},
testSuperclassNotDefined: function() { with(this) {
assertRaise('ReferenceError', function() {
var DumbClass = JS.Class(JS.Class.NotDefined, {});
});
}},
testSubclassUpdating: function() { with(this) {
var kevin = new Koala('Kevin');
Animal.method('shout', function(thing) {
return this.name + ' is loving ' + thing + '!!!';
});
assertEqual('Kevin is loving trees!!!', kevin.shout('trees'));
Animal.classMethod('count', function() { return 6; });
assertEqual(4*6, Koala.count() + Bear.count() + Dog.count() + Pitbull.count());
}},
testClassMethodInheritanceSkipsGenerations: function() { with(this) {
Dog.eatFood = function(food) { return 'Dogs eat ' + food; };
assertEqual('Dogs eat biscuits', Dog.eatFood('biscuits'));
Animal.classMethod('eatFood', function(food) { return 'Animals eat ' + food; });
assertEqual('Animals eat people', Pitbull.eatFood('people'));
assertEqual('Dogs eat biscuits', Dog.eatFood('biscuits'));
Pitbull.classMethod('eatFood', function() { return this._super(); });
assertEqual('Dogs eat people', Pitbull.eatFood('people'));
}},
testModularInheritance: function() { with(this) {
var paginator = new Paginator(12);
assert(paginator.is_a(Paginator));
assert(paginator.items[6].is_a(Paginator.Item));
assert(paginator.items[6].is_a(paginator.items[3].klass));
assertEqual('Item 7', paginator.items[7].getName());
var gallery = new Gallery(3);
assertEqual(12, gallery.items.length);
assert(gallery.is_a(Gallery));
assert(gallery.is_a(Paginator));
assert(gallery.items[5].is_a(Gallery.Item));
assert(gallery.items[5].is_a(Paginator.Item));
assert(Paginator.Item === Gallery.Item);
assert(ItemInheritor.Item !== Gallery.Item);
assert(ItemInheritor.Item.superclass === Gallery.Item);
var itor = new ItemInheritor(2);
assertEqual('Item 13', itor.items[6].getName());
}}
});
</script>
</body>
</html>