diff options
Diffstat (limited to 'includes/js/util/doh/runner.js')
-rw-r--r-- | includes/js/util/doh/runner.js | 948 |
1 files changed, 948 insertions, 0 deletions
diff --git a/includes/js/util/doh/runner.js b/includes/js/util/doh/runner.js new file mode 100644 index 0000000..f5e47e1 --- /dev/null +++ b/includes/js/util/doh/runner.js @@ -0,0 +1,948 @@ +// FIXME: need to add async tests +// FIXME: need to handle URL wrapping and test registration/running from URLs + +// package system gunk. +try{ + dojo.provide("doh.runner"); +}catch(e){ + if(!this["doh"]){ + doh = {}; + } +} + +// +// Utility Functions and Classes +// + +doh.selfTest = false; + +doh.hitch = function(/*Object*/thisObject, /*Function|String*/method /*, ...*/){ + var args = []; + for(var x=2; x<arguments.length; x++){ + args.push(arguments[x]); + } + var fcn = ((typeof method == "string") ? thisObject[method] : method) || function(){}; + return function(){ + var ta = args.concat([]); // make a copy + for(var x=0; x<arguments.length; x++){ + ta.push(arguments[x]); + } + return fcn.apply(thisObject, ta); // Function + }; +} + +doh._mixin = function(/*Object*/ obj, /*Object*/ props){ + // summary: + // Adds all properties and methods of props to obj. This addition is + // "prototype extension safe", so that instances of objects will not + // pass along prototype defaults. + var tobj = {}; + for(var x in props){ + // the "tobj" condition avoid copying properties in "props" + // inherited from Object.prototype. For example, if obj has a custom + // toString() method, don't overwrite it with the toString() method + // that props inherited from Object.protoype + if((typeof tobj[x] == "undefined") || (tobj[x] != props[x])){ + obj[x] = props[x]; + } + } + // IE doesn't recognize custom toStrings in for..in + if( this["document"] + && document.all + && (typeof props["toString"] == "function") + && (props["toString"] != obj["toString"]) + && (props["toString"] != tobj["toString"]) + ){ + obj.toString = props.toString; + } + return obj; // Object +} + +doh.mixin = function(/*Object*/obj, /*Object...*/props){ + // summary: Adds all properties and methods of props to obj. + for(var i=1, l=arguments.length; i<l; i++){ + doh._mixin(obj, arguments[i]); + } + return obj; // Object +} + +doh.extend = function(/*Object*/ constructor, /*Object...*/ props){ + // summary: + // Adds all properties and methods of props to constructor's + // prototype, making them available to all instances created with + // constructor. + for(var i=1, l=arguments.length; i<l; i++){ + doh._mixin(constructor.prototype, arguments[i]); + } + return constructor; // Object +} + + +doh._line = "------------------------------------------------------------"; + +/* +doh._delegate = function(obj, props){ + // boodman-crockford delegation + function TMP(){}; + TMP.prototype = obj; + var tmp = new TMP(); + if(props){ + dojo.lang.mixin(tmp, props); + } + return tmp; +} +*/ + +doh.debug = function(){ + // summary: + // takes any number of arguments and sends them to whatever debugging + // or logging facility is available in this environment + + // YOUR TEST RUNNER NEEDS TO IMPLEMENT THIS +} + +doh._AssertFailure = function(msg){ + // idea for this as way of dis-ambiguating error types is from JUM. + // The JUM is dead! Long live the JUM! + + if(!(this instanceof doh._AssertFailure)){ + return new doh._AssertFailure(msg); + } + this.message = new String(msg||""); + return this; +} +doh._AssertFailure.prototype = new Error(); +doh._AssertFailure.prototype.constructor = doh._AssertFailure; +doh._AssertFailure.prototype.name = "doh._AssertFailure"; + +doh.Deferred = function(canceller){ + this.chain = []; + this.id = this._nextId(); + this.fired = -1; + this.paused = 0; + this.results = [null, null]; + this.canceller = canceller; + this.silentlyCancelled = false; +}; + +doh.extend(doh.Deferred, { + getTestCallback: function(cb, scope){ + var _this = this; + return function(){ + try{ + cb.apply(scope||dojo.global||_this, arguments); + }catch(e){ + _this.errback(e); + return; + } + _this.callback(true); + } + }, + + getFunctionFromArgs: function(){ + var a = arguments; + if((a[0])&&(!a[1])){ + if(typeof a[0] == "function"){ + return a[0]; + }else if(typeof a[0] == "string"){ + return dojo.global[a[0]]; + } + }else if((a[0])&&(a[1])){ + return doh.hitch(a[0], a[1]); + } + return null; + }, + + makeCalled: function() { + var deferred = new doh.Deferred(); + deferred.callback(); + return deferred; + }, + + _nextId: (function(){ + var n = 1; + return function(){ return n++; }; + })(), + + cancel: function(){ + if(this.fired == -1){ + if (this.canceller){ + this.canceller(this); + }else{ + this.silentlyCancelled = true; + } + if(this.fired == -1){ + this.errback(new Error("Deferred(unfired)")); + } + }else if( (this.fired == 0)&& + (this.results[0] instanceof doh.Deferred)){ + this.results[0].cancel(); + } + }, + + + _pause: function(){ + this.paused++; + }, + + _unpause: function(){ + this.paused--; + if ((this.paused == 0) && (this.fired >= 0)) { + this._fire(); + } + }, + + _continue: function(res){ + this._resback(res); + this._unpause(); + }, + + _resback: function(res){ + this.fired = ((res instanceof Error) ? 1 : 0); + this.results[this.fired] = res; + this._fire(); + }, + + _check: function(){ + if(this.fired != -1){ + if(!this.silentlyCancelled){ + throw new Error("already called!"); + } + this.silentlyCancelled = false; + return; + } + }, + + callback: function(res){ + this._check(); + this._resback(res); + }, + + errback: function(res){ + this._check(); + if(!(res instanceof Error)){ + res = new Error(res); + } + this._resback(res); + }, + + addBoth: function(cb, cbfn){ + var enclosed = this.getFunctionFromArgs(cb, cbfn); + if(arguments.length > 2){ + enclosed = doh.hitch(null, enclosed, arguments, 2); + } + return this.addCallbacks(enclosed, enclosed); + }, + + addCallback: function(cb, cbfn){ + var enclosed = this.getFunctionFromArgs(cb, cbfn); + if(arguments.length > 2){ + enclosed = doh.hitch(null, enclosed, arguments, 2); + } + return this.addCallbacks(enclosed, null); + }, + + addErrback: function(cb, cbfn){ + var enclosed = this.getFunctionFromArgs(cb, cbfn); + if(arguments.length > 2){ + enclosed = doh.hitch(null, enclosed, arguments, 2); + } + return this.addCallbacks(null, enclosed); + }, + + addCallbacks: function(cb, eb){ + this.chain.push([cb, eb]) + if(this.fired >= 0){ + this._fire(); + } + return this; + }, + + _fire: function(){ + var chain = this.chain; + var fired = this.fired; + var res = this.results[fired]; + var self = this; + var cb = null; + while (chain.length > 0 && this.paused == 0){ + // Array + var pair = chain.shift(); + var f = pair[fired]; + if(f == null){ + continue; + } + try { + res = f(res); + fired = ((res instanceof Error) ? 1 : 0); + if(res instanceof doh.Deferred){ + cb = function(res){ + self._continue(res); + } + this._pause(); + } + }catch(err){ + fired = 1; + res = err; + } + } + this.fired = fired; + this.results[fired] = res; + if((cb)&&(this.paused)){ + res.addBoth(cb); + } + } +}); + +// +// State Keeping and Reporting +// + +doh._testCount = 0; +doh._groupCount = 0; +doh._errorCount = 0; +doh._failureCount = 0; +doh._currentGroup = null; +doh._currentTest = null; +doh._paused = true; + +doh._init = function(){ + this._currentGroup = null; + this._currentTest = null; + this._errorCount = 0; + this._failureCount = 0; + this.debug(this._testCount, "tests to run in", this._groupCount, "groups"); +} + +// doh._urls = []; +doh._groups = {}; + +// +// Test Registration +// + +doh.registerTestNs = function(/*String*/ group, /*Object*/ ns){ + // summary: + // adds the passed namespace object to the list of objects to be + // searched for test groups. Only "public" functions (not prefixed + // with "_") will be added as tests to be run. If you'd like to use + // fixtures (setUp(), tearDown(), and runTest()), please use + // registerTest() or registerTests(). + for(var x in ns){ + if( (x.charAt(0) != "_") && + (typeof ns[x] == "function") ){ + this.registerTest(group, ns[x]); + } + } +} + +doh._testRegistered = function(group, fixture){ + // slot to be filled in +} + +doh._groupStarted = function(group){ + // slot to be filled in +} + +doh._groupFinished = function(group, success){ + // slot to be filled in +} + +doh._testStarted = function(group, fixture){ + // slot to be filled in +} + +doh._testFinished = function(group, fixture, success){ + // slot to be filled in +} + +doh.registerGroup = function( /*String*/ group, + /*Array||Function||Object*/ tests, + /*Function*/ setUp, + /*Function*/ tearDown){ + // summary: + // registers an entire group of tests at once and provides a setUp and + // tearDown facility for groups. If you call this method with only + // setUp and tearDown parameters, they will replace previously + // installed setUp or tearDown functions for the group with the new + // methods. + // group: + // string name of the group + // tests: + // either a function or an object or an array of functions/objects. If + // an object, it must contain at *least* a "runTest" method, and may + // also contain "setUp" and "tearDown" methods. These will be invoked + // on either side of the "runTest" method (respectively) when the test + // is run. If an array, it must contain objects matching the above + // description or test functions. + // setUp: a function for initializing the test group + // tearDown: a function for initializing the test group + if(tests){ + this.register(group, tests); + } + if(setUp){ + this._groups[group].setUp = setUp; + } + if(tearDown){ + this._groups[group].tearDown = tearDown; + } +} + +doh._getTestObj = function(group, test){ + var tObj = test; + if(typeof test == "string"){ + if(test.substr(0, 4)=="url:"){ + return this.registerUrl(group, test); + }else{ + tObj = { + name: test.replace("/\s/g", "_") + }; + tObj.runTest = new Function("t", test); + } + }else if(typeof test == "function"){ + // if we didn't get a fixture, wrap the function + tObj = { "runTest": test }; + if(test["name"]){ + tObj.name = test.name; + }else{ + try{ + var fStr = "function "; + var ts = tObj.runTest+""; + if(0 <= ts.indexOf(fStr)){ + tObj.name = ts.split(fStr)[1].split("(", 1)[0]; + } + // doh.debug(tObj.runTest.toSource()); + }catch(e){ + } + } + // FIXME: try harder to get the test name here + } + return tObj; +} + +doh.registerTest = function(/*String*/ group, /*Function||Object*/ test){ + // summary: + // add the provided test function or fixture object to the specified + // test group. + // group: + // string name of the group to add the test to + // test: + // either a function or an object. If an object, it must contain at + // *least* a "runTest" method, and may also contain "setUp" and + // "tearDown" methods. These will be invoked on either side of the + // "runTest" method (respectively) when the test is run. + if(!this._groups[group]){ + this._groupCount++; + this._groups[group] = []; + this._groups[group].inFlight = 0; + } + var tObj = this._getTestObj(group, test); + if(!tObj){ return; } + this._groups[group].push(tObj); + this._testCount++; + this._testRegistered(group, tObj); + return tObj; +} + +doh.registerTests = function(/*String*/ group, /*Array*/ testArr){ + // summary: + // registers a group of tests, treating each element of testArr as + // though it were being (along with group) passed to the registerTest + // method. + for(var x=0; x<testArr.length; x++){ + this.registerTest(group, testArr[x]); + } +} + +// FIXME: move implementation to _browserRunner? +doh.registerUrl = function( /*String*/ group, + /*String*/ url, + /*Integer*/ timeout){ + this.debug("ERROR:"); + this.debug("\tNO registerUrl() METHOD AVAILABLE."); + // this._urls.push(url); +} + +doh.registerString = function(group, str){ +} + +// FIXME: remove the doh.add alias SRTL. +doh.register = doh.add = function(groupOrNs, testOrNull){ + // summary: + // "magical" variant of registerTests, registerTest, and + // registerTestNs. Will accept the calling arguments of any of these + // methods and will correctly guess the right one to register with. + if( (arguments.length == 1)&& + (typeof groupOrNs == "string") ){ + if(groupOrNs.substr(0, 4)=="url:"){ + this.registerUrl(groupOrNs); + }else{ + this.registerTest("ungrouped", groupOrNs); + } + } + if(arguments.length == 1){ + this.debug("invalid args passed to doh.register():", groupOrNs, ",", testOrNull); + return; + } + if(typeof testOrNull == "string"){ + if(testOrNull.substr(0, 4)=="url:"){ + this.registerUrl(testOrNull); + }else{ + this.registerTest(groupOrNs, testOrNull); + } + // this.registerTestNs(groupOrNs, testOrNull); + return; + } + if(doh._isArray(testOrNull)){ + this.registerTests(groupOrNs, testOrNull); + return; + } + this.registerTest(groupOrNs, testOrNull); +} + +// +// Assertions and In-Test Utilities +// + +doh.t = doh.assertTrue = function(/*Object*/ condition){ + // summary: + // is the passed item "truthy"? + if(arguments.length != 1){ + throw doh._AssertFailure("assertTrue failed because it was not passed exactly 1 argument"); + } + if(!eval(condition)){ + throw doh._AssertFailure("assertTrue('" + condition + "') failed"); + } +} + +doh.f = doh.assertFalse = function(/*Object*/ condition){ + // summary: + // is the passed item "falsey"? + if(arguments.length != 1){ + throw doh._AssertFailure("assertFalse failed because it was not passed exactly 1 argument"); + } + if(eval(condition)){ + throw doh._AssertFailure("assertFalse('" + condition + "') failed"); + } +} + +doh.e = doh.assertError = function(/*Error object*/expectedError, /*Object*/scope, /*String*/functionName, /*Array*/args){ + // summary: + // Test for a certain error to be thrown by the given function. + // example: + // t.assertError(dojox.data.QueryReadStore.InvalidAttributeError, store, "getValue", [item, "NOT THERE"]); + // t.assertError(dojox.data.QueryReadStore.InvalidItemError, store, "getValue", ["not an item", "NOT THERE"]); + try{ + scope[functionName].apply(scope, args); + }catch (e){ + if(e instanceof expectedError){ + return true; + }else{ + throw new doh._AssertFailure("assertError() failed:\n\texpected error\n\t\t"+expectedError+"\n\tbut got\n\t\t"+e+"\n\n"); + } + } + throw new doh._AssertFailure("assertError() failed:\n\texpected error\n\t\t"+expectedError+"\n\tbut no error caught\n\n"); +} + + +doh.is = doh.assertEqual = function(/*Object*/ expected, /*Object*/ actual){ + // summary: + // are the passed expected and actual objects/values deeply + // equivalent? + + // Compare undefined always with three equal signs, because undefined==null + // is true, but undefined===null is false. + if((expected === undefined)&&(actual === undefined)){ + return true; + } + if(arguments.length < 2){ + throw doh._AssertFailure("assertEqual failed because it was not passed 2 arguments"); + } + if((expected === actual)||(expected == actual)){ + return true; + } + if( (this._isArray(expected) && this._isArray(actual))&& + (this._arrayEq(expected, actual)) ){ + return true; + } + if( ((typeof expected == "object")&&((typeof actual == "object")))&& + (this._objPropEq(expected, actual)) ){ + return true; + } + throw new doh._AssertFailure("assertEqual() failed:\n\texpected\n\t\t"+expected+"\n\tbut got\n\t\t"+actual+"\n\n"); +} + +doh._arrayEq = function(expected, actual){ + if(expected.length != actual.length){ return false; } + // FIXME: we're not handling circular refs. Do we care? + for(var x=0; x<expected.length; x++){ + if(!doh.assertEqual(expected[x], actual[x])){ return false; } + } + return true; +} + +doh._objPropEq = function(expected, actual){ + if(expected instanceof Date){ + return actual instanceof Date && expected.getTime()==actual.getTime(); + } + // Make sure ALL THE SAME properties are in both objects! + for(var x in actual){ // Lets check "actual" here, expected is checked below. + if(expected[x] === undefined){ + return false; + } + }; + + for(var x in expected){ + if(!doh.assertEqual(expected[x], actual[x])){ + return false; + } + } + return true; +} + +doh._isArray = function(it){ + return (it && it instanceof Array || typeof it == "array" || (dojo["NodeList"] !== undefined && it instanceof dojo.NodeList)); +} + +// +// Runner-Wrapper +// + +doh._setupGroupForRun = function(/*String*/ groupName, /*Integer*/ idx){ + var tg = this._groups[groupName]; + this.debug(this._line); + this.debug("GROUP", "\""+groupName+"\"", "has", tg.length, "test"+((tg.length > 1) ? "s" : "")+" to run"); +} + +doh._handleFailure = function(groupName, fixture, e){ + // this.debug("FAILED test:", fixture.name); + // mostly borrowed from JUM + this._groups[groupName].failures++; + var out = ""; + if(e instanceof this._AssertFailure){ + this._failureCount++; + if(e["fileName"]){ out += e.fileName + ':'; } + if(e["lineNumber"]){ out += e.lineNumber + ' '; } + out += e+": "+e.message; + this.debug("\t_AssertFailure:", out); + }else{ + this._errorCount++; + } + this.debug(e); + if(fixture.runTest["toSource"]){ + var ss = fixture.runTest.toSource(); + this.debug("\tERROR IN:\n\t\t", ss); + }else{ + this.debug("\tERROR IN:\n\t\t", fixture.runTest); + } + + if(e.rhinoException){ + e.rhinoException.printStackTrace(); + }else if(e.javaException){ + e.javaException.printStackTrace(); + } +} + +try{ + setTimeout(function(){}, 0); +}catch(e){ + setTimeout = function(func){ + return func(); + } +} + +doh._runFixture = function(groupName, fixture){ + var tg = this._groups[groupName]; + this._testStarted(groupName, fixture); + var threw = false; + var err = null; + // run it, catching exceptions and reporting them + try{ + // let doh reference "this.group.thinger..." which can be set by + // another test or group-level setUp function + fixture.group = tg; + // only execute the parts of the fixture we've got + if(fixture["setUp"]){ fixture.setUp(this); } + if(fixture["runTest"]){ // should we error out of a fixture doesn't have a runTest? + fixture.startTime = new Date(); + var ret = fixture.runTest(this); + fixture.endTime = new Date(); + // if we get a deferred back from the test runner, we know we're + // gonna wait for an async result. It's up to the test code to trap + // errors and give us an errback or callback. + if(ret instanceof doh.Deferred){ + + tg.inFlight++; + ret.groupName = groupName; + ret.fixture = fixture; + + ret.addErrback(function(err){ + doh._handleFailure(groupName, fixture, err); + }); + + var retEnd = function(){ + if(fixture["tearDown"]){ fixture.tearDown(doh); } + tg.inFlight--; + if((!tg.inFlight)&&(tg.iterated)){ + doh._groupFinished(groupName, (!tg.failures)); + } + doh._testFinished(groupName, fixture, ret.results[0]); + if(doh._paused){ + doh.run(); + } + } + + var timer = setTimeout(function(){ + // ret.cancel(); + // retEnd(); + ret.errback(new Error("test timeout in "+fixture.name.toString())); + }, fixture["timeout"]||1000); + + ret.addBoth(function(arg){ + clearTimeout(timer); + retEnd(); + }); + if(ret.fired < 0){ + doh.pause(); + } + return ret; + } + } + if(fixture["tearDown"]){ fixture.tearDown(this); } + }catch(e){ + threw = true; + err = e; + if(!fixture.endTime){ + fixture.endTime = new Date(); + } + } + var d = new doh.Deferred(); + setTimeout(this.hitch(this, function(){ + if(threw){ + this._handleFailure(groupName, fixture, err); + } + this._testFinished(groupName, fixture, (!threw)); + + if((!tg.inFlight)&&(tg.iterated)){ + doh._groupFinished(groupName, (!tg.failures)); + }else if(tg.inFlight > 0){ + setTimeout(this.hitch(this, function(){ + doh.runGroup(groupName); // , idx); + }), 100); + this._paused = true; + } + if(doh._paused){ + doh.run(); + } + }), 30); + doh.pause(); + return d; +} + +doh._testId = 0; +doh.runGroup = function(/*String*/ groupName, /*Integer*/ idx){ + // summary: + // runs the specified test group + + // the general structure of the algorithm is to run through the group's + // list of doh, checking before and after each of them to see if we're in + // a paused state. This can be caused by the test returning a deferred or + // the user hitting the pause button. In either case, we want to halt + // execution of the test until something external to us restarts it. This + // means we need to pickle off enough state to pick up where we left off. + + // FIXME: need to make fixture execution async!! + + var tg = this._groups[groupName]; + if(tg.skip === true){ return; } + if(this._isArray(tg)){ + if(idx<=tg.length){ + if((!tg.inFlight)&&(tg.iterated == true)){ + if(tg["tearDown"]){ tg.tearDown(this); } + doh._groupFinished(groupName, (!tg.failures)); + return; + } + } + if(!idx){ + tg.inFlight = 0; + tg.iterated = false; + tg.failures = 0; + } + doh._groupStarted(groupName); + if(!idx){ + this._setupGroupForRun(groupName, idx); + if(tg["setUp"]){ tg.setUp(this); } + } + for(var y=(idx||0); y<tg.length; y++){ + if(this._paused){ + this._currentTest = y; + // this.debug("PAUSED at:", tg[y].name, this._currentGroup, this._currentTest); + return; + } + doh._runFixture(groupName, tg[y]); + if(this._paused){ + this._currentTest = y+1; + if(this._currentTest == tg.length){ + tg.iterated = true; + } + // this.debug("PAUSED at:", tg[y].name, this._currentGroup, this._currentTest); + return; + } + } + tg.iterated = true; + if(!tg.inFlight){ + if(tg["tearDown"]){ tg.tearDown(this); } + doh._groupFinished(groupName, (!tg.failures)); + } + } +} + +doh._onEnd = function(){} + +doh._report = function(){ + // summary: + // a private method to be implemented/replaced by the "locally + // appropriate" test runner + + // this.debug("ERROR:"); + // this.debug("\tNO REPORTING OUTPUT AVAILABLE."); + // this.debug("\tIMPLEMENT doh._report() IN YOUR TEST RUNNER"); + + this.debug(this._line); + this.debug("| TEST SUMMARY:"); + this.debug(this._line); + this.debug("\t", this._testCount, "tests in", this._groupCount, "groups"); + this.debug("\t", this._errorCount, "errors"); + this.debug("\t", this._failureCount, "failures"); +} + +doh.togglePaused = function(){ + this[(this._paused) ? "run" : "pause"](); +} + +doh.pause = function(){ + // summary: + // halt test run. Can be resumed. + this._paused = true; +} + +doh.run = function(){ + // summary: + // begins or resumes the test process. + // this.debug("STARTING"); + this._paused = false; + var cg = this._currentGroup; + var ct = this._currentTest; + var found = false; + if(!cg){ + this._init(); // we weren't paused + found = true; + } + this._currentGroup = null; + this._currentTest = null; + + for(var x in this._groups){ + if( + ( (!found)&&(x == cg) )||( found ) + ){ + if(this._paused){ return; } + this._currentGroup = x; + if(!found){ + found = true; + this.runGroup(x, ct); + }else{ + this.runGroup(x); + } + if(this._paused){ return; } + } + } + this._currentGroup = null; + this._currentTest = null; + this._paused = false; + this._onEnd(); + this._report(); +} + +tests = doh; + +(function(){ + // scop protection + try{ + if(typeof dojo != "undefined"){ + dojo.platformRequire({ + browser: ["doh._browserRunner"], + rhino: ["doh._rhinoRunner"], + spidermonkey: ["doh._rhinoRunner"] + }); + var _shouldRequire = (dojo.isBrowser) ? (dojo.global == dojo.global["parent"]) : true; + if(_shouldRequire){ + if(dojo.isBrowser){ + dojo.addOnLoad(function(){ + if(dojo.byId("testList")){ + var _tm = ( (dojo.global.testModule && dojo.global.testModule.length) ? dojo.global.testModule : "dojo.tests.module"); + dojo.forEach(_tm.split(","), dojo.require, dojo); + setTimeout(function(){ + doh.run(); + }, 500); + } + }); + }else{ + // dojo.require("doh._base"); + } + } + }else{ + if( + (typeof load == "function")&& + ( (typeof Packages == "function")|| + (typeof Packages == "object") ) + ){ + throw new Error(); + }else if(typeof load == "function"){ + throw new Error(); + } + } + }catch(e){ + print("\n"+doh._line); + print("The Dojo Unit Test Harness, $Rev$"); + print("Copyright (c) 2007, The Dojo Foundation, All Rights Reserved"); + print(doh._line, "\n"); + + load("_rhinoRunner.js"); + + try{ + var dojoUrl = "../../dojo/dojo.js"; + var testUrl = ""; + var testModule = "dojo.tests.module"; + for(var x=0; x<arguments.length; x++){ + if(arguments[x].indexOf("=") > 0){ + var tp = arguments[x].split("="); + if(tp[0] == "dojoUrl"){ + dojoUrl = tp[1]; + } + if(tp[0] == "testUrl"){ + testUrl = tp[1]; + } + if(tp[0] == "testModule"){ + testModule = tp[1]; + } + } + } + if(dojoUrl.length){ + if(!this["djConfig"]){ + djConfig = {}; + } + djConfig.baseUrl = dojoUrl.split("dojo.js")[0]; + load(dojoUrl); + } + if(testUrl.length){ + load(testUrl); + } + if(testModule.length){ + dojo.forEach(testModule.split(","), dojo.require, dojo); + } + }catch(e){ + print("An exception occurred: " + e); + } + + doh.run(); + } +}).apply(this, typeof arguments != "undefined" ? arguments : [null]); |