Skip to content

Commit 1a64009

Browse files
author
cloudhead
committed
bin/vows, autotesting utility
1 parent 051bb40 commit 1a64009

File tree

1 file changed

+180
-0
lines changed

1 file changed

+180
-0
lines changed

bin/vows

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
#!/usr/bin/env node
2+
3+
var path = require('path'),
4+
sys = require('sys'),
5+
fs = require('fs'),
6+
exec = require('child_process').exec,
7+
Script = process.binding('evals').Script;
8+
9+
require.paths.unshift(path.join(__dirname, '..', 'lib'));
10+
11+
var argv = [], options = {
12+
matcher: /.*/,
13+
brief: false
14+
};
15+
16+
//
17+
// Parse command-line parameters
18+
//
19+
for (var i = 0, arg; i < process.argv.length; i++) {
20+
arg = process.argv[i];
21+
22+
if (arg === __filename) { continue }
23+
24+
if (arg[0] !== '-') {
25+
argv.push(arg);
26+
} else {
27+
arg = arg.match(/^--?(.*)/)[1];
28+
29+
if (arg[0] === 'R') {
30+
options.matcher = new(RegExp)(arg.slice(1));
31+
} else if (arg in options) {
32+
options[arg] = true;
33+
}
34+
}
35+
}
36+
37+
// Get rid of process runner
38+
// ('node' in most cases)
39+
argv = argv.slice(1);
40+
41+
var vows = require('vows').config(options);
42+
43+
if (argv.length > 0) {
44+
argv.forEach(function (arg) {
45+
runTest(arg);
46+
});
47+
} else {
48+
//
49+
// Watch mode
50+
//
51+
vows.options.brief = true;
52+
53+
(function () {
54+
var clock = [
55+
'. ', '.. ', '... ', ' ...',
56+
' ..', ' .', ' .', ' ..',
57+
'... ', '.. ', '. '
58+
];
59+
var current = 0,
60+
status = 0,
61+
runningTests = false,
62+
statusText = '',
63+
colors = ['\033[32m', '\033[33m', '\033[91m'],
64+
timer = setInterval(tick, 100);
65+
66+
cursorHide();
67+
68+
// Run every 100ms
69+
function tick() {
70+
cursorSave();
71+
eraseLine();
72+
print(colors[status]);
73+
print(clock[current]);
74+
75+
if (runningTests) {
76+
print(' \033[39mrunning tests...');
77+
} else {
78+
print(' ' + statusText);
79+
}
80+
81+
print('\033[39m');
82+
cursorRestore();
83+
current = (current == clock.length - 1) ? 0 : current + 1;
84+
}
85+
86+
//
87+
// Utility functions
88+
//
89+
function print(str) { process.stdout.write(str) }
90+
function eraseLine() { print("\033[2K") }
91+
function cursorSave() { print("\033[s") }
92+
function cursorRestore() { print("\033[u") }
93+
function cursorHide() { print("\033[?25l") }
94+
function cursorShow() { print("\033[?25h") }
95+
function cleanup() { cursorShow(), print('\n') }
96+
97+
//
98+
// Called when a file has been modified.
99+
// Run the matching tests and change the status.
100+
//
101+
function changed(file) {
102+
runningTests = true;
103+
runTest("test/" + file + "-test.js").addListener('end', function (h, b, e) {
104+
runningTests = false;
105+
statusText = h + " honored, " +
106+
b + " broken, " +
107+
e + " errored";
108+
109+
if (b || e) {
110+
eraseLine();
111+
status = e ? 2 : 1;
112+
} else {
113+
status = 0;
114+
}
115+
});
116+
}
117+
//
118+
// Recursively traverse a hierarchy, returning
119+
// a list of all relevant .js files.
120+
//
121+
function paths(dir) {
122+
var paths = [];
123+
124+
try { fs.statSync(dir) }
125+
catch (e) { return [] }
126+
127+
(function traverse(dir, stack) {
128+
stack.push(dir);
129+
fs.readdirSync(stack.join('/')).forEach(function (file) {
130+
var path = stack.concat([file]).join('/'),
131+
stat = fs.statSync(path);
132+
133+
if (file[0] == '.' || file === 'vendor') {
134+
return;
135+
} else if (stat.isFile() && /\.js$/.test(file)) {
136+
paths.push(path);
137+
} else if (stat.isDirectory()) {
138+
traverse(file, stack);
139+
}
140+
});
141+
stack.pop();
142+
})(dir || '.', []);
143+
144+
return paths;
145+
}
146+
147+
//
148+
// Watch all relevant files in lib/ and src/,
149+
// and call `changed()` on change.
150+
//
151+
paths('lib').concat(paths('src')).forEach(function (p) {
152+
fs.watchFile(p, function (current, previous) {
153+
if (new(Date)(current.mtime).valueOf() ===
154+
new(Date)(previous.mtime).valueOf()) { return }
155+
else {
156+
changed(path.basename(p, '.js'));
157+
}
158+
});
159+
});
160+
161+
process.addListener('exit', cleanup);
162+
process.addListener('SIGINT', function () {
163+
cleanup();
164+
process.exit();
165+
});
166+
process.addListener('SIGQUIT', function () {
167+
changed();
168+
});
169+
})();
170+
}
171+
172+
function runTest(file) {
173+
var code = (function (require, __filename, __dirname) {
174+
/* content */
175+
}).toString().replace('/* content */', fs.readFileSync(file));
176+
177+
return Script.runInThisContext('(' + code + ')', file)
178+
.call(global, require, file, path.dirname(file));
179+
}
180+

0 commit comments

Comments
 (0)