Skip to content

Commit 204f2be

Browse files
jamestalmagesindresorhus
authored andcommitted
Support karma-ava
closes #942 This does a few things: - Moves anything used in child processes that the browser can't replicate into `lib/process-adapter.js` (so that browser implementations can implement that missing functionality). - Separates out `prefix-title` so `karma-ava` can use it. It enables use of [`karma-ava`](https://github.com/avajs/karma-ava), which is very preliminary right now, but does work: https://cloud.githubusercontent.com/assets/4082216/16401095/75720328-3caf-11e6-950d-27a9e48bbf9a.png -- This also includes two commits from #896
1 parent 01a110e commit 204f2be

File tree

7 files changed

+156
-133
lines changed

7 files changed

+156
-133
lines changed

index.js

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
'use strict';
2-
var path = require('path');
3-
var chalk = require('chalk');
2+
var process = require('./lib/process-adapter');
43
var serializeError = require('./lib/serialize-error');
54
var globals = require('./lib/globals');
65
var Runner = require('./lib/runner');
7-
var send = require('./lib/send');
6+
var send = process.send;
87

98
var opts = globals.options;
109
var runner = new Runner({
@@ -13,18 +12,6 @@ var runner = new Runner({
1312
match: opts.match
1413
});
1514

16-
// check if the test is being run without AVA cli
17-
var isForked = typeof process.send === 'function';
18-
19-
if (!isForked) {
20-
var fp = path.relative('.', process.argv[1]);
21-
22-
console.log();
23-
console.error('Test files must be run with the AVA CLI:\n\n ' + chalk.grey.dim('$') + ' ' + chalk.cyan('ava ' + fp) + '\n');
24-
25-
process.exit(1); // eslint-disable-line xo/no-process-exit
26-
}
27-
2815
// note that test files have require('ava')
2916
require('./lib/test-worker').avaRequired = true;
3017

lib/fork.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ var objectAssign = require('object-assign');
66
var Promise = require('bluebird');
77
var debug = require('debug')('ava');
88
var AvaError = require('./ava-error');
9-
var doSend = require('./send');
109

1110
if (fs.realpathSync(__filename) !== __filename) {
1211
console.warn(
@@ -50,12 +49,16 @@ module.exports = function (file, opts) {
5049
var relFile = path.relative('.', file);
5150

5251
var exiting = false;
53-
var send = function (ps, name, data) {
52+
var send = function (name, data) {
5453
if (!exiting) {
5554
// This seems to trigger a Node bug which kills the AVA master process, at
5655
// least while running AVA's tests. See
5756
// <https://github.com/novemberborn/_ava-tap-crash> for more details.
58-
doSend(ps, name, data);
57+
ps.send({
58+
name: 'ava-' + name,
59+
data: data,
60+
ava: true
61+
});
5962
}
6063
};
6164

@@ -86,7 +89,7 @@ module.exports = function (file, opts) {
8689
ps.on('results', function (data) {
8790
results = data;
8891
data.tests = testResults;
89-
send(ps, 'teardown');
92+
send('teardown');
9093
});
9194

9295
ps.on('exit', function (code, signal) {
@@ -106,7 +109,7 @@ module.exports = function (file, opts) {
106109
});
107110

108111
ps.on('no-tests', function (data) {
109-
send(ps, 'teardown');
112+
send('teardown');
110113

111114
var message = 'No tests found in ' + relFile;
112115

@@ -120,13 +123,13 @@ module.exports = function (file, opts) {
120123

121124
// teardown finished, now exit
122125
ps.on('teardown', function () {
123-
send(ps, 'exit');
126+
send('exit');
124127
exiting = true;
125128
});
126129

127130
// uncaught exception in fork, need to exit
128131
ps.on('uncaughtException', function () {
129-
send(ps, 'teardown');
132+
send('teardown');
130133
});
131134

132135
ps.stdout.on('data', function (data) {
@@ -144,13 +147,13 @@ module.exports = function (file, opts) {
144147
};
145148

146149
promise.send = function (name, data) {
147-
send(ps, name, data);
150+
send(name, data);
148151

149152
return promise;
150153
};
151154

152155
promise.exit = function () {
153-
send(ps, 'init-exit');
156+
send('init-exit');
154157

155158
return promise;
156159
};
@@ -164,12 +167,12 @@ module.exports = function (file, opts) {
164167

165168
promise.run = function (options) {
166169
if (isReady) {
167-
send(ps, 'run', options);
170+
send('run', options);
168171
return promise;
169172
}
170173

171174
ps.on('stats', function () {
172-
send(ps, 'run', options);
175+
send('run', options);
173176
});
174177

175178
return promise;

lib/prefix-title.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
var path = require('path');
3+
4+
module.exports = function (file, base, separator) {
5+
var prefix = file
6+
.replace(base, function (match, offset) {
7+
// only replace this.base if it is found at the start of the path
8+
return offset === 0 ? '' : match;
9+
})
10+
.replace(/\.spec/, '')
11+
.replace(/\.test/, '')
12+
.replace(/test\-/g, '')
13+
.replace(/\.js$/, '')
14+
.split(path.sep)
15+
.filter(function (p) {
16+
return p !== '__tests__';
17+
})
18+
.join(separator);
19+
20+
if (prefix.length > 0) {
21+
prefix += separator;
22+
}
23+
24+
return prefix;
25+
};

lib/process-adapter.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
'use strict';
2+
var fs = require('fs');
3+
var path = require('path');
4+
var chalk = require('chalk');
5+
var sourceMapSupport = require('source-map-support');
6+
var installPrecompiler = require('require-precompiled');
7+
8+
var debug = require('debug')('ava');
9+
10+
// check if the test is being run without AVA cli
11+
var isForked = typeof process.send === 'function';
12+
13+
if (!isForked) {
14+
var fp = path.relative('.', process.argv[1]);
15+
16+
console.log();
17+
console.error('Test files must be run with the AVA CLI:\n\n ' + chalk.grey.dim('$') + ' ' + chalk.cyan('ava ' + fp) + '\n');
18+
19+
process.exit(1); // eslint-disable-line xo/no-process-exit
20+
}
21+
22+
exports.send = function (name, data) {
23+
process.send({
24+
name: 'ava-' + name,
25+
data: data,
26+
ava: true
27+
});
28+
};
29+
30+
exports.on = process.on.bind(process);
31+
exports.emit = process.emit.bind(process);
32+
exports.exit = process.exit.bind(process);
33+
exports.env = process.env;
34+
35+
var opts = exports.opts = JSON.parse(process.argv[2]);
36+
37+
// Fake TTY support
38+
if (opts.tty) {
39+
process.stdout.isTTY = true;
40+
process.stdout.columns = opts.tty.columns || 80;
41+
process.stdout.rows = opts.tty.rows;
42+
43+
var tty = require('tty');
44+
var isatty = tty.isatty;
45+
46+
tty.isatty = function (fd) {
47+
if (fd === 1 || fd === process.stdout) {
48+
return true;
49+
}
50+
51+
return isatty(fd);
52+
};
53+
}
54+
55+
if (debug.enabled) {
56+
// Forward the `time-require` `--sorted` flag.
57+
// Intended for internal optimization tests only.
58+
if (opts._sorted) {
59+
process.argv.push('--sorted');
60+
}
61+
62+
require('time-require');
63+
}
64+
65+
var sourceMapCache = Object.create(null);
66+
var cacheDir = opts.cacheDir;
67+
68+
exports.installSourceMapSupport = function () {
69+
sourceMapSupport.install({
70+
environment: 'node',
71+
handleUncaughtExceptions: false,
72+
retrieveSourceMap: function (source) {
73+
if (sourceMapCache[source]) {
74+
return {
75+
url: source,
76+
map: fs.readFileSync(sourceMapCache[source], 'utf8')
77+
};
78+
}
79+
}
80+
});
81+
};
82+
83+
exports.installPrecompilerHook = function () {
84+
installPrecompiler(function (filename) {
85+
var precompiled = opts.precompiled[filename];
86+
87+
if (precompiled) {
88+
sourceMapCache[filename] = path.join(cacheDir, precompiled + '.js.map');
89+
return fs.readFileSync(path.join(cacheDir, precompiled + '.js'), 'utf8');
90+
}
91+
92+
return null;
93+
});
94+
};
95+
96+
exports.installDependencyTracking = function (dependencies, testPath) {
97+
Object.keys(require.extensions).forEach(function (ext) {
98+
var wrappedHandler = require.extensions[ext];
99+
require.extensions[ext] = function (module, filename) {
100+
if (filename !== testPath) {
101+
dependencies.push(filename);
102+
}
103+
104+
wrappedHandler(module, filename);
105+
};
106+
});
107+
};

lib/run-status.js

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
'use strict';
22
var EventEmitter = require('events').EventEmitter;
3-
var path = require('path');
43
var util = require('util');
54
var chalk = require('chalk');
65
var isObj = require('is-obj');
76
var flatten = require('arr-flatten');
87
var figures = require('figures');
8+
var prefixTitle = require('./prefix-title');
99

1010
function RunStatus(opts) {
1111
if (!(this instanceof RunStatus)) {
@@ -128,26 +128,7 @@ RunStatus.prototype.prefixTitle = function (file) {
128128

129129
var separator = ' ' + chalk.gray.dim(figures.pointerSmall) + ' ';
130130

131-
var prefix = path.relative('.', file)
132-
.replace(this.base, function (match, offset) {
133-
// only replace this.base if it is found at the start of the path
134-
return offset === 0 ? '' : match;
135-
})
136-
.replace(/\.spec/, '')
137-
.replace(/\.test/, '')
138-
.replace(/test\-/g, '')
139-
.replace(/\.js$/, '')
140-
.split(path.sep)
141-
.filter(function (p) {
142-
return p !== '__tests__';
143-
})
144-
.join(separator);
145-
146-
if (prefix.length > 0) {
147-
prefix += separator;
148-
}
149-
150-
return prefix;
131+
return prefixTitle(file, this.base, separator);
151132
};
152133

153134
RunStatus.prototype.handleOutput = function (channel, data) {

lib/send.js

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)