Add Utils to global.Cylon namespace, add bootstrap

This commit moves Utils to live in the global Cylon namespace, so they can be
accessed in test suites. This is necessary because Mocha, when setting up for
tests, will override our #after method, making TDR not work if any robots
contain a #after call in their work block.

To fix this, in test setup you can call global.Cylon.Utils.bootstrap();
which will re-setup our globals.
This commit is contained in:
Andrew Stewart 2014-04-01 12:31:13 -07:00
parent 2563e62de4
commit 1cffa6067e
1 changed files with 167 additions and 146 deletions

View File

@ -77,161 +77,182 @@ Number.prototype.toScale = function(start, end) {
}
};
var Utils = {
// Public: Alias to setInterval, combined with Number monkeypatches below to
// create an artoo-like syntax.
//
// interval - interval to run action on
// action - action to perform at interval
//
// Examples
//
// every 5.seconds(), -> console.log("hello world (and again in 5 seconds)!")
//
// Returns an interval
every: function(interval, action) {
return setInterval(action, interval);
},
var namespace = require('node-namespace');
// Public: Alias to setTimeout, combined with Number monkeypatches below to
// create an artoo-like syntax.
//
// interval - interval to run action on
// action - action to perform at interval
//
// Examples
//
// after 10.seconds(), -> console.log("hello world from ten seconds ago!")
//
// Returns an interval
after: function(delay, action) {
return setTimeout(action, delay);
},
namespace('Cylon', function() {
this.Utils = {
// Public: Alias to setInterval, combined with Number monkeypatches below to
// create an artoo-like syntax.
//
// interval - interval to run action on
// action - action to perform at interval
//
// Examples
//
// every 5.seconds(), -> console.log("hello world (and again in 5 seconds)!")
//
// Returns an interval
every: function(interval, action) {
return setInterval(action, interval);
},
// Public: Alias to the `every` function, but passing 0
// Examples
//
// constantly -> console.log("hello world (and again and again)!")
//
// Returns an interval
constantly: function(action) {
return every(0, action);
},
// Public: Alias to setTimeout, combined with Number monkeypatches below to
// create an artoo-like syntax.
//
// interval - interval to run action on
// action - action to perform at interval
//
// Examples
//
// after 10.seconds(), -> console.log("hello world from ten seconds ago!")
//
// Returns an interval
after: function(delay, action) {
return setTimeout(action, delay);
},
// Public: Sleep - do nothing for some duration of time.
//
// ms - number of ms to sleep for
//
// Returns a function
// Examples:
// sleep 1.second()
sleep: function(ms) {
var start = Date.now();
// Public: Alias to the `every` function, but passing 0
// Examples
//
// constantly -> console.log("hello world (and again and again)!")
//
// Returns an interval
constantly: function(action) {
return every(0, action);
},
while(Date.now() < start + ms) {
var i = 0;
}
},
// Public: Sleep - do nothing for some duration of time.
//
// ms - number of ms to sleep for
//
// Returns a function
// Examples:
// sleep 1.second()
sleep: function(ms) {
var start = Date.now();
// Copies
slice: [].slice,
hasProp: {}.hasOwnProperty,
while(Date.now() < start + ms) {
var i = 0;
}
},
// Public: Function to use for class inheritance. Copy of a CoffeeScript helper
// function.
//
// Example
//
// var Sphero = (function(klass) {
// subclass(Sphero, klass);
// // Sphero is now a subclass of Parent, and can access it's methods through
// // Sphero.__super__
// })(Parent);
//
// Returns subclass
subclass: function(child, parent) {
var ctor = function() { this.constructor = child; };
// Copies
slice: [].slice,
hasProp: {}.hasOwnProperty,
for (var key in parent) {
if (hasProp.call(parent, key)) { child[key] = parent[key]; }
}
// Public: Function to use for class inheritance. Copy of a CoffeeScript helper
// function.
//
// Example
//
// var Sphero = (function(klass) {
// subclass(Sphero, klass);
// // Sphero is now a subclass of Parent, and can access it's methods through
// // Sphero.__super__
// })(Parent);
//
// Returns subclass
subclass: function(child, parent) {
var ctor = function() { this.constructor = child; };
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.__super__ = parent.prototype;
return child;
},
// Public: Proxies a list of methods from one object to another. It will not
// overwrite existing methods unless told to.
//
// methods - array of functions to proxy
// target - object to proxy the functions to
// base - (optional) object that proxied functions will be declared on. Defaults
// to this
// force - (optional) boolean - whether or not to force method assignment
//
// Returns base
proxyFunctionsToObject: function(methods, target, base, force) {
if (base == null) { base = this; }
if (force == null) { force = false; }
var fn = function(method) {
return base[method] = function() {
var args = arguments.length >= 1 ? [].slice.call(arguments, 0) : [];
return target[method].apply(target, args);
};
};
for (var i = 0; i < methods.length; i++) {
var method = methods[i];
if (!force) {
if (typeof base[method] === 'function') { continue; }
for (var key in parent) {
if (hasProp.call(parent, key)) { child[key] = parent[key]; }
}
fn(method);
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.__super__ = parent.prototype;
return child;
},
// Public: Proxies a list of methods from one object to another. It will not
// overwrite existing methods unless told to.
//
// methods - array of functions to proxy
// target - object to proxy the functions to
// base - (optional) object that proxied functions will be declared on. Defaults
// to this
// force - (optional) boolean - whether or not to force method assignment
//
// Returns base
proxyFunctionsToObject: function(methods, target, base, force) {
if (base == null) { base = this; }
if (force == null) { force = false; }
var fn = function(method) {
return base[method] = function() {
var args = arguments.length >= 1 ? [].slice.call(arguments, 0) : [];
return target[method].apply(target, args);
};
};
for (var i = 0; i < methods.length; i++) {
var method = methods[i];
if (!force) {
if (typeof base[method] === 'function') { continue; }
}
fn(method);
}
return base;
},
// Public: Proxies a list of methods for test stubbing.
//
// methods - array of functions to proxy
// base - (optional) object that proxied functions will be declared on. Defaults
// to this
//
// Returns base
proxyTestStubs: function(methods, base) {
if (base == null) { base = this; }
methods.forEach(function(method) {
base[method] = function() { return true; };
base.commandList.push(method);
});
return base;
},
// Public: Binds an argument to a caller
//
// fn - function to bind
// me - value for 'this' scope inside the function
//
// Examples
//
// var me = { hello: "Hello World" };
// var proxy = { boundMethod: function() { return this.hello; } };
// proxy.boundMethod = bind(proxy.boundMethod, me);
// proxy.boundMethod();
// //=> "Hello World"
//
// Returns a function wrapper
bind: function(fn, me) {
return function() { return fn.apply(me, arguments); };
},
// Public: Adds all methods from Cylon.Utils directly to the global
// namespace.
//
// Examples
//
// Cylon.Utils.bootstrap();
// (after === Cylon.Utils.After) // true
//
// Returns Cylon.Utils
bootstrap: function() {
for (util in this) {
// we're not going to attach the 'bootstrap' method
if (!(util === "bootstrap")) {
global[util] = this[util];
}
}
return this;
}
return base;
},
};
});
// Public: Proxies a list of methods for test stubbing.
//
// methods - array of functions to proxy
// base - (optional) object that proxied functions will be declared on. Defaults
// to this
//
// Returns base
proxyTestStubs: function(methods, base) {
if (base == null) { base = this; }
methods.forEach(function(method) {
base[method] = function() { return true; };
base.commandList.push(method);
});
return base;
},
// Public: Binds an argument to a caller
//
// fn - function to bind
// me - value for 'this' scope inside the function
//
// Examples
//
// var me = { hello: "Hello World" };
// var proxy = { boundMethod: function() { return this.hello; } };
// proxy.boundMethod = bind(proxy.boundMethod, me);
// proxy.boundMethod();
// //=> "Hello World"
//
// Returns a function wrapper
bind: function(fn, me) {
return function() { return fn.apply(me, arguments); };
}
};
// Add all utility functions to global namespace
for (var util in Utils) { global[util] = Utils[util]; }
module.exports = Utils;
module.exports = Cylon.Utils.bootstrap();