UNPKG

can

Version:

MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.

521 lines (485 loc) 12.3 kB
// FIXME: this test assumes the existence of the global object "tests" tests= typeof tests=="undefined" ? {} : tests; define([ "doh/main", "dojo/aspect", "dojo/_base/declare", "dojo/_base/kernel", "dojo/_base/lang" ], function(doh, aspect, declare, kernel, lang){ doh.register("tests._base.declare", [ function smokeTest(t){ declare("tests._base.declare.tmp", null); var tmp = new tests._base.declare.tmp(); declare("testsFoo", null); tmp = new testsFoo(); }, function smokeTest2(t){ declare("tests._base.declare.foo", null, { foo: "thonk" }); var tmp = new tests._base.declare.foo(); t.is("thonk", tmp.foo); declare("testsFoo2", null, { foo: "thonk" }); var tmp2 = new testsFoo2(); t.is("thonk", tmp2.foo); }, function smokeTestWithCtor(t){ declare("tests._base.declare.fooBar", null, { constructor: function(){ this.foo = "blah"; }, foo: "thonk" }); var tmp = new tests._base.declare.fooBar(); t.is("blah", tmp.foo); }, function smokeTestCompactArgs(t){ declare("tests._base.declare.fooBar2", null, { foo: "thonk" }); var tmp = new tests._base.declare.fooBar2(); t.is("thonk", tmp.foo); }, function subclass(t){ declare("tests._base.declare.tmp3", null, { foo: "thonk" }); declare("tests._base.declare.tmp4", tests._base.declare.tmp3); var tmp = new tests._base.declare.tmp4(); t.is("thonk", tmp.foo); }, function subclassWithCtor(t){ declare("tests._base.declare.tmp5", null, { constructor: function(){ this.foo = "blah"; }, foo: "thonk" }); declare("tests._base.declare.tmp6", tests._base.declare.tmp5); var tmp = new tests._base.declare.tmp6(); t.is("blah", tmp.foo); }, function mixinSubclass(t){ declare("tests._base.declare.tmp7", null, { foo: "thonk" }); declare("tests._base.declare.tmp8", null, { constructor: function(){ this.foo = "blah"; } }); var tmp = new tests._base.declare.tmp8(); t.is("blah", tmp.foo); declare("tests._base.declare.tmp9", [ tests._base.declare.tmp7, // prototypal tests._base.declare.tmp8 // mixin ]); var tmp2 = new tests._base.declare.tmp9(); t.is("blah", tmp2.foo); }, function superclassRef(t){ declare("tests._base.declare.tmp10", null, { foo: "thonk" }); declare("tests._base.declare.tmp11", tests._base.declare.tmp10, { constructor: function(){ this.foo = "blah"; } }); var tmp = new tests._base.declare.tmp11(); t.is("blah", tmp.foo); t.is("thonk", tests._base.declare.tmp11.superclass.foo); }, function inheritedCall(t){ var foo = "xyzzy"; declare("tests._base.declare.tmp12", null, { foo: "thonk", bar: function(arg1, arg2){ if(arg1){ this.foo = arg1; } if(arg2){ foo = arg2; } } }); declare("tests._base.declare.tmp13", tests._base.declare.tmp12, { constructor: function(){ this.foo = "blah"; } }); var tmp = new tests._base.declare.tmp13(); t.is("blah", tmp.foo); t.is("xyzzy", foo); tmp.bar("zot"); t.is("zot", tmp.foo); t.is("xyzzy", foo); tmp.bar("trousers", "squiggle"); t.is("trousers", tmp.foo); t.is("squiggle", foo); }, function inheritedExplicitCall(t){ var foo = "xyzzy"; declare("tests._base.declare.tmp14", null, { foo: "thonk", bar: function(arg1, arg2){ if(arg1){ this.foo = arg1; } if(arg2){ foo = arg2; } } }); declare("tests._base.declare.tmp15", tests._base.declare.tmp14, { constructor: function(){ this.foo = "blah"; }, bar: function(arg1, arg2){ this.inherited("bar", arguments, [arg2, arg1]); }, baz: function(arg1, arg2){ tests._base.declare.tmp15.superclass.bar.apply(this, arguments); } }); var tmp = new tests._base.declare.tmp15(); t.is("blah", tmp.foo); t.is("xyzzy", foo); tmp.baz("zot"); t.is("zot", tmp.foo); t.is("xyzzy", foo); tmp.bar("trousers", "squiggle"); t.is("squiggle", tmp.foo); t.is("trousers", foo); }, function inheritedMixinCalls(t){ declare("tests._base.declare.tmp16", null, { foo: "", bar: function(){ this.foo += "tmp16"; } }); declare("tests._base.declare.mixin16", null, { bar: function(){ this.inherited(arguments); this.foo += ".mixin16"; } }); declare("tests._base.declare.mixin17", tests._base.declare.mixin16, { bar: function(){ this.inherited(arguments); this.foo += ".mixin17"; } }); declare("tests._base.declare.tmp17", [tests._base.declare.tmp16, tests._base.declare.mixin17], { bar: function(){ this.inherited(arguments); this.foo += ".tmp17"; } }); var tmp = new tests._base.declare.tmp17(); tmp.bar(); t.is("tmp16.mixin16.mixin17.tmp17", tmp.foo); }, function mixinPreamble(t){ var passed = false; declare("tests._base.declare.tmp16", null); new tests._base.declare.tmp16({ preamble: function(){ passed = true; } }); t.t(passed); }, function basicMixin(t){ // testing if a plain Class-like object can be inherited // by declare var d = new doh.Deferred; var Thing = function(args){ lang.mixin(this, args); }; Thing.prototype.method = function(){ t.t(true); d.callback(true); }; declare("Thinger", Thing, { method: function(){ this.inherited(arguments); } }); var it = new Thinger(); it.method(); return d; }, function mutatedMethods(t){ // testing if methods can be mutated (within a reason) declare("tests._base.declare.tmp18", null, { constructor: function(){ this.clear(); }, clear: function(){ this.flag = 0; }, foo: function(){ ++this.flag; }, bar: function(){ ++this.flag; }, baz: function(){ ++this.flag; } }); declare("tests._base.declare.tmp19", tests._base.declare.tmp18, { foo: function(){ ++this.flag; this.inherited(arguments); }, bar: function(){ ++this.flag; this.inherited(arguments); }, baz: function(){ ++this.flag; this.inherited(arguments); } }); var x = new tests._base.declare.tmp19(); // smoke tests t.is(0, x.flag); x.foo(); t.is(2, x.flag); x.clear(); t.is(0, x.flag); var a = 0; // aspect.after() on a prototype method aspect.after(tests._base.declare.tmp19.prototype, "foo", function(){ a = 1; }); x.foo(); t.is(2, x.flag); t.is(1, a); x.clear(); a = 0; // extra chaining var old = tests._base.declare.tmp19.prototype.bar; tests._base.declare.tmp19.prototype.bar = function(){ a = 1; ++this.flag; old.call(this); }; x.bar(); t.is(3, x.flag); t.is(1, a); x.clear(); a = 0; // replacement tests._base.declare.tmp19.prototype.baz = function(){ a = 1; ++this.flag; this.inherited("baz", arguments); }; x.baz(); t.is(2, x.flag); t.is(1, a); }, function modifiedInstance(t){ var stack; declare("tests._base.declare.tmp20", null, { foo: function(){ stack.push(20); } }); declare("tests._base.declare.tmp21", null, { foo: function(){ this.inherited(arguments); stack.push(21); } }); declare("tests._base.declare.tmp22", tests._base.declare.tmp20, { foo: function(){ this.inherited(arguments); stack.push(22); } }); declare("tests._base.declare.tmp23", [tests._base.declare.tmp20, tests._base.declare.tmp21], { foo: function(){ this.inherited(arguments); stack.push(22); } }); var a = new tests._base.declare.tmp22(); var b = new tests._base.declare.tmp23(); var c = { foo: function(){ this.inherited("foo", arguments); stack.push("INSIDE C"); } }; stack = []; a.foo(); t.is([20, 22], stack); stack = []; b.foo(); t.is([20, 21, 22], stack); lang.mixin(a, c); lang.mixin(b, c); stack = []; a.foo(); t.is([20, 22, "INSIDE C"], stack); stack = []; b.foo(); t.is([20, 21, 22, "INSIDE C"], stack); }, function duplicatedBase(t){ var stack; var A = declare(null, { constructor: function(){ stack.push(1); } }); var B = declare([A, A, A], { constructor: function(){ stack.push(2); } }); stack = []; new A; t.is([1], stack); stack = []; new B; t.is([1, 2], stack); }, function indirectlyDuplicatedBase(t){ var stack; var A = declare(null, { constructor: function(){ stack.push(1); } }); var B = declare(A, { constructor: function(){ stack.push(2); } }); var C = declare([A, B], { constructor: function(){ stack.push(3); } }); var D = declare([B, A], { constructor: function(){ stack.push(4); } }); stack = []; new C; t.is([1, 2, 3], stack); stack = []; new D; t.is([1, 2, 4], stack); }, function wrongMultipleInheritance(t){ var stack; var A = declare([], { constructor: function(){ stack.push(1); } }); var B = declare([A], { constructor: function(){ stack.push(2); } }); stack = []; new A; t.is([1], stack); stack = []; new B; t.is([1, 2], stack); }, function impossibleBases(t){ var A = declare(null); var B = declare(null); var C = declare([A, B]); var D = declare([B, A]); var flag = false; try{ var E = declare([C, D]); }catch(e){ flag = true; } t.t(flag); }, function noNew(t){ // all of the classes I create will use this as their // pseudo-constructor function function noNewConstructor(){ this.noNew_Value = 'instance value'; } var g = kernel.global; // this value will remain unchanged if the code for // calling a constructor without 'new' works correctly. g.noNew_Value = 'global value'; // perform the actual test function noNewTest(cls){ // call class function without new var obj = cls('instance value'); t.is(obj.noNew_Value, 'instance value'); t.is(g.noNew_Value, 'global value'); } // There are three different functions that might be // created by declare(), so I need to test all // three. // 1. Class with manual-chained constructor noNewTest( declare(null, { constructor: noNewConstructor, '-chains-': {constructor: 'manual'} }) ); // 2. Class with no superclasses var A = declare(null, { constructor: noNewConstructor }); noNewTest(A); // 3. Class with at least one superclass noNewTest(declare(A)); // Make sure multiple inheritance call works var B = declare(A); var C = declare(null, { ctest: function(){return true;} }); var D = declare([A, B, C], { dtest: function(){return true;} }); noNewTest(D); // make sure I get the test functions from // all superclasses var d = D(); t.t(d.ctest()); t.t(d.dtest()); // Make sure call through an object works var noNewClasses = { D: D, noNew_Value: 'unchanged' }; var obj = noNewClasses.D(); t.is(obj.noNew_Value, 'instance value'); t.is(noNewClasses.noNew_Value, 'unchanged'); }, function createSubclass(t){ var A = dojo.declare(null, { foo: "thonk" }); var B = dojo.declare(null, { }); var C = dojo.declare(null, { bar: "thonk" }); // Both 'mixins' and 'props' parameters are provided var D1 = A.createSubclass([B, C], { constructor: function(){ this.foo = "blah"; } }); // Only 'mixins' parameters is provided var D2 = A.createSubclass([B, C]); // The 'props' parameter is provided as first instead of second parameter var D3 = A.createSubclass({ constructor: function(){ this.foo = "blah"; } }); // No arguments at all provided var D4 = A.createSubclass(); // Single Mixin var D5 = A.createSubclass(C); var d1 = new D1(); var d2 = new D2(); var d3 = new D3(); var d4 = new D4(); var d5 = new D5(); t.is("blah", d1.foo); t.is("thonk", d2.foo); t.is("thonk", d1.bar); t.is("thonk", d2.bar); t.is("blah", d3.foo); t.is("thonk", d4.foo); t.is("thonk", d5.bar); } // FIXME: there are still some permutations to test like: // - ctor arguments // - multi-level inheritance + L/R conflict checks ]); });