Add a bunch of unit tests (not nearly complete, but it's a start).
diff --git a/edit.html b/edit.html
index 9be9bda..8e753ba 100644
--- a/edit.html
+++ b/edit.html
@@ -60,7 +60,7 @@
for (var parti in parts) {
var part = parts[parti];
if (part) {
- var bits = afterquery.trySplitOne(part, '=');
+ var bits = afterquery.internal.trySplitOne(part, '=');
if (bits) {
out.push(niceEncode(bits[0]) + '=' + niceEncode(bits[1]));
} else {
@@ -90,7 +90,8 @@
lastloaded = null;
var exampleurl = (window.location.protocol + '//' + window.location.host +
'/example1.json');
-args = afterquery.parseArgs(window.location.search || ('?url=' + exampleurl));
+args = afterquery.internal.parseArgs(window.location.search ||
+ ('?url=' + exampleurl));
argsToForm(args);
updateUrl();
</script>
diff --git a/render.js b/render.js
index b6c2e43..faaa028 100644
--- a/render.js
+++ b/render.js
@@ -1,11 +1,25 @@
'use strict';
var afterquery = (function() {
- // Mostly for konqueror compatibility
- var console = window.console;
+ // To appease v8shell
+ var console;
+ try {
+ console = window.console;
+ }
+ catch (ReferenceError) {
+ console = {
+ debug: print
+ };
+ }
+
+ // For konqueror compatibility
if (!console) {
- console = {};
- console.debug = function() {};
+ console = window.console;
+ }
+ if (!console) {
+ console = {
+ debug: function() {}
+ };
}
@@ -92,12 +106,11 @@
function guessTypes(data) {
- console.debug('guessTypes');
var impossible = [];
for (var rowi in data) {
var row = data[rowi];
for (var coli in row) {
- impossible[coli] += 0;
+ impossible[coli] |= 0;
var cell = row[coli];
if (cell == '' || cell == null) continue;
var d = myParseDate(cell);
@@ -136,12 +149,13 @@
var DATE_RE1 = RegExp('^(\\d{4})[-/](\\d{1,2})(?:[-/](\\d{1,2})' +
'(?:[T\\s](\\d{1,2}):(\\d\\d)(?::(\\d\\d))?)?)?$');
- var DATE_RE2 = RegExp('^Date\\((\\d+),(\\d+),(\\d+)' +
- '(?:,(\\d+),(\\d+)(?:,(\\d+)(?:,(\\d+))?)?)?\\)$');
+ var DATE_RE2 = /^Date\(([\d,]+)\)$/;
function myParseDate(s) {
if (s == null) return s;
if (s && s.getDate) return s;
- var g = DATE_RE1.exec(s) || DATE_RE2.exec(s);
+ var g = DATE_RE2.exec(s);
+ if (g) g = (',' + g[1]).split(',');
+ if (!g || g.length > 8) g = DATE_RE1.exec(s);
if (g) {
return new Date(g[1], g[2] - 1, g[3] || 1,
g[4] || 0, g[5] || 0, g[6] || 0, g[7] || 0);
@@ -1119,8 +1133,22 @@
}
return {
- parseArgs: parseArgs,
- trySplitOne: trySplitOne,
+ internal: {
+ parseArgs: parseArgs,
+ trySplitOne: trySplitOne,
+ dataToGvizTable: dataToGvizTable,
+ guessTypes: guessTypes,
+ groupBy: groupBy,
+ pivotBy: pivotBy,
+ stringifiedCols: stringifiedCols,
+ treeify: treeify,
+ filterBy: filterBy,
+ queryBy: queryBy,
+ orderBy: orderBy,
+ extractRegexp: extractRegexp,
+ fillNullsWithZero: fillNullsWithZero,
+ gridFromData: gridFromData
+ },
render: wrap(_run)
};
})();
diff --git a/t/trender.js b/t/trender.js
new file mode 100644
index 0000000..40a8ead
--- /dev/null
+++ b/t/trender.js
@@ -0,0 +1,115 @@
+'use strict';
+
+
+function dump(arg) {
+ function _dump(indent, obj) {
+ var any = 0;
+ if (typeof obj != 'string') {
+ for (var i in obj) {
+ _dump((indent ? indent + '.' : '') + i, obj[i]);
+ any++;
+ }
+ }
+ if (!any) {
+ print(indent + ' = ' + obj);
+ }
+ }
+ _dump('', arg);
+}
+
+
+// load the 'afterquery' object for testing
+load('render.js');
+
+
+// fake gviz library implementation
+var google = {
+ visualization: {
+ DataTable: function(t) { return t; }
+ }
+};
+
+wvtest('parseArgs', function() {
+ var query = '?a=b&c=d&e==f&&g=h&g=i%25%31%31&a=&a=x';
+ var args = afterquery.internal.parseArgs(query);
+ WVPASSEQ(args.all.join('|'), 'a,b|c,d|e,=f|,|g,h|g,i%11|a,|a,x');
+ WVPASSEQ(args.get('a'), 'x');
+ WVPASSEQ(args.get(''), '');
+ WVPASSEQ(args.get('g'), 'i%11');
+
+ WVPASSEQ(afterquery.internal.parseArgs('').all.join('|'), ',');
+ WVPASSEQ(afterquery.internal.parseArgs('?').all.join('|'), ',');
+ WVPASSEQ(afterquery.internal.parseArgs('abc=def').all.join('|'), 'bc,def');
+});
+
+
+wvtest('dataToGvizTable', function() {
+ var grid = {
+ headers: ['a', 'b', 'c', 'd', 'e'],
+ types: ['number', 'date', 'datetime', 'bool', 'string'],
+ data: [
+ [null, null, null, null, null],
+ [0, 1, 2, 3, 4],
+ [1.5, '2012-11-15 01:23', '2013-12-16 01:24:25', false, 'hello']
+ ]
+ };
+ var dt = afterquery.internal.dataToGvizTable(grid, {});
+ dump(dt);
+ WVPASSEQ(dt.cols.length, 5);
+ WVPASSEQ(dt.rows.length, 3);
+ for (var i in dt.cols) {
+ WVPASSEQ(dt.cols[i].id, ['a', 'b', 'c', 'd', 'e'][i]);
+ WVPASSEQ(dt.cols[i].label, dt.cols[i].id);
+ WVPASSEQ(dt.cols[i].type,
+ ['number', 'date', 'datetime', 'bool', 'string'][i]);
+ }
+ for (var coli in dt.rows[0]) {
+ print('row', 0, 'col', coli);
+ WVPASSEQ(dt.rows[0].c[coli], null);
+ }
+ for (var rowi = 1; rowi < dt.rows.length; rowi++) {
+ for (var coli in dt.rows[rowi].c) {
+ print('row', rowi, 'col', coli);
+ WVPASSEQ(dt.rows[rowi].c[coli].v, grid.data[rowi][coli]);
+ }
+ }
+});
+
+
+wvtest('guessTypes', function() {
+ var data1 = [['1999-01-01', '1999-02-02', 1, 2.5, false, 'foo']];
+ var data2 = [['1999-01-01', '1999-02-02 12:34', 2, 'x', true, null]];
+ var datanull = [[null, null, null, null]];
+ var guessTypes = afterquery.internal.guessTypes;
+ WVPASSEQ(guessTypes([]), []);
+ WVPASSEQ(guessTypes([[5]]), ['number']);
+ WVPASSEQ(guessTypes([[null]]), ['boolean']);
+ WVPASSEQ(guessTypes([['2012']]), ['number']);
+ WVPASSEQ(guessTypes([['2012-01']]), ['date']);
+ WVPASSEQ(guessTypes([['2012/01']]), ['date']);
+ WVPASSEQ(guessTypes([['2012/01-02']]), ['date']);
+ WVPASSEQ(guessTypes([['2012/01/01 23:45']]), ['datetime']);
+ WVPASSEQ(guessTypes([['2012-01/01 23:45:67']]), ['datetime']);
+ WVPASSEQ(guessTypes([['2012/01/01T23:45:67']]), ['datetime']);
+ WVPASSEQ(guessTypes([['2012-01-01T23:45:67']]), ['datetime']);
+ WVPASSEQ(guessTypes([['2012/01/01 23:45:67.12']]), ['string']);
+ WVPASSEQ(guessTypes([['Date(2012,2,3)']]), ['date']);
+ WVPASSEQ(guessTypes([['Date(2012,2,3,4)']]), ['datetime']);
+ WVPASSEQ(guessTypes([['Date(2012,2,3,4,5,6)']]), ['datetime']);
+ WVPASSEQ(guessTypes([['Date(2012,2,3,4,5,6,7)']]), ['datetime']);
+ WVPASSEQ(guessTypes([['Date(2012,2,3,4,5,6,7,8)']]), ['string']);
+ WVPASSEQ(guessTypes([['Date(2012,x,1)']]), ['string']);
+ WVPASSEQ(guessTypes(data1),
+ ['date', 'date', 'boolean', 'number', 'boolean', 'string']);
+ WVPASSEQ(guessTypes(data2),
+ ['date', 'datetime', 'number', 'string', 'boolean', 'boolean']);
+ WVPASSEQ(guessTypes(data1.concat(data2)),
+ ['date', 'datetime', 'number', 'string', 'boolean', 'string']);
+ WVPASSEQ(guessTypes(data2.concat(data1)),
+ ['date', 'datetime', 'number', 'string', 'boolean', 'string']);
+ WVPASSEQ(guessTypes(data2.concat(datanull)
+ .concat(data1)),
+ ['date', 'datetime', 'number', 'string', 'boolean', 'string']);
+ WVPASSEQ(guessTypes(data2.concat(datanull)),
+ ['date', 'datetime', 'number', 'string', 'boolean', 'boolean']);
+});
diff --git a/wvtest.js b/wvtest.js
index e7b1d92..3a1008c 100644
--- a/wvtest.js
+++ b/wvtest.js
@@ -92,6 +92,10 @@
function WVPASSEQ(a, b, precision) {
var t = trace()[1];
+ if (a && b && a.join && b.join) {
+ a = a.join('|');
+ b = b.join('|');
+ }
var cond = precision ? Math.abs(a-b) < precision : (a == b);
return _check(cond, t, '' + a + ' == ' + b);
}
@@ -99,6 +103,10 @@
function WVPASSNE(a, b, precision) {
var t = trace()[1];
+ if (a.join && b.join) {
+ a = a.join('|');
+ b = b.join('|');
+ }
var cond = precision ? Math.abs(a-b) >= precision : (a != b);
return _check(a != b, t, '' + a + ' != ' + b);
}