Skip to content

Commit

Permalink
Support karma-ava
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jamestalmage authored and sindresorhus committed Aug 6, 2016
1 parent 01a110e commit 204f2be
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 133 deletions.
17 changes: 2 additions & 15 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
'use strict';
var path = require('path');
var chalk = require('chalk');
var process = require('./lib/process-adapter');
var serializeError = require('./lib/serialize-error');
var globals = require('./lib/globals');
var Runner = require('./lib/runner');
var send = require('./lib/send');
var send = process.send;

var opts = globals.options;
var runner = new Runner({
Expand All @@ -13,18 +12,6 @@ var runner = new Runner({
match: opts.match
});

// check if the test is being run without AVA cli
var isForked = typeof process.send === 'function';

if (!isForked) {
var fp = path.relative('.', process.argv[1]);

console.log();
console.error('Test files must be run with the AVA CLI:\n\n ' + chalk.grey.dim('$') + ' ' + chalk.cyan('ava ' + fp) + '\n');

process.exit(1); // eslint-disable-line xo/no-process-exit
}

// note that test files have require('ava')
require('./lib/test-worker').avaRequired = true;

Expand Down
25 changes: 14 additions & 11 deletions lib/fork.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ var objectAssign = require('object-assign');
var Promise = require('bluebird');
var debug = require('debug')('ava');
var AvaError = require('./ava-error');
var doSend = require('./send');

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

var exiting = false;
var send = function (ps, name, data) {
var send = function (name, data) {
if (!exiting) {
// This seems to trigger a Node bug which kills the AVA master process, at
// least while running AVA's tests. See
// <https://github.com/novemberborn/_ava-tap-crash> for more details.
doSend(ps, name, data);
ps.send({
name: 'ava-' + name,
data: data,
ava: true
});
}
};

Expand Down Expand Up @@ -86,7 +89,7 @@ module.exports = function (file, opts) {
ps.on('results', function (data) {
results = data;
data.tests = testResults;
send(ps, 'teardown');
send('teardown');
});

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

ps.on('no-tests', function (data) {
send(ps, 'teardown');
send('teardown');

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

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

// teardown finished, now exit
ps.on('teardown', function () {
send(ps, 'exit');
send('exit');
exiting = true;
});

// uncaught exception in fork, need to exit
ps.on('uncaughtException', function () {
send(ps, 'teardown');
send('teardown');
});

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

promise.send = function (name, data) {
send(ps, name, data);
send(name, data);

return promise;
};

promise.exit = function () {
send(ps, 'init-exit');
send('init-exit');

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

promise.run = function (options) {
if (isReady) {
send(ps, 'run', options);
send('run', options);
return promise;
}

ps.on('stats', function () {
send(ps, 'run', options);
send('run', options);
});

return promise;
Expand Down
25 changes: 25 additions & 0 deletions lib/prefix-title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict';
var path = require('path');

module.exports = function (file, base, separator) {
var prefix = file
.replace(base, function (match, offset) {
// only replace this.base if it is found at the start of the path
return offset === 0 ? '' : match;
})
.replace(/\.spec/, '')
.replace(/\.test/, '')
.replace(/test\-/g, '')
.replace(/\.js$/, '')
.split(path.sep)
.filter(function (p) {
return p !== '__tests__';
})
.join(separator);

if (prefix.length > 0) {
prefix += separator;
}

return prefix;
};
107 changes: 107 additions & 0 deletions lib/process-adapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
'use strict';
var fs = require('fs');
var path = require('path');
var chalk = require('chalk');
var sourceMapSupport = require('source-map-support');
var installPrecompiler = require('require-precompiled');

var debug = require('debug')('ava');

// check if the test is being run without AVA cli
var isForked = typeof process.send === 'function';

if (!isForked) {
var fp = path.relative('.', process.argv[1]);

console.log();
console.error('Test files must be run with the AVA CLI:\n\n ' + chalk.grey.dim('$') + ' ' + chalk.cyan('ava ' + fp) + '\n');

process.exit(1); // eslint-disable-line xo/no-process-exit
}

exports.send = function (name, data) {
process.send({
name: 'ava-' + name,
data: data,
ava: true
});
};

exports.on = process.on.bind(process);
exports.emit = process.emit.bind(process);
exports.exit = process.exit.bind(process);
exports.env = process.env;

var opts = exports.opts = JSON.parse(process.argv[2]);

// Fake TTY support
if (opts.tty) {
process.stdout.isTTY = true;
process.stdout.columns = opts.tty.columns || 80;
process.stdout.rows = opts.tty.rows;

var tty = require('tty');
var isatty = tty.isatty;

tty.isatty = function (fd) {
if (fd === 1 || fd === process.stdout) {
return true;
}

return isatty(fd);
};
}

if (debug.enabled) {
// Forward the `time-require` `--sorted` flag.
// Intended for internal optimization tests only.
if (opts._sorted) {
process.argv.push('--sorted');
}

require('time-require');
}

var sourceMapCache = Object.create(null);
var cacheDir = opts.cacheDir;

exports.installSourceMapSupport = function () {
sourceMapSupport.install({
environment: 'node',
handleUncaughtExceptions: false,
retrieveSourceMap: function (source) {
if (sourceMapCache[source]) {
return {
url: source,
map: fs.readFileSync(sourceMapCache[source], 'utf8')
};
}
}
});
};

exports.installPrecompilerHook = function () {
installPrecompiler(function (filename) {
var precompiled = opts.precompiled[filename];

if (precompiled) {
sourceMapCache[filename] = path.join(cacheDir, precompiled + '.js.map');
return fs.readFileSync(path.join(cacheDir, precompiled + '.js'), 'utf8');
}

return null;
});
};

exports.installDependencyTracking = function (dependencies, testPath) {
Object.keys(require.extensions).forEach(function (ext) {
var wrappedHandler = require.extensions[ext];
require.extensions[ext] = function (module, filename) {
if (filename !== testPath) {
dependencies.push(filename);
}

wrappedHandler(module, filename);
};
});
};
23 changes: 2 additions & 21 deletions lib/run-status.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use strict';
var EventEmitter = require('events').EventEmitter;
var path = require('path');
var util = require('util');
var chalk = require('chalk');
var isObj = require('is-obj');
var flatten = require('arr-flatten');
var figures = require('figures');
var prefixTitle = require('./prefix-title');

function RunStatus(opts) {
if (!(this instanceof RunStatus)) {
Expand Down Expand Up @@ -128,26 +128,7 @@ RunStatus.prototype.prefixTitle = function (file) {

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

var prefix = path.relative('.', file)
.replace(this.base, function (match, offset) {
// only replace this.base if it is found at the start of the path
return offset === 0 ? '' : match;
})
.replace(/\.spec/, '')
.replace(/\.test/, '')
.replace(/test\-/g, '')
.replace(/\.js$/, '')
.split(path.sep)
.filter(function (p) {
return p !== '__tests__';
})
.join(separator);

if (prefix.length > 0) {
prefix += separator;
}

return prefix;
return prefixTitle(file, this.base, separator);
};

RunStatus.prototype.handleOutput = function (channel, data) {
Expand Down
16 changes: 0 additions & 16 deletions lib/send.js

This file was deleted.

0 comments on commit 204f2be

Please sign in to comment.