cls
Version:
Class factory featuring inheritance of static properties, static constructors, lazy population of prototypes, and this._super.
222 lines (176 loc) • 4.89 kB
JavaScript
var assert = require("assert");
var Class = require("../main");
describe("Class", function() {
it("should have correct instanceof and override behavior", function() {
var A = Class.extend({
init: function(val) {
this.val = val;
}
});
var B = A.extend({
init: function(val) {
this._super(val + 1);
this.overrideMe();
},
overrideMe: function() {
// pass
}
});
var C = B.extend({
overrideMe: function() {
this._super.apply(this, arguments);
this.val += 1;
},
toString: function() {
return "C(" + this.val + ")";
}
});
var a = new A(3);
var b = new B(3);
var c = new C(3);
assert.strictEqual(a.val, 3);
assert.strictEqual(b.val, 4);
assert.strictEqual(c.val, 5);
assert.ok(a instanceof A);
assert.ok(!(a instanceof B));
assert.ok(!(a instanceof C));
assert.ok(b instanceof A);
assert.ok(b instanceof B);
assert.ok(!(b instanceof C));
assert.ok(c instanceof A);
assert.ok(c instanceof B);
assert.ok(c instanceof C);
c.overrideMe();
assert.strictEqual(c.val, 6);
var Bp = B.prototype;
var saved = Bp.overrideMe;
Bp.overrideMe = function(x) { this.val += x };
c.overrideMe(2);
assert.strictEqual(c.val, 9);
Bp.overrideMe = saved;
c.overrideMe(2);
assert.strictEqual(c.val, 10);
assert.equal(c, "C(10)"); // note non-strict equality
});
});
describe("statics", function() {
it("should support static inheritance and constructors", function() {
var A = Class.extend({
name: "A",
init: function(val) {
this.val = val;
},
assertClass: function() {
assert.notEqual(this, A);
assert.strictEqual(this.cls, A);
},
statics: {
init: function(cls) {
cls.instance = cls.create(10);
},
create: function(val) {
return new this(val + 1);
},
asdf: "asdf"
}
});
var B = A.extend({
name: "B",
assertClass: function() {
assert.notEqual(this, B);
assert.strictEqual(this.cls, B);
},
conflict: function() {
return "instance won";
},
toString: function() {
return this.cls.toString();
},
statics: {
toString: function() {
return this.prototype.name;
},
conflict: function() {
return "class won";
}
}
});
var C = B.extend({
name: "C",
assertClass: function() {
assert.notEqual(this, C);
assert.strictEqual(this.cls, C);
},
statics: {
init: function(cls) {
this._super(cls);
cls.instance.val = 0;
},
create: function(val) {
return this._super(val * 2);
},
toString: function() {
return "<class " + this._super() + ">";
},
asdf: "ASDF"
}
});
var a = A.create(2),
b = B.create(3),
c = C.create(4),
c2 = new C(5);
assert.ok(a instanceof A);
assert.ok(!(a instanceof B));
assert.ok(b instanceof A);
assert.ok(b instanceof B);
assert.strictEqual(a.val, 3);
assert.strictEqual(b.val, 4);
assert.strictEqual(B + "", b.name);
assert.strictEqual(B + "", b + "");
assert.strictEqual(B.toString(), b.toString());
assert.strictEqual(c.val, 9);
assert.strictEqual(c2.val, 5);
assert.equal(c, "<class C>");
assert.equal(C, "<class C>");
assert.strictEqual(b.conflict(), "instance won");
assert.strictEqual(B.conflict(), "class won");
assert.strictEqual(c.conflict(), "instance won");
assert.strictEqual(C.conflict(), "class won");
a.assertClass();
b.assertClass();
c.assertClass();
c2.assertClass();
assert.strictEqual(A.asdf, "asdf");
assert.strictEqual(B.asdf, "asdf");
assert.strictEqual(C.asdf, "ASDF");
assert.strictEqual(A.instance.cls, A);
assert.strictEqual(B.instance.cls, B);
assert.strictEqual(C.instance.cls, C);
assert.strictEqual(A.instance.val, 11);
assert.strictEqual(B.instance.val, 11);
assert.strictEqual(C.instance.val, 0);
});
});
describe("base property", function() {
it("should equal the base class's prototype", function() {
var A = Class.extend({
foo: function() {
return "name: " + this.name;
}
});
var B = A.extend({
name: "B",
bar: function() {
assert.strictEqual(B.base.bar, this._super);
return B.base.foo.call(this);
}
});
var C = B.extend({
name: "C"
});
assert.strictEqual(B.base, A.prototype);
assert.strictEqual(C.base, B.prototype);
assert.strictEqual(new B().bar(), "name: B");
assert.strictEqual(new C().bar(), "name: C");
});
});