Skip to content
Browse files

Fixed djangode and template system for node v1.30

  • Loading branch information...
1 parent aa72208 commit 8ce43c411a594fdcc39219351b1d5659e82fe995 Anders Hellerup Madsen committed
View
33 djangode.js
@@ -1,6 +1,6 @@
var http = require('http'),
sys = require('sys'),
- posix = require('posix'),
+ fs = require('fs'),
url = require('url');
function extname(path) {
@@ -21,8 +21,13 @@ exports.serveFile = function(req, res, filename) {
return;
}
sys.puts("loading " + filename + "...");
- var promise = posix.cat(filename, encoding);
- promise.addCallback(function(data) {
+ fs.readFile(filename, encoding, function (error, data) {
+ if (error) {
+ status = 404;
+ body = '404'
+ sys.puts("Error loading " + filename);
+ return callback();
+ }
body = data;
headers = [
['Content-Type', content_type],
@@ -34,17 +39,11 @@ exports.serveFile = function(req, res, filename) {
sys.puts("static file " + filename + " loaded");
callback();
});
- promise.addErrback(function() {
- status = 404;
- body = '404'
- sys.puts("Error loading " + filename);
- callback();
- });
}
loadResponseData(function() {
res.sendHeader(status, headers);
- res.sendBody(body, encoding);
- res.finish();
+ res.write(body, encoding);
+ res.close();
});
}
@@ -58,8 +57,8 @@ function respond(res, body, content_type, status) {
res.sendHeader(status || 200, {
'Content-Type': content_type + '; charset=utf-8'
});
- res.sendBody(body, 'utf8');
- res.finish();
+ res.write(body, 'utf8');
+ res.close();
}
exports.respond = respond;
@@ -69,17 +68,17 @@ exports.redirect = redirect = function(res, location, status) {
'Content-Type': 'text/html; charset=utf-8',
'Location': location
});
- res.sendBody('Redirecting...');
- res.finish();
+ res.write('Redirecting...');
+ res.close();
}
exports.extractPost = function(req, callback) {
req.setBodyEncoding('utf-8');
var body = '';
- req.addListener('body', function(chunk) {
+ req.addListener('data', function(chunk) {
body += chunk;
});
- req.addListener('complete', function() {
+ req.addListener('end', function() {
callback(http.parseUri('http://fake/?' + body).params);
});
}
View
9 template/loader.js
@@ -2,7 +2,7 @@
/*global require, process, exports, escape */
var sys = require('sys');
-var posix = require('posix');
+var fs = require('fs');
var cache = {};
var template_path = '/tmp';
@@ -16,12 +16,13 @@ function load(name, parse_function, callback) {
}
} else {
if (callback) {
- posix.cat(template_path + '/' + name).addCallback(function(s) {
+ fs.readfile(template_path + '/' + name, function (error, s) {
+ if (error) { callback(error); }
cache[name] = parse_function(s);
- callback(cache[name]);
+ callback(false, cache[name]);
});
} else {
- var content = posix.cat(template_path + '/' + name).wait();
+ var content = fs.readFileSync(template_path + '/' + name);
cache[name] = parse_function(content);
return cache[name];
}
View
4 template/template.js
@@ -238,7 +238,7 @@ function make_nodelist() {
process.mixin(Parser.prototype, {
- callbacks: template_defaults.callbacks,
+ tags: template_defaults.tags,
parse: function () {
@@ -259,7 +259,7 @@ process.mixin(Parser.prototype, {
//sys.debug('' + this.indent + ': ' + token);
- callback = this.callbacks[token.type];
+ callback = this.tags[token.type];
if (callback && typeof callback === 'function') {
node_list.append( callback(this, token), token.type );
} else {
View
223 template/template_defaults.js
@@ -11,9 +11,6 @@ var utils = require('utils/utils');
Not implemented (yet):
unordered_list
- wordcount
- wordwrap
- yesno
NOTE:
stringformat() filter is regular sprintf compliant and doesn't have real python syntax
@@ -27,10 +24,6 @@ Missing tags:
debug
- ifchanged
- ifequal
- ifnotequal
- now
regroup
spaceless
templatetag
@@ -243,12 +236,16 @@ var filters = exports.filters = {
return (value instanceof Date) ? utils.date.format_time(value, arg) : '';
},
timesince: function (value, arg) {
- value = new Date(value), arg = new Date(arg);
+ // TODO: this filter may not be safe (if people decides to put & or " in formatstrings"
+ value = new Date(value);
+ arg = new Date(arg);
if (isNaN(value) || isNaN(arg)) { return ''; }
return utils.date.timesince(value, arg);
},
timeuntil: function (value, arg) {
- value = new Date(value), arg = new Date(arg);
+ // TODO: this filter may not be safe (if people decides to put & or " in formatstrings"
+ value = new Date(value);
+ arg = new Date(arg);
if (isNaN(value) || isNaN(arg)) { return ''; }
return utils.date.timeuntil(value, arg);
},
@@ -280,7 +277,19 @@ var filters = exports.filters = {
return out;
}
return utils.html.urlize(value + "", { limit: arg });
+ },
+ wordcount: function (value, arg) {
+ return (value + "").split(/\s+/g).length;
+ },
+ wordwrap: function (value, arg) {
+ return utils.wordwrap(value + "", arg - 0);
+ },
+ yesno: function (value, arg) {
+ var responses = (arg + "").split(/,/g);
+ if (responses[2] && (value === undefined || value === null)) { return responses[2]; }
+ return (value ? responses[0] : responses[1]) || '';
}
+
};
@@ -353,6 +362,33 @@ var nodes = exports.nodes = {
};
},
+ IfChangedNode: function (node_list) {
+ var last;
+
+ return function (context) {
+ var current = node_list.evaluate(context);
+ if (current !== last) {
+ last = current;
+ return current;
+ } else {
+ return '';
+ }
+ };
+ },
+
+ IfEqualNode: function (node_list, first, second) {
+ return function (context) {
+ return context.get(first) == context.get(second) ? node_list.evaluate(context) : '';
+ };
+ },
+
+ IfNotEqualNode: function (node_list, first, second) {
+ return function (context) {
+ return context.get(first) != context.get(second) ? node_list.evaluate(context) : '';
+ };
+ },
+
+
CycleNode: function (items) {
var cnt = 0;
@@ -373,7 +409,7 @@ var nodes = exports.nodes = {
};
},
- BlockNode: function (name, node_list) {
+ BlockNode: function (node_list, name) {
return function (context) {
@@ -410,7 +446,14 @@ var nodes = exports.nodes = {
};
},
- AutoescapeNode: function (enable, node_list) {
+ AutoescapeNode: function (node_list, enable) {
+
+ if (enable.toLowerCase() === 'on') {
+ enable = true;
+ } else {
+ enable = false;
+ }
+
return function (context) {
var before = context.autoescaping;
context.autoescaping = enable;
@@ -420,18 +463,21 @@ var nodes = exports.nodes = {
}
},
- FirstOfNode: function (choices) {
+ FirstOfNode: function (/*...*/) {
+
+ var choices = Array.prototype.slice.apply(arguments);
+
return function (context) {
var i, val;
for (i = 0; i < choices.length; i++) {
- var val = context.get(choices[i]);
+ val = context.get(choices[i]);
if (val) { return val; }
}
return '';
- }
+ };
},
- WithNode: function (variable, name, node_list) {
+ WithNode: function (node_list, variable, name) {
return function (context) {
var item = context.get(variable);
context.push();
@@ -440,11 +486,80 @@ var nodes = exports.nodes = {
context.pop();
return out;
}
+ },
+
+ NowNode: function (format) {
+ if (format.match(/^["']/)) {
+ format = format.slice(1, -1);
+ }
+ return function (context) {
+ return utils.date.format_date(new Date(), format);
+ };
}
};
-var callbacks = exports.callbacks = {
+
+function assert_args_in_token(token, options) {
+ options = options || {};
+
+ var parts = token.split_contents();
+
+ if (options.argcount !== undefined && parts.length !== options.argcount + 1) {
+ throw 'unexpected syntax in "' + token.type + '" tag: Wrong number of arguments';
+ }
+
+ var i;
+ for (i = 1; i < parts.length; i++) {
+ if (options[i + 'mustbe']) {
+ var expected = options[i + 'mustbe'];
+ if (expected instanceof Array) {
+ if (expected.indexOf(parts[i]) === -1) {
+ throw 'unexpected syntax in "' + token.type + '" tag: Expected one of "' + expected.join('", "') + '"';
+ }
+ } else if (expected != parts[i]) {
+ throw 'unexpected syntax in "' + token.type + '" tag: Expected "' + options[i + 'mustbe'] + '"';
+ }
+ }
+ }
+
+ if (options.exclude) {
+ if (!(options.exclude instanceof Array)) { options.exclude = [options.exclude] }
+ var include = [];
+ for (i = 1; i < parts.length; i++) {
+ if (options.exclude.indexOf(i) === -1) { include.push(i); }
+ }
+ parts = include.map(function (x) { return parts[x]; });
+ } else {
+ parts = parts.slice(1);
+ }
+
+ return parts;
+}
+
+
+function simple_tag(node, options) {
+
+ return function (parser, token) {
+ var parts = assert_args_in_token(token, options);
+ return node.apply(null, parts);
+ };
+
+}
+
+function inclusion_tag(node, options) {
+ return function (parser, token) {
+
+ var parts = assert_args_in_token(token, options);
+
+ var node_list = parser.parse('end' + token.type);
+ parser.delete_first_token();
+
+ return node.apply(null, [node_list].concat(parts));
+ };
+}
+
+var tags = exports.tags = {
'text': function (parser, token) { return nodes.TextNode(token.contents); },
'variable': function (parser, token) {
@@ -452,7 +567,7 @@ var callbacks = exports.callbacks = {
},
'comment': function (parser, token) {
- parser.parse('endcomment');
+ parser.parse('end' + token.type);
parser.delete_first_token();
return nodes.TextNode('');
},
@@ -461,7 +576,7 @@ var callbacks = exports.callbacks = {
var parts = token.split_contents();
- if (parts[0] !== 'for' || parts[2] !== 'in' || (parts[4] && parts[4] !== 'reversed')) {
+ if (parts[2] !== 'in' || (parts[4] && parts[4] !== 'reversed')) {
throw 'unexpected syntax in "for" tag: ' + token.contents;
}
@@ -479,8 +594,6 @@ var callbacks = exports.callbacks = {
var parts = token.split_contents();
- if (parts[0] !== 'if') { throw 'unexpected syntax in "if" tag'; }
-
// get rid of if keyword
parts.shift();
@@ -519,11 +632,18 @@ var callbacks = exports.callbacks = {
return nodes.IfNode(item_names, not_item_names, operator, node_list, else_list);
},
+ // TODO: else
+ 'ifchanged': inclusion_tag(nodes.IfChangedNode, { argcount: 0 }),
+
+ // TODO: else
+ 'ifequal': inclusion_tag(nodes.IfEqualNode, { argcount: 2 }),
+
+ // TODO: else
+ 'ifnotequal': inclusion_tag(nodes.IfNotEqualNode, { argcount: 2 }),
+
'cycle': function (parser, token) {
var parts = token.split_contents();
- if (parts[0] !== 'cycle') { throw 'unexpected syntax in "cycle" tag'; }
-
var items = parts.slice(1);
var as_idx = items.indexOf('as');
var name = '';
@@ -554,7 +674,7 @@ var callbacks = exports.callbacks = {
'filter': function (parser, token) {
var parts = token.split_contents();
- if (parts[0] !== 'filter' || parts.length > 2) { throw 'unexpected syntax in "filter" tag'; }
+ if (parts.length > 2) { throw 'unexpected syntax in "filter" tag'; }
var expr = parser.make_filterexpression('|' + parts[1]);
@@ -563,62 +683,17 @@ var callbacks = exports.callbacks = {
return nodes.FilterNode(expr, node_list);
},
-
- 'block': function (parser, token) {
- var parts = token.split_contents();
- if (parts[0] !== 'block' || parts.length !== 2) { throw 'unexpected syntax in "block" tag'; }
- var name = parts[1];
- var node_list = parser.parse('endblock');
- parser.delete_first_token();
+ 'autoescape': inclusion_tag(nodes.AutoescapeNode, { argcount: 1, '1mustbe': ['on', 'off'] }),
- return nodes.BlockNode(name, node_list);
- },
+ 'block': inclusion_tag(nodes.BlockNode, { argcount: 1 }),
- 'extends': function (parser, token) {
- var parts = token.split_contents();
- if (parts[0] !== 'extends' || parts.length !== 2) { throw 'unexpected syntax in "extends" tag'; }
- var name = parts[1];
-
- return nodes.ExtendsNode(name);
- },
-
- 'autoescape': function (parser, token) {
- var parts = token.split_contents();
- if (parts[0] !== 'autoescape' || parts.length !== 2) { throw 'unexpected syntax in "autoescape" tag'; }
- var enable;
- if (parts[1] === 'on') {
- enable = true;
- } else if (parts[1] === 'off' ) {
- enable = false;
- } else {
- throw 'unexpected syntax in "autoescape" tag. Expected on or off';
- }
-
- var node_list = parser.parse('endautoescape');
- parser.delete_first_token();
+ 'extends': simple_tag(nodes.ExtendsNode, { argcount: 1 }),
- return nodes.AutoescapeNode(enable, node_list);
- },
+ 'firstof': simple_tag(nodes.FirstOfNode),
- 'firstof': function (parser, token) {
- var parts = token.split_contents();
- if (parts[0] !== 'firstof') { throw 'unexpected syntax in "firstof" tag'; }
- return nodes.FirstOfNode( parts.slice(1) );
- },
-
- 'with': function (parser, token) {
- var parts = token.split_contents();
- if (parts[0] !== 'with' || parts[2] !== 'as' || parts.length !== 4) {
- throw 'unexpected syntax in "with" tag';
- }
- var node_list = parser.parse('endwith');
- parser.delete_first_token();
-
- return nodes.WithNode(parts[1], parts[3], node_list);
- }
+ 'with': inclusion_tag(nodes.WithNode, { argcount: 3, exclude: 2, '2mustbe': 'as' }),
+ 'now': simple_tag(nodes.NowNode, { argcount: 1 })
};
-
-
View
49 template/template_defaults.tags.test.js
@@ -1,14 +1,13 @@
var sys = require('sys');
-var posix = require('posix');
+var fs = require('fs');
var template = require('template/template');
process.mixin(GLOBAL, require('utils/test').dsl);
process.mixin(GLOBAL, require('template/template_defaults'));
function write_file(path, content) {
- var file = posix.open(path,
- process.O_WRONLY | process.O_TRUNC | process.O_CREAT, 0666).wait();
- posix.write(file, content).wait();
- posix.close(file).wait();
+ var file = fs.openSync(path, process.O_WRONLY | process.O_TRUNC | process.O_CREAT, 0666);
+ fs.writeSync(file, content);
+ fs.closeSync(file);
}
@@ -178,6 +177,44 @@ testcase('with')
assertEquals('1:1', t.render(o));
assertEquals(1, cnt);
});
+testcase('ifchanged')
+ test('should work as expected', function () {
+ var t = template.parse('{% for item in list %}{% ifchanged %}{{ item }}{% endifchanged %}{%endfor%}');
+ var list = ['hest','giraf','giraf','hestgiraf'];
+ assertEquals('hestgirafhestgiraf', t.render({list: list}));
+ });
+testcase('ifequal')
+ test('should work as expected', function () {
+ var t = template.parse('{% ifequal "hest" "hest" %}giraf{%endifequal %}');
+ assertEquals('giraf', t.render());
+ t = template.parse('{% ifequal item "hest" %}giraf{%endifequal %}');
+ assertEquals('giraf', t.render({item: 'hest' }));
+ t = template.parse('{% ifequal item other %}giraf{%endifequal %}');
+ assertEquals('giraf', t.render({item: 'hest', other: 'hest' }));
+ assertEquals('', t.render({item: 'hest', other: 'laks' }));
+ });
+testcase('ifnotequal')
+ test('should work as expected', function () {
+ var t = template.parse('{% ifnotequal "hest" "giraf" %}laks{%endifnotequal %}');
+ assertEquals('laks', t.render());
+
+ t = template.parse('{% ifnotequal item "giraf" %}laks{%endifnotequal %}');
+ assertEquals('laks', t.render({item: 'hest' }));
+
+ t = template.parse('{% ifnotequal item other %}laks{%endifnotequal %}');
+ assertEquals('laks', t.render({item: 'hest', other: 'giraf' }));
+
+ assertEquals('', t.render({item: 'hest', other: 'hest' }));
+ });
+testcase('now')
+ test('should work as expected', function () {
+ var t = template.parse('{% now "H:i" %}');
+ var date = new Date();
+ var expected = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':' +
+ (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
+ assertEquals(expected, t.render());
+ });
+
-run(true);
+run(false);
View
14 template/template_defaults.test.js
@@ -164,7 +164,7 @@ testcase('length_is filter')
assertEquals(true, filters.length_is([1,2,3,4,5], 5));
assertEquals(true, filters.length_is('hest', 4));
});
- test('should fail on incorrect length or bad arguments', function () {
+ test('should return false on incorrect length or bad arguments', function () {
assertEquals(false, filters.length_is([1,2,3,4,5], 2));
assertEquals(false, filters.length_is('hest', 16));
assertEquals(false, filters.length_is(16, 4));
@@ -442,5 +442,17 @@ testcase('urlizetrunc');
filters.urlizetrunc('hest', 15, safety);
assertEquals(true, safety.is_safe);
});
+testcase('wordcount')
+ test('should count words', function () {
+ assertEquals(6, filters.wordcount('I am not an atomic playboy'));
+ });
+testcase('yesno')
+ test('should return correct value', function () {
+ assertEquals('yeah', filters.yesno(true, "yeah,no,maybe"));
+ assertEquals('no', filters.yesno(false, "yeah,no,maybe"));
+ assertEquals('maybe', filters.yesno(null, "yeah,no,maybe"));
+ assertEquals('maybe', filters.yesno(undefined, "yeah,no,maybe"));
+ assertEquals('no', filters.yesno(undefined, "yeah,no"));
+ });
run();
View
3 template_example.js
@@ -1,5 +1,4 @@
-var posix = require('posix'),
- sys = require('sys'),
+var sys = require('sys'),
dj = require('djangode'),
template_system = require('template/template');
View
27 utils/iter.js
@@ -0,0 +1,27 @@
+var sys = require('sys');
+
+exports.reduce = function reduce(array, iter_callback, initial, result_callback) {
+
+ var index = 0;
+ var depth = 0;
+
+ (function inner (error, value) {
+
+ if (error) {
+ result_callback(error);
+ }
+
+ if (index < array.length) {
+ process.nextTick( function () {
+ try {
+ iter_callback( value, array[index++], inner );
+ } catch (e) {
+ result_callback(e);
+ }
+ });
+ } else {
+ result_callback( false, value );
+ }
+ })( false, initial );
+}
+
View
28 utils/iter.test.js
@@ -0,0 +1,28 @@
+process.mixin(GLOBAL, require('utils/test').dsl);
+process.mixin(GLOBAL, require('utils/iter'));
+
+var events = require('events');
+var sys = require('sys');
+
+testcase('reduce');
+ test_async('should work like regular reduce', function (content, callback) {
+ var list = [];
+ for (var i = 0; i < 400000; i++) {
+ list.push(i);
+ }
+
+ //var t = new Date();
+ var expected = list.reduce(function (p, c) { return p + c; }, 0);
+ //sys.debug(new Date() - t);
+
+ reduce(list, function (p, c, callback) { callback(false, p + c); }, 0,
+ function (error, actual) {
+ //sys.debug(new Date() - t);
+ assertEquals(expected, actual, callback);
+ callback();
+ }
+ );
+ });
+
+run();
+
View
42 utils/string.js
@@ -162,3 +162,45 @@ function center(s, width) {
}
exports.center = center;
+
+/*************************************************************************/
+
+// from: http://phpjs.org/functions/wordwrap, all credit to authors below
+function wordwrap (str, int_width, str_break, cut) {
+ // Wraps buffer to selected number of characters using string break char
+ // version: 909.322
+ // discuss at: http://phpjs.org/functions/wordwrap
+ // + original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
+ // + improved by: Nick Callen
+ // + revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
+ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // + improved by: Sakimori // + bugfixed by: Michael Grier
+ // * example 1: wordwrap('Kevin van Zonneveld', 6, '|', true);
+ // * returns 1: 'Kevin |van |Zonnev|eld'
+ // * example 2: wordwrap('The quick brown fox jumped over the lazy dog.', 20, '\n');
+ // * returns 2: 'The quick brown fox \njumped over the lazy\n dog.'
+ // * example 3: wordwrap('Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.');
+ // * returns 3: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod \ntempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim \nveniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea \ncommodo consequat.'
+ // PHP Defaults
+ var m = ((arguments.length >= 2) ? arguments[1] : 75 );
+ var b = ((arguments.length >= 3) ? arguments[2] : "\n" );
+ var c = ((arguments.length >= 4) ? arguments[3] : false);
+
+ var i, j, l, s, r;
+
+ str += '';
+ if (m < 1) {
+ return str;
+ }
+ for (i = -1, l = (r = str.split(/\r\n|\n|\r/)).length; ++i < l; r[i] += s) {
+ for (s = r[i], r[i] = ""; s.length > m; r[i] += s.slice(0, j) + ((s = s.slice(j)).length ? b : "")){
+ j = c == 2 || (j = s.slice(0, m + 1).match(/\S*(\s)?$/))[1] ? m : j.input.length - j[0].length ||
+ c == 1 && m || j.input.length + (j = s.slice(m).match(/^\S*/)).input.length;
+ }
+ }
+ return r.join("\n");
+}
+exports.wordwrap = wordwrap;
+
+
+
View
4 utils/string.test.js
@@ -25,5 +25,9 @@ testcase('titleCaps')
titleCaps("Q&A With Steve Jobs: 'That's What Happens In Technology'")
);
})
+testcase('wrap')
+ test('should wrap text', function () {
+ assertEquals('Joel \nis a \nslug', wordwrap('Joel is a slug', 5));
+ });
run();
View
181 utils/test.js
@@ -46,6 +46,7 @@ var isEqual = function (expected, actual) {
var testcases = [];
+
exports.dsl = {
testcase: function (name) {
@@ -53,6 +54,20 @@ exports.dsl = {
},
test: function (name, func) {
+ testcases[0].tests.push({
+ name: name,
+ body: function (context, callback) {
+ try {
+ func(context);
+ callback();
+ } catch (e) {
+ callback(e);
+ }
+ }
+ });
+ },
+
+ test_async: function (name, func) {
testcases[0].tests.push({ name: name, body: func });
},
@@ -66,82 +81,111 @@ exports.dsl = {
run: function (stop_on_error) {
- var count = 0, failed = 0, errors = 0;
-
- testcases.reverse();
+ var count = 0, error_cnt = 0, failed_cnt = 0;
+ var testcase_idx = testcases.length - 1;
- try {
+ (function run_testcases() {
- testcases.forEach( function (testcase) {
+ var idx = 0;
+ var testcase = testcases[testcase_idx--];
+ if (testcase) {
sys.puts('\n[Testcase: ' + testcase.name + ']');
- testcase.tests.forEach( function (test) {
-
- count++;
-
- var context = testcase.setup ? testcase.setup() : {};
-
- try {
- test.body(context);
- sys.puts(' [OK] ' + test.name + ': passed');
- } catch (e) {
- if (e instanceof AssertFailedException) {
- sys.puts(' [--] ' + test.name + ': failed. ' + e.message);
- failed++;
- } else {
- sys.print(' [!!] ' + test.name + ': error. ');
- if (e.stack && e.type) {
- sys.puts(e.type + '\n' + e.stack);
+ (function run_tests() {
+
+ var test = testcase.tests[idx];
+
+ if (test) {
+
+ idx = idx + 1;
+ count = count + 1;
+
+ var context = testcase.setup ? testcase.setup() : {};
+
+ function handle_result(error) {
+ if (error) {
+ if (error instanceof AssertFailedException) {
+ sys.puts(' [--] ' + test.name + ': failed. ' + error.message);
+ failed_cnt++;
+ } else {
+ sys.print(' [!!] ' + test.name + ': error. ');
+ if (error.stack && error.type) {
+ sys.puts(error.type + '\n' + error.stack);
+ } else {
+ sys.puts(JSON.stringify(error, 0, 2));
+ }
+ error_cnt++;
+ }
+
+ if (stop_on_error) {
+ sys.puts('stopping on first error');
+ testcase_idx = -1;
+ idx = testcase.tests.length;
+ }
} else {
- sys.puts(JSON.stringify(e, 0, 2));
+ sys.puts(' [OK] ' + test.name + ': passed');
}
- errors++;
+
+ if (testcase.teardown) { testcase.teardown(context); }
+
+ process.nextTick(run_tests);
}
- if (stop_on_error) { throw 'stopping on first error'; }
- }
- if (testcase.teardown) { testcase.teardown(context); }
- });
- sys.puts('----');
- });
- } catch (e) {
- if (e === 'stopping on first error') {
- sys.puts(e);
+ try {
+ test.body(context, handle_result);
+ } catch (e) {
+ handle_result(e);
+ }
+
+ } else {
+ // no more tests
+ sys.puts('----');
+ process.nextTick(run_testcases);
+ }
+ })();
} else {
- throw e;
+ // no more testcases
+ sys.puts('\nTotal: ' + count + ', Failures: ' + failed_cnt + ', Errors: ' + error_cnt + '');
}
- }
- sys.puts('\nTotal: ' + count + ', Failures: ' + failed + ', Errors: ' + errors + '');
+
+ })();
},
- assertEquals: function (actual, expected) {
+ assertEquals: function (actual, expected, callback) {
if (!isEqual(actual, expected)) {
- throw new AssertFailedException(
+ var exception = new AssertFailedException(
'\nExpected: ' + sys.inspect(actual) + '\nActual: ' + sys.inspect(expected) + '\n'
);
- }
+ if (callback) { callback(exception); } else { throw exception; }
+ };
},
- shouldThrow: function (func, args, this_context) {
+ shouldThrow: function (func, args, this_context, callback) {
try {
func.apply(this_context, args);
} catch (e) {
- return;
+ var passed = true;
+ }
+
+ if (!passed) {
+ var exception = new AssertFailedException('No exception was thrown');
+ if (callback) { callback(exception); } else { throw exception; }
}
- throw new AssertFailedException('No exception was thrown');
},
- shouldNotThrow: function (func, args, this_context) {
+ shouldNotThrow: function (func, args, this_context, callback) {
try {
func.apply(this_context, args);
} catch (e) {
- throw new AssertFailedException('Caught <' + e + '>');
+ var exception = new AssertFailedException('Caught <' + e + '>');
+ if (callback) { callback(exception); } else { throw exception; }
}
},
- fail: function (message) {
- throw new AssertFailedException(message);
+ fail: function (message, callback) {
+ var exception = new AssertFailedException(message);
+ if (callback) { callback(exception); } else { throw exception; }
}
};
@@ -156,7 +200,7 @@ with (exports.dsl) {
assertEquals(2, 2);
shouldNotThrow( assertEquals, [2,2] );
})
- test('four should not eqaul two', function () {
+ test('four should not equal two', function () {
shouldThrow( assertEquals, [2,4] );
})
test('broken function should throw', function () {
@@ -186,7 +230,48 @@ with (exports.dsl) {
test('different objects should not be equal', function () {
shouldThrow( assertEquals, [ {a: 'hest', b: 5, c: [1,2,3]}, {a: 'hest', b: 5, c: [2,3]} ]);
})
+
+ testcase('Testing async tests');
+ test_async('wait then success', function(context, callback) {
+ setTimeout(callback, 500);
+ });
+ test_async('wait then failure', function(context, callback) {
+ setTimeout(function () { callback("error - but it's okay :-)")}, 500);
+ });
+ test_async("this test throws, and should always fail", function () {
+ throw "it's okay :-)";
+ });
+ test_async('wait with assert', function (context, callback) {
+ setTimeout(function () {
+ assertEquals('hest', 'hest', callback);
+ assertEquals(2, 2, callback);
+ shouldThrow(assertEquals, [2,4], null, callback)
+ callback();
+ });
+ });
+
+ testcase('Testing setup and teardown');
+ var teardown_result = 0;
+
+ setup(function () {
+ return { hest: 1 }
+ });
+
+ teardown(function (context) {
+ teardown_result = context.hest;
+ });
+
+ test('setup should run before test', function (context) {
+ assertEquals({ hest: 1 }, context);
+ context.hest += 1;
+ });
+
+ test('teardown should run after test', function (context) {
+ assertEquals(2, teardown_result);
+ });
+
run();
}
-*/
+//*/
+
View
1 utils/utils.js
@@ -3,4 +3,5 @@
exports.string = require('utils/string');
exports.date = require('utils/date');
exports.html = require('utils/html');
+exports.iter = require('utils/iter');

0 comments on commit 8ce43c4

Please sign in to comment.
Something went wrong with that request. Please try again.