Skip to content

Instantly share code, notes, and snippets.

@shamansir
Created July 31, 2011 19:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shamansir/1117095 to your computer and use it in GitHub Desktop.
Save shamansir/1117095 to your computer and use it in GitHub Desktop.
Three tiny snippets that [may be] make JS simple: each, assert, class (+ tests for them)
var Base = class_({
_init: function(a, b) {
this.a = a;
this.b = b;
},
someMethod: function(a) {
this.a = a;
},
anotherMethod: function() { }
});
var Child = class_({
_extends: Base,
_init: function(b, c) {
this._s__init(5, b);
this.c = c;
},
someMethod: function(nein) {
this._s_someMethod(12);
this.b = 20;
},
someOtherMethod: function() { }
});
var SubChild = class_({
_extends: Child,
_init: function(d) {
this._s__init(13, 2);
this.d = d;
},
subMethod: function() { }
});
var T1 = class_({
_init: function() { },
setUp: function() { },
testClasses: function() {
var base1 = new Base(5, 7);
assertEquals(base1.a, 5);
assertEquals(base1.b, 7);
base1.someMethod(14);
assertEquals(base1.a, 14);
var base2 = new Base(13, 8);
assertEquals(base2.a, 13);
assertEquals(base2.b, 8);
base2.someMethod(30);
assertEquals(base2.a, 30);
var child = new Child(15, 9);
assertEquals(child.a, 5);
assertEquals(child.b, 15);
assertEquals(child.c, 9);
child.someMethod();
assertEquals(child.a, 12);
assertEquals(child.b, 20);
child.anotherMethod();
var subChild = new SubChild(15, -7);
assertEquals(subChild.a, 5);
assertEquals(subChild.b, 13);
assertEquals(subChild.c, 2);
assertEquals(subChild.d, -7);
subChild.someMethod();
assertEquals(child.a, 12);
assertEquals(child.b, 20);
subChild.subMethod();
assertInstance(base1, Base);
assertInstance(base2, Base);
assertInstance(child, Base);
assertInstance(child, Child);
assertInstance(subChild, Base);
assertInstance(subChild, Child);
assertInstance(subChild, SubChild);
assertTrue(child.hasOwnProperty('c'), 'child has property c');
assertTrue(child.hasOwnProperty('b'), 'child has property b');
assertTrue(child.hasOwnProperty('a'), 'child has property a');
assertFalse(child.hasOwnProperty('d'), 'child has no property d');
assertTrue(subChild.hasOwnProperty('a'), 'subChild has property a');
assertTrue(subChild.hasOwnProperty('b'), 'subChild has property b');
assertTrue(subChild.hasOwnProperty('c'), 'subChild has property c');
assertTrue(subChild.hasOwnProperty('d'), 'subChild has property d');
assertTrue(base1.hasOwnProperty('a'), 'base1 has property a');
assertTrue(base1.hasOwnProperty('b'), 'base1 has property b');
assertTrue(child.hasOwnProperty('someOtherMethod'), 'child has property someOtherMethod');
assertTrue(child.hasOwnProperty('someMethod'), 'child has property someMethod');
assertTrue(child.hasOwnProperty('anotherMethod'), 'child has property anotherMethod');
assertTrue(base1.hasOwnProperty('someMethod'), 'base1 has property someMethod');
assertTrue(base1.hasOwnProperty('anotherMethod'), 'base1 has property anotherMethod');
assertTrue(base2.hasOwnProperty('someMethod'), 'base2 has property someMethod');
assertTrue(base2.hasOwnProperty('anotherMethod'), 'base1 has property anotherMethod');
assertTrue(subChild.hasOwnProperty('someMethod'), 'subChild has property someMethod');
assertTrue(subChild.hasOwnProperty('subMethod'), 'subChild has property subMethod');
/* var base3 = Base();
assertDefined(base3);
assertInstance(base3, 'Base'); */
},
testAsserts: function() {
assert(null == null);
//assert(12 == null, '12 == null');
assert('a' == 'a', 'a == a');
assertTrue(true);
assertFalse(false);
//assertTrue(false);
//assertFalse(true);
//assertEquals(5, 5.1);
assertEquals(5, 5);
//assertEquals('a', 'ab');
assertEquals('aa', 'aa');
assertType(12, 'number');
//assertType(12, 'string');
assertType('12', 'string');
assertInstance(this, T1);
assertInstance(this, Object);
//assertInstance(null, Object);
assertNotNull(this);
//assertNotNull(null);
assertEquals(7.2, 7.2);
},
testEach: function() {
var arr = [12, 16, 18, 20, 30];
var i = 0;
each(arr, function(elem) {
assertEquals(elem, arr[i++]);
assertEquals(this, arr);
});
var obj = { 'a': 0, 'b': 12, 'cc': 'aaa',
'vv': function() {}, 'kk': { 'e': 15 } };
var keys = [ 'a', 'b', 'cc', 'vv', 'kk' ];
var i = 0;
each(obj, function(v, k) {
assertEquals(v, obj[keys[i]]);
assertEquals(k, keys[i]);
assertEquals(this, obj);
i++;
});
},
tearDown: function() { }
});
var _f = function() {
this.b = 12;
assertTrue(true);
assertEquals('12', '12');
assertEquals(this.b, 12);
//assertEquals(this, _f);
}
runTests(new T1()/*, 'T1'*/);
runTests(_f, '_f');
//new T1().test1();
//_f();
// ==== Console stub ===========================================================
if (!window.console) console = { 'log': function() {},
'info': function() {},
'warn': function() {},
'error': function() {},
'group': function() {},
'trace': function() {},
'groupEnd': function() {} };
// ==== Each ===================================================================
/**
* Tiny each
* @param {Array, Object} iterable the iterable to iterate through
* @param {Function} fn to call on each iteration, in function-mode gets an element (func(elem)),
in object-mode gets a key and value (func(k, v))
*/
function each(iterable, func) {
if (iterable instanceof Array) for (var i = 0, l = iterable.length; i < l; i++) func.call(iterable, iterable[i]);
else if (iterable instanceof Object) for (field in iterable) if (iterable.hasOwnProperty(field)) func.call(iterable, iterable[field], field);
}
// ==== Object Oriented ========================================================
// slightly modified from JS snippets
// http://www.willmcgugan.com/blog/tech/2009/12/5/javascript-snippets/
function class_(def) {
var _proto = def;
if (def['_extends'] !== undefined) {
var _ex = def['_extends'];
if (typeof _ex === 'function') {
each(_ex.prototype, function(v, k){
if (_proto[k] === undefined) {
_proto[k] = v;
} else {
_proto['_s_'+k] = v;
}
});
} else throw new Error('Wrong _extends field');
}
var _init = def['_init'];
if (_init === undefined) {
_init = function() {
if (this.prototype['_s__init']) this._s__init();
}
}
_init.prototype = _proto;
if (def['hasOwnProperty'] === undefined) {
def['hasOwnProperty'] = function(k) {
return (k !== 'hasOwnProperty') &&
(Object.prototype.hasOwnProperty.call(this, k) ||
Object.prototype.hasOwnProperty.call(_proto, k));
}
}
return _init;
}
function bind(obj, method) {
return function() { return method.apply(obj, arguments); }
}
Function.prototype.bind = function(obj) {
var fn = this;
return function() { return fn.apply(obj, arguments); }
}
// ==== Test Driven ============================================================
/**
* Assert Exception
* @param {Object} result the result of the assertion
* @param {Object} expectation what was expected
*/
function AssertException(result, expectation) { this.result = result;
this.expectation = expectation; }
AssertException.prototype.toString = function () {
if (this.expectation) return ('AssertException: Expected: ' + this.expectation + ' Got: ' + this.result);
else return ('AssertException: Got: ' + this.result);
}
/**
* Tiny assert
* @param {Boolean} test the expression to test
* @param {String} [_expectation] what was expected
* @throws {AssertException} if assertion was failed
*/
function assert(test, _expectation) {
if (!test) throw new AssertException(test, _expectation);
}
function _assert(test, val, expectation) {
if (!test) throw new AssertException(val, expectation);
}
function assertNotNull(test, label) { _assert(test !== null, test + ' == null', label || 'not null'); }
function assertDefined(test, label) { _assert(test !== undefined, test + ' !== undefined', label || 'defined'); }
function assertTrue(test, label) { _assert(test, test + ' != true', label || 'true'); }
function assertFalse(test, label) { _assert(!test, test + ' != false', label || 'false'); }
function assertEquals(first, second, label) { _assert(first === second, first + ' != ' + second, label || (second + ' == ' + second)); }
function assertInstance(test, cls, label) { _assert(test instanceof cls, test + ' not instance of ' + cls, label || (test + ' instance of ' + cls)); }
function assertType(test, typename, label) { _assert(typeof test == typename, test + ' is not of type ' + typename, label || (test + ' has type ' + typename)); }
/**
* Tests runner
* @param {Object, Function} suite for function-typed parameter,
calls a function and informs through Firebug console about assertions
for object-typed parameter,
works like JUnit, calls every method which name starts with 'test...'
also calls 'setUp' and 'tearDown' in the proper moments
informs through Firebug console about assertions and passed/failed methods
* @param {String} [_name] some name for test case or test suite (used only in logs to help you determine what failed)
* @param {Boolean} [_stopWhenFailed] for object-mode, stops testing when first assertion is failed in some method
* @returns {AssertException} first failed exception for function-mode, nothing for object-mode
*
* runTests(new SomeClass());
* runTests(someFunc(), 'someFunc');
*/
var __tCount = 0,
__fCount = 0;
function runTests(suite, _name, _stopWhenFailed) {
if (typeof suite === 'function') { __fCount++;
var field = (_name ? _name : ('Function ' + __fCount));
try { suite();
console.info('%s: %s', field, 'OK');
} catch (ex) {
if (ex instanceof AssertException) {
var info_ = '(' + field;
if (ex.lineNumber) info_ += ':' + ex.lineNumber;
if (ex.expectation) console.error('Assertion failed. Expected:', ex.expectation,
'. Got:', ex.result, info_ + ')');
else console.error('Assertion failed. Got:', ex.result, info_ + ')');
console.error(ex);
console.warn('%s: %s', field, 'FAILED');
return ex;
} else {
throw new Error(ex.toString());
}
}
} else if (typeof suite === 'object') { __tCount++;
var title = _name || ("Suite " + __tCount);
console.group(title);
for (var field in suite) {
if ((typeof suite[field] === 'function') &&
(field.indexOf('test') === 0) && suite.hasOwnProperty(field)) {
console.log('Running', title + ' / ' + field);
if (suite.setUp) suite.setUp();
var result = runTests(bind(suite, suite[field]), field);
var passed = (result === null);
if (_stopWhenFailed && (result !== null)) return result;
if (suite.tearDown) suite.tearDown();
}
}
console.groupEnd();
} else {
throw new Exception('Passed var has invalid type');
}
return null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment