diff --git a/packages/neutrino/commands/build/index.js b/packages/neutrino/commands/build/index.js index 5c5915c..8601f6f 100644 --- a/packages/neutrino/commands/build/index.js +++ b/packages/neutrino/commands/build/index.js @@ -5,7 +5,10 @@ const DevServer = require('webpack-dev-server'); const webpack = require('webpack'); const build = (config, done) => { - webpack(config, (err, stats) => { + const compiler = webpack(config); + + + compiler.run((err, stats) => { if (!err) { console.log(stats.toString({ colors: true })); } else { @@ -20,7 +23,24 @@ const build = (config, done) => { }); }; -const watch = (config, done) => { +const watch = (config, handler, done) => { + const compiler = webpack(config); + const watcher = compiler.watch(config.watchOptions || {}, (err, stats) => { + if (!err) { + return handler(); + } + + console.error(err.stack || err); + + if (err.details) { + console.error(err.details); + } + }); + + process.on('SIGINT', () => watcher.close(done)); +}; + +const devServer = (config, done) => { const protocol = config.devServer.https ? 'https' : 'http'; const host = config.devServer.host || 'localhost'; const port = config.devServer.port || 5000; @@ -46,6 +66,9 @@ module.exports = (args, done) => { return build(config, done); } - watch(config, done); + devServer(config, done); }; +module.exports.build = build; +module.exports.devServer = devServer; +module.exports.watch = watch; diff --git a/packages/neutrino/commands/init/index.js b/packages/neutrino/commands/init/index.js index f31239a..a83533c 100644 --- a/packages/neutrino/commands/init/index.js +++ b/packages/neutrino/commands/init/index.js @@ -1,17 +1,16 @@ 'use strict'; const yeoman = require('yeoman-environment'); -const crypto = require('crypto'); const npm = require('npm'); -const os = require('os'); const path = require('path'); +const temp = require('../../src/temp'); const env = yeoman.createEnv(); module.exports = (args, done) => { // For initializing a project, the preset is not installed in the project. // Rather, we install it ourselves into a temp directory and invoke from there. - const tempDir = path.join(os.tmpdir(), crypto.randomBytes(8).toString('hex')); + const tempDir = temp(); const packageName = args.packageName; npm.load({ loglevel: 'silent' }, (err, npm) => { diff --git a/packages/neutrino/commands/test/index.js b/packages/neutrino/commands/test/index.js index a988d6b..841a932 100644 --- a/packages/neutrino/commands/test/index.js +++ b/packages/neutrino/commands/test/index.js @@ -2,9 +2,10 @@ const getPreset = require('../../src/get-preset'); const Server = require('karma').Server; +const builder = require('../build'); +const mocha = require('../../src/mocha'); -module.exports = (args, done) => { - const config = getPreset(args.options.preset); +const browser = (config, args, done) => { const karma = config.karma; delete config.karma; @@ -15,3 +16,19 @@ module.exports = (args, done) => { new Server(karma, done).start(); }; + +const node = (config, args, done) => { + args.options.watch ? + builder.watch(config, () => mocha(config), done) : + builder.build(config, () => mocha(config, done)); +}; + +module.exports = (args, done) => { + const config = getPreset(args.options.preset); + + if (config.mocha) { + node(config, args, done); + } else { + browser(config, args, done); + } +}; diff --git a/packages/neutrino/package.json b/packages/neutrino/package.json index 282a20e..42b9ddb 100644 --- a/packages/neutrino/package.json +++ b/packages/neutrino/package.json @@ -44,7 +44,10 @@ "author": "Eli Perelman ", "license": "MPL-2.0", "dependencies": { + "babel-register": "6.14.0", + "change-case": "3.0.0", "karma": "1.2.0", + "mocha": "3.0.2", "npm": "3.10.6", "resolve": "1.1.7", "vorpal": "1.4.1", diff --git a/packages/neutrino/src/mocha.js b/packages/neutrino/src/mocha.js new file mode 100644 index 0000000..3376d9f --- /dev/null +++ b/packages/neutrino/src/mocha.js @@ -0,0 +1,35 @@ +const spawn = require('child_process').spawn; +const toParam = require('change-case').paramCase; + +let proc; + +module.exports = (config, done) => { + if (proc) { + proc.kill(); + } + + const babelLoader = config.module.loaders.find(loader => loader.loader.includes('babel')); + const mocha = config.mocha; + + process.env.NEUTRINO_BABEL_CONFIG = JSON.stringify(babelLoader ? babelLoader.query : {}); + + const args = Object + .keys(mocha) + .reduce((args, key) => { + const value = mocha[key]; + + return value === true ? + args.concat(`--${toParam(key)}`) : + args.concat(`--${toParam(key)}`, mocha[key]); + }, ['--require', require.resolve('./register')]); + + proc = spawn('node_modules/.bin/mocha', args, { + cwd: process.cwd(), + env: process.env, + stdio: 'inherit' + }); + + if (done) { + proc.on('close', done); + } +}; \ No newline at end of file diff --git a/packages/neutrino/src/register.js b/packages/neutrino/src/register.js new file mode 100644 index 0000000..51d2da1 --- /dev/null +++ b/packages/neutrino/src/register.js @@ -0,0 +1,4 @@ +// This registration runs in a separate process along with Mocha. +// This ensures that Mocha runs the test files with the same Babel +// configuration as the other webpack files +require('babel-register')(JSON.parse(process.env.NEUTRINO_BABEL_CONFIG)); diff --git a/packages/neutrino/src/temp.js b/packages/neutrino/src/temp.js new file mode 100644 index 0000000..c607dfd --- /dev/null +++ b/packages/neutrino/src/temp.js @@ -0,0 +1,5 @@ +const crypto = require('crypto'); +const os = require('os'); +const path = require('path'); + +module.exports = () => path.join(os.tmpdir(), crypto.randomBytes(8).toString('hex'));