Created
July 31, 2011 19:10
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==== 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