Added `add` command and tests.

This commit is contained in:
Braydon Fuller 2015-08-25 13:01:52 -04:00
parent af88cbe55f
commit 5ea787b3a1
3 changed files with 211 additions and 23 deletions

View File

@ -55,17 +55,21 @@ program
});
program
.command('add <module>')
.command('add <modules...>')
.alias('install')
.description('Install a module for the current node')
.action(function(module){
var config = findConfig();
if (!config) {
.action(function(modules){
var configInfo = findConfig(process.cwd());
if (!configInfo) {
throw new Error('Could not find configuration, see `bitcore-node create --help`');
}
add(config, module);
console.log('Successfully added module: ', module);
console.log(module);
var opts = {
path: configInfo.path,
modules: modules
};
add(opts, function() {
console.log('Successfully added modules: ', modules.join(', '));
});
}).on('--help', function() {
console.log(' Examples:');
console.log();

View File

@ -1,2 +1,104 @@
'use strict';
var async = require('async');
var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;
var bitcore = require('bitcore');
var $ = bitcore.util.preconditions;
var _ = bitcore.deps._;
/**
* @param {String} configFilePath - The absolute path to the configuration file
* @param {String} module - The name of the module
* @param {Function} done
*/
function addConfig(configFilePath, module, done) {
$.checkState(path.isAbsolute(configFilePath), 'An absolute path is expected');
fs.readFile(configFilePath, function(err, data) {
if (err) {
return done(err);
}
var config = JSON.parse(data);
$.checkState(
Array.isArray(config.modules),
'Configuration file is expected to have a modules array.'
);
config.modules.push(module);
config.modules = _.unique(config.modules);
config.modules.sort(function(a, b) {
return a > b;
});
fs.writeFile(configFilePath, JSON.stringify(config, null, 2), done);
});
}
/**
* @param {String} configDir - The absolute configuration directory path
* @param {String} module - The name of the module
* @param {Function} done
*/
function addModule(configDir, module, done) {
$.checkState(path.isAbsolute(configDir), 'An absolute path is expected');
var npm = spawn('npm', ['install', module, '--save'], {cwd: configDir});
npm.stdout.on('data', function(data) {
process.stdout.write(data);
});
npm.stderr.on('data', function(data) {
process.stderr.write(data);
});
npm.on('close', function(code) {
if (code !== 0) {
return done(new Error('There was an error installing module: ' + module));
} else {
return done();
}
});
}
/**
* @param {String} options.cwd - The current working directory
* @param {String} options.dirname - The bitcore-node configuration directory
* @param {Array} options.modules - An array of strings of module names
* @param {Function} done - A callback function called when finished
*/
function add(options, done) {
$.checkArgument(_.isObject(options));
$.checkArgument(_.isFunction(done));
$.checkArgument(
_.isString(options.path) && path.isAbsolute(options.path),
'An absolute path is expected'
);
$.checkArgument(Array.isArray(options.modules));
var configPath = options.path;
var modules = options.modules;
var bitcoreConfigPath = path.resolve(configPath, 'bitcore-node.json');
var packagePath = path.resolve(configPath, 'package.json');
if (!fs.existsSync(bitcoreConfigPath) || !fs.existsSync(packagePath)) {
return done(
new Error('Directory does not have a bitcore-node.json and/or package.json file.')
);
}
async.eachSeries(
modules,
function(module, next) {
// npm install <module_name> --save
addModule(configPath, module, function(err) {
if (err) {
return next(err);
}
// add module to bitcore-node.json
addConfig(bitcoreConfigPath, module, next);
});
}, done
);
}
module.exports = add;

View File

@ -2,37 +2,119 @@
var should = require('chai').should();
var sinon = require('sinon');
var path = require('path');
var fs = require('fs');
var proxyquire = require('proxyquire');
var mkdirp = require('mkdirp');
var rimraf = require('rimraf');
var add = require('../../lib/scaffold/add');
describe('#add', function() {
before(function() {
// setup testing directories
var basePath = path.resolve(__dirname, '..');
var testDir = path.resolve(basePath, 'temporary-test-data');
var startConfig = {
name: 'My Node',
modules: []
};
var startPackage = {};
before(function(done) {
mkdirp(testDir + '/s0/s1', function(err) {
if (err) {
throw err;
}
fs.writeFile(
testDir + '/s0/s1/bitcore-node.json',
JSON.stringify(startConfig),
function(err) {
if (err) {
throw err;
}
fs.writeFile(
testDir + '/s0/s1/package.json',
JSON.stringify(startPackage),
done
);
}
);
});
});
after(function() {
after(function(done) {
// cleanup testing directories
rimraf(testDir, function(err) {
if (err) {
throw err;
}
done();
});
});
describe('will modify scaffold files', function() {
it('will give an error if expected files do not exist', function() {
it('will give an error if expected files do not exist', function(done) {
add({
path: path.resolve(testDir, 's0'),
modules: ['a', 'b', 'c']
}, function(err) {
should.exist(err);
err.message.match(/^Invalid state/);
done();
});
});
it('will update bitcore-node.json modules', function() {
it('will receive error from `npm install`', function(done) {
var spawn = sinon.stub().returns({
stdout: {
on: sinon.stub()
},
stderr: {
on: sinon.stub()
},
on: sinon.stub().callsArgWith(1, 1)
});
var addtest = proxyquire('../../lib/scaffold/add', {
'child_process': {
spawn: spawn
}
});
addtest({
path: path.resolve(testDir, 's0/s1/'),
modules: ['a', 'b', 'c']
}, function(err) {
should.exist(err);
err.message.should.equal('There was an error installing module: a');
done();
});
});
it('will update package.json modules', function() {
});
it('will install the necessary node.js modules', function() {
});
it('will install dependencies', function() {
it('will update bitcore-node.json modules', function(done) {
var spawn = sinon.stub().returns({
stdout: {
on: sinon.stub()
},
stderr: {
on: sinon.stub()
},
on: sinon.stub().callsArgWith(1, 0)
});
var addtest = proxyquire('../../lib/scaffold/add', {
'child_process': {
spawn: spawn
}
});
addtest({
path: path.resolve(testDir, 's0/s1/'),
modules: ['a', 'b', 'c']
}, function(err) {
should.not.exist(err);
var configPath = path.resolve(testDir, 's0/s1/bitcore-node.json');
var config = JSON.parse(fs.readFileSync(configPath));
config.modules.should.deep.equal(['a','b','c']);
done();
});
});
});