-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathindex.js
122 lines (98 loc) · 3.3 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
'use strict';
var fs = require('fs');
var path = require('path');
var dox = require('dox');
var _ = require('lodash');
var commentParser = require('./comment-parser');
var getExampleCode = require('./get-example-code');
var util = require('./util');
var escapeString = getExampleCode.escapeString;
var JSDOCTEST_DISABLE = process.env.JSDOCTEST_DISABLE || false;
/**
* Runs jsdoctests in some file, and reports the results to the command-line.
*/
exports.run = function jsdoctest$run(filename) {
require('should');
var content = fs.readFileSync(filename, 'utf8');
var jsdocTests = exports.getJsdoctests(content);
content += _.map(jsdocTests, exports.toJsdocRegister).join('');
global.__registerTest = exports.registerTest;
module._compile(util.stripBOM(content), filename);
delete global.__registerTest;
return exports.runRegistered();
};
/**
* Parses "jsdoctests" out of a file's contents and returns them. These are
* `dox` outputted `comment` nodes, overloaded with an `examples` field which
* adds `testCase` and `expectedResult` pairs to them.
*/
exports.getJsdoctests = function jsdoctest$getJsdoctests(content) {
var parsedContent = dox.parseComments(content);
var functionComments = _.filter(parsedContent, function(c) {
return c.ctx && (c.ctx.type === 'method' || c.ctx.type === 'function');
});
var comments = _.map(functionComments, function(comment) {
var exampleNodes = _.filter(comment.tags, { type: 'example' });
var examples = _.flatten(_.map(exampleNodes, function(exampleNode) {
return commentParser.run(exampleNode.string);
}));
comment.examples = examples;
return examples.length ? comment : undefined;
});
var ret = _.compact(comments);
ret.source = parsedContent;
return ret;
};
var tests = [];
/**
* Registers a test case to be run by the runner
*/
exports.registerTest = function jsdoctest$registerTest(id, fn) {
tests.push({
id: id,
fn: fn,
});
};
/**
* Runs test cases accumulated in the `tests` array.
*/
exports.runRegistered = function() {
var failed = false;
_.each(tests, function(test) {
console.log(test.id);
try {
test.fn();
} catch(err) {
console.error(err.toString());
failed = true;
}
});
return failed;
};
/**
* Compiles a jsdoc comment `dox` comment overloaded with the `examples` node to
* the internal test suite registering code.
*/
exports.toJsdocRegister = function jsdoctest$toJsdocRegister(comment) {
var baseId = comment.ctx.name + ' - ';
var compiled = _.map(comment.examples, function(example) {
var id = escapeString(baseId) +
escapeString(example.testCase) + ' => ' +
escapeString(example.expectedResult);
var fn = 'function() {' + example.testCode + '}';
return '__registerTest(\'' + id + '\', ' + fn + ');';
}).join('');
return '\n' + compiled;
};
// Mocha `--require` support:
if(path.basename(process.argv[1]) === '_mocha' && !JSDOCTEST_DISABLE) {
var mocha = require('./mocha');
// Avoid circular require weirdness
if(module.parent.exports === mocha) {
// We could just always delete the cache, but I think this is clearer and
// shows explicitly what the circular problem is
delete require.cache[path.join(__dirname, 'mocha.js')];
mocha = require('./mocha');
}
mocha.toggleDoctestInjection();
}