Ox.doc: change test object from {statement, result} to {statement, expected}, plus some refactoring; Ox.test: allow source, file, files, docObject or docObjects as first argument, make it testable and add a test, plus some refactoring; Ox.tokenize: add error type, continue lexing on error
This commit is contained in:
parent
38016aa06b
commit
5dc654ad6d
1 changed files with 150 additions and 90 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
/*@
|
||||
Ox.doc <f> Generates documentation for annotated JavaScript
|
||||
(source) -> <[o]> Array of doc objects
|
||||
(source[, callback]) -> <[o]> Array of doc objects
|
||||
(file, callback) -> <u> undefined
|
||||
(files, callback) -> <u> undefined
|
||||
source <s> JavaScript source code
|
||||
|
@ -35,6 +35,8 @@ Ox.doc <f> Generates documentation for annotated JavaScript
|
|||
Present if the <code>type</code> of the item is
|
||||
<code>"function"</code>.
|
||||
tests <[o]> Tests (array of test objects)
|
||||
expected <s> Expected result
|
||||
statement <s> Statement
|
||||
type <s> Type of the item
|
||||
<script>
|
||||
Ox.test.doc = Ox.doc(
|
||||
|
@ -46,10 +48,14 @@ Ox.doc <f> Generates documentation for annotated JavaScript
|
|||
' Bar per baz is a good indicator of an item\'s foo-ness.\n' +
|
||||
' (item) -> <n> Bar per baz, or NaN\n' +
|
||||
' item <o> Any item\n' +
|
||||
' > My.foo({bar: 1, baz: 10})\n' +
|
||||
' 0.1\n' +
|
||||
' > My.foo({})\n' +
|
||||
' NaN\n' +
|
||||
'@*' + '/\n' +
|
||||
'My.foo = function(item) {\n' +
|
||||
' return item.bar / item.baz;\n' +
|
||||
'}'
|
||||
'};'
|
||||
);
|
||||
</script>
|
||||
> Ox.test.doc[0].name
|
||||
|
@ -64,6 +70,8 @@ Ox.doc <f> Generates documentation for annotated JavaScript
|
|||
['number']
|
||||
> Ox.test.doc[1].usage[0].summary
|
||||
'Bar per baz, or NaN'
|
||||
> Ox.test.doc[1].tests[1]
|
||||
{expected: 'NaN', statement: 'My.foo({})'}
|
||||
@*/
|
||||
Ox.doc = (function() {
|
||||
var re = {
|
||||
|
@ -127,12 +135,12 @@ Ox.doc = (function() {
|
|||
item.usage.push(parseNode(node));
|
||||
} else if (subitem.types[0] == 'event') {
|
||||
item.events = item.events || [];
|
||||
item.events.push(parseNode(node));
|
||||
item.events.push(parseNode(node));
|
||||
} else {
|
||||
key = item.types[0] == 'function'
|
||||
? 'arguments' : 'properties'
|
||||
item[key] = item[key] || [];
|
||||
item[key].push(parseNode(node));
|
||||
item[key].push(parseNode(node));
|
||||
}
|
||||
} else {
|
||||
item.description = item.description
|
||||
|
@ -203,14 +211,14 @@ Ox.doc = (function() {
|
|||
section = tree.line.split(' ')[0]
|
||||
}
|
||||
});
|
||||
return items;
|
||||
return items;
|
||||
}
|
||||
function parseTest(string) {
|
||||
// fixme: we cannot properly handle tests where a string contains '\n '
|
||||
var lines = decodeLinebreaks(string).split('\n ');
|
||||
return {
|
||||
statement: lines[0].slice(2),
|
||||
result: lines[1].trim()
|
||||
expected: lines[1].trim()
|
||||
};
|
||||
}
|
||||
function parseTokens(tokens, includeLeadingLinebreaks) {
|
||||
|
@ -311,18 +319,22 @@ Ox.doc = (function() {
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
return function(/* source | file, callback | files, callback*/) {
|
||||
var source = arguments.length == 1 ? arguments[0] : void 0,
|
||||
files = arguments.length == 2 ? Ox.makeArray(arguments[0]) : void 0,
|
||||
callback = arguments[1],
|
||||
counter = 0, items = [];
|
||||
files && files.forEach(function(file) {
|
||||
Ox.get(file, function(source) {
|
||||
items = items.concat(parseSource(source, file.split('?')[0]));
|
||||
++counter == files.length && callback(items);
|
||||
});
|
||||
});
|
||||
return source ? parseSource(source) : void 0;
|
||||
return function(argument, callback) {
|
||||
var counter = 0, items = [], ret;
|
||||
if (arguments.length == 1) {
|
||||
ret = parseSource(argument);
|
||||
} else {
|
||||
argument = Ox.makeArray(argument);
|
||||
argument.forEach(function(file) {
|
||||
Ox.get(file, function(source) {
|
||||
items = items.concat(
|
||||
parseSource(source, file.split('?')[0])
|
||||
);
|
||||
++counter == argument.length && callback(items);
|
||||
});
|
||||
})
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}());
|
||||
|
||||
|
@ -567,91 +579,128 @@ Ox.minify = function() {
|
|||
|
||||
/*@
|
||||
Ox.test <f> Takes JavaScript, runs inline tests, returns results
|
||||
(source, callback) -> <[o]> Array of results
|
||||
(file, callback) -> <u> undefined
|
||||
(files, callback) -> <u> undefines
|
||||
file <s> Path to JavaScript file
|
||||
files <[s]> List of paths to J
|
||||
(files, callback) -> <u> undefined
|
||||
(doc, callback) -> <u> undefined
|
||||
(docs, callback) -> <u> undefined
|
||||
source <s> JavaScript source
|
||||
file <s> JavaScript file
|
||||
files <[s]> Array of JavaScript files
|
||||
doc <o> Documentation object (as returned by Ox.doc)
|
||||
docs <[o]> Array of documentation objects (as returned by Ox.doc)
|
||||
callback <f> Callback function
|
||||
results [<o>] Array of results
|
||||
results <[o]> Array of results
|
||||
actual <s> Actual result
|
||||
expected <s> Expected result
|
||||
name <s> Item name
|
||||
section <s> Section in the file
|
||||
section <s|u> Section in the file
|
||||
statement <s> Test statement
|
||||
passed <b> True if actual result and expected result are equal
|
||||
<script>
|
||||
Ox.test.foo = function(item) {
|
||||
return item.bar / item.baz;
|
||||
};
|
||||
Ox.test.source =
|
||||
'/*@\n'+
|
||||
'Ox.test.foo <f> Returns an items\'s bar per baz\n' +
|
||||
' Bar per baz is a good indicator of an item\'s foo-ness.\n' +
|
||||
' (item) -> <n> Bar per baz, or NaN\n' +
|
||||
' item <o> Any item\n' +
|
||||
' > Ox.test.foo({bar: 1, baz: 10})\n' +
|
||||
' 0.1\n' +
|
||||
' > Ox.test.foo({})\n' +
|
||||
' NaN\n' +
|
||||
'@*' + '/\n' +
|
||||
'Ox.test.foo = function(item) {\n' +
|
||||
' return item.bar / item.baz;\n' +
|
||||
'};';
|
||||
</script>
|
||||
> Ox.test(Ox.test.source, function(r) { Ox.test(r[0].passed, true); })
|
||||
undefined
|
||||
@*/
|
||||
Ox.test = function(file, callback) {
|
||||
var regexp = /(Ox\.test\()/;
|
||||
if (arguments.length == 2) {
|
||||
Ox.doc(file, function(items) {
|
||||
var results = [];
|
||||
file = file.split('?')[0];
|
||||
Ox.test.data[file] = {
|
||||
callback: callback,
|
||||
done: false,
|
||||
results: [],
|
||||
tests: {}
|
||||
};
|
||||
items.forEach(function(item) {
|
||||
item.tests && item.tests.some(function(test) {
|
||||
return test.result;
|
||||
}) && item.tests.forEach(function(test) {
|
||||
var actual, isAsync = regexp.test(test.statement);
|
||||
if (isAsync) {
|
||||
Ox.test.data[file].tests[item.name] = {
|
||||
section: item.section,
|
||||
statement: test.statement
|
||||
};
|
||||
test.statement = test.statement.replace(
|
||||
regexp, '$1\'' + item.name + '\', '
|
||||
);
|
||||
}
|
||||
if (test.result || test.statement.match(/Ox\.test/)) {
|
||||
// don't eval script tags without assignment to Ox.test.foo
|
||||
actual = eval(test.statement);
|
||||
Ox.Log('TEST', test.statement);
|
||||
}
|
||||
if (!isAsync && test.result) {
|
||||
Ox.test.data[file].results.push({
|
||||
actual: JSON.stringify(actual),
|
||||
expected: test.result,
|
||||
name: item.name,
|
||||
section: item.section,
|
||||
statement: test.statement,
|
||||
passed: Ox.isEqual(eval(
|
||||
'(' + test.result + ')'
|
||||
), actual)
|
||||
});
|
||||
}
|
||||
});
|
||||
Ox.test = function(argument, callback) {
|
||||
Ox.print('Ox.test', argument, '----------------------------------')
|
||||
function runTests(items) {
|
||||
var id = Ox.uid(), regexp = /(.+Ox\.test\()/, results = [];
|
||||
Ox.test.data[id] = {
|
||||
callback: callback,
|
||||
done: false,
|
||||
results: results,
|
||||
tests: {}
|
||||
};
|
||||
items.forEach(function(item) {
|
||||
item.tests && item.tests.some(function(test) {
|
||||
return test.expected;
|
||||
}) && item.tests.forEach(function(test) {
|
||||
var actual, isAsync = regexp.test(test.statement);
|
||||
if (isAsync) {
|
||||
Ox.test.data[id].tests[test.statement] = {
|
||||
name: item.name,
|
||||
section: item.section
|
||||
};
|
||||
Ox.Log('TEST', 'XXX', test.statement);
|
||||
test.statement = test.statement.replace(
|
||||
regexp,
|
||||
"$1'" + test.statement.replace(/'/g, "\\'") + "', "
|
||||
);
|
||||
}
|
||||
if (test.expected || test.statement.match(/Ox\.test\./)) {
|
||||
// don't eval script tags without assignment to Ox.test.foo
|
||||
Ox.Log('TEST', test.statement);
|
||||
actual = eval(test.statement);
|
||||
}
|
||||
if (!isAsync && test.expected) {
|
||||
Ox.test.data[id].results.push({
|
||||
actual: JSON.stringify(actual),
|
||||
expected: test.expected,
|
||||
name: item.name,
|
||||
section: item.section,
|
||||
statement: test.statement,
|
||||
passed: Ox.isEqual(
|
||||
actual, eval('(' + test.expected + ')')
|
||||
)
|
||||
});
|
||||
}
|
||||
});
|
||||
Ox.test.data[file].done = true;
|
||||
if (Ox.isEmpty(Ox.test.data[file].tests)) {
|
||||
callback(Ox.test.data[file].results);
|
||||
}
|
||||
});
|
||||
Ox.test.data[id].done = true;
|
||||
if (Ox.isEmpty(Ox.test.data[id].tests)) {
|
||||
callback(Ox.test.data[id].results);
|
||||
}
|
||||
}
|
||||
if (arguments.length == 2) {
|
||||
if (Ox.typeOf(argument) == 'string' && Ox.contains(argument, '\n')) {
|
||||
runTests(Ox.doc(argument))
|
||||
} else {
|
||||
argument = Ox.makeArray(argument);
|
||||
if (Ox.typeOf(argument[0]) == 'string') {
|
||||
Ox.doc(argument, runTests);
|
||||
} else {
|
||||
runTests(argument);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var name = arguments[0],
|
||||
var statement = arguments[0],
|
||||
result = arguments[1],
|
||||
expected = arguments[2];
|
||||
file = null;
|
||||
expected = arguments[2],
|
||||
id, test;
|
||||
Ox.forEach(Ox.test.data, function(v, k) {
|
||||
if (v.tests[name]) {
|
||||
file = k;
|
||||
if (v.tests[statement]) {
|
||||
id = k;
|
||||
test = v.tests[statement];
|
||||
Ox.Break();
|
||||
}
|
||||
});
|
||||
Ox.test.data[file].results.push({
|
||||
Ox.test.data[id].results.push(Ox.extend(test, {
|
||||
actual: result,
|
||||
expected: expected,
|
||||
name: name,
|
||||
section: Ox.test.data[file].tests[name].section,
|
||||
statement: Ox.test.data[file].tests[name].statement,
|
||||
statement: statement,
|
||||
passed: Ox.isEqual(result, expected)
|
||||
});
|
||||
delete Ox.test.data[file].tests[name];
|
||||
if (Ox.test.data[file].done && Ox.isEmpty(Ox.test.data[file].tests)) {
|
||||
Ox.test.data[file].callback(Ox.test.data[file].results);
|
||||
}));
|
||||
delete Ox.test.data[id].tests[statement];
|
||||
if (Ox.test.data[id].done && Ox.isEmpty(Ox.test.data[id].tests)) {
|
||||
Ox.test.data[id].callback(Ox.test.data[id].results);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -663,10 +712,11 @@ Ox.tokenize <f> Tokenizes JavaScript
|
|||
column <n> Column of the token
|
||||
line <n> Line of the token
|
||||
type <s> Type of the token
|
||||
Type can be <code>"comment"</code>, <code>"identifier"</code>,
|
||||
<code>"linebreak"</code>, <code>"number"</code>,
|
||||
<code>"operator"</code>, <code>"regexp"</code>,
|
||||
<code>"string"</code> or <code>"whitespace"</code>
|
||||
Type can be <code>"comment"</code>, <code>"error"</code>,
|
||||
<code>"identifier"</code>, <code>"linebreak"</code>,
|
||||
<code>"number"</code>, <code>"operator"</code>,
|
||||
<code>"regexp"</code>, <code>"string"</code> or
|
||||
<code>"whitespace"</code>
|
||||
value <s> Value of the token
|
||||
source <s> JavaScript source code
|
||||
> Ox.tokenize('// comment\nvar foo = bar / baz;').length
|
||||
|
@ -790,10 +840,20 @@ Ox.tokenize = (function() {
|
|||
type = 'whitespace';
|
||||
while (whitespace.indexOf(source[++cursor]) > -1) {}
|
||||
} else {
|
||||
break;
|
||||
type = 'error';
|
||||
++cursor;
|
||||
}
|
||||
value = source.slice(start, cursor);
|
||||
tokens.push({column: column, line: line, type: type, value: value});
|
||||
if (
|
||||
type == 'error' && tokens.length
|
||||
&& tokens[tokens.length - 1].type == 'error'
|
||||
) {
|
||||
tokens[tokens.length - 1].value += value;
|
||||
} else {
|
||||
tokens.push(
|
||||
{column: column, line: line, type: type, value: value}
|
||||
);
|
||||
}
|
||||
if (type == 'comment') {
|
||||
lines = value.split('\n');
|
||||
column = lines[lines.length - 1].length;
|
||||
|
|
Loading…
Reference in a new issue