-
Notifications
You must be signed in to change notification settings - Fork 9
/
mocha.js
112 lines (93 loc) · 3.42 KB
/
mocha.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
'use strict';
var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var jsdoctest = require('./index');
var getExampleCode = require('./get-example-code');
var util = require('./util');
var escapeString = getExampleCode.escapeString;
/**
* Mocks `mocha`'s register environment for doctest mocha integration. This
* works in the same manner `coffee-script/register` or `mocha --require
* blanket` work.
*/
exports.loadDoctests = function loadDoctests(module, filename) {
require('should');
var rootDir = process.cwd();
var content = fs.readFileSync(filename, 'utf8');
var mochaSpec = exports.contentsToMochaSpec(rootDir, filename, content);
module._compile(util.stripBOM(content + mochaSpec), filename);
};
/**
* Compiles a string containing the contents of a JSDoc annotated file and
* outputs the generated mocha spec for its JSDocTests.
*/
exports.contentsToMochaSpec =
function contentsToMochaSpec(rootDir, filename, content) {
var comments = jsdoctest.getJsdoctests(content);
var moduleName = exports._getModuleName(rootDir, filename, comments.source);
return '\ndescribe(\'' + escapeString(moduleName) + '\', function() {' +
_.map(_.compact(comments), function(comment) {
return exports.commentToMochaSpec(comment);
}).join('') +
'});';
};
/**
* Compiles a jsdoc comment parsed by `dox` and its doctest examples into a
* mocha spec.
*/
exports.commentToMochaSpec = function commentToMochaSpec(comment) {
var ctx = comment.ctx || {};
return '\ndescribe(\'' + escapeString(ctx.string) + '\', function() {' +
_.map(comment.examples, function(example) {
return 'it(\'' + escapeString(example.label || example.displayTestCase) +
'\', function(' + (example.isAsync ? 'done' : '') + ') {' +
getExampleCode(example) +
'});';
}).join('\n') +
'});';
};
var originalLoad;
/**
* Toggles doctest injection into loaded modules. That is: doctests will be
* compiled into modules as mocha specs, whenever they're declared.
*/
exports.toggleDoctestInjection = function toggleDoctestInjection() {
if(originalLoad) {
require.extensions['.js'] = originalLoad;
} else {
originalLoad = originalLoad || require.extensions['.js'];
require.extensions['.js'] = function(module, filename) {
if(filename.match(/node_modules/)) {
return originalLoad(module, filename);
}
return exports.loadDoctests(module, filename);
};
}
};
/**
* Resolves the expected module name for a given file, to use as the top-level
* spec when generating mocha doctest `describes`
*
* @param {String} The root directory
* @param {String} The module's filename
* @return {String} moduleName
*/
exports._getModuleName = function getModuleName(rootDir, filename, parsedContent) {
var moduleBlock = _.find(parsedContent, function(block) {
return block.tags && _.find(block.tags, { type: 'module' });
});
if(moduleBlock) {
var moduleTag = _.find(moduleBlock.tags, { type: 'module' });
if(moduleTag && moduleTag.string) {
var smoduleTag = moduleTag.string.split(' ');
if(smoduleTag[0].charAt(0) === '{' && !!smoduleTag[1]) return smoduleTag[1];
else if(!!smoduleTag[0]) return smoduleTag[0];
}
}
var filenamePrime = path.relative(rootDir, filename);
return stripExtension(filenamePrime);
function stripExtension(f) {
return f.replace(/\..+$/, '');
}
};