Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor and further modularize CLI and add unit tests #446

Merged
merged 1 commit into from
Jan 27, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion bin/styleguide
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#!/usr/bin/env node

require('../lib/cli').main();
var path = require('path'),
cli = require(path.resolve(__dirname, '../lib/modules/cli')),
yargs = require('yargs'),
args = cli.argv(yargs).argv;

cli.styleguide(args);
66 changes: 0 additions & 66 deletions lib/cli.js

This file was deleted.

21 changes: 21 additions & 0 deletions lib/modules/cli/argv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
var chalk = require('chalk');

module.exports = function(argLib) {
return argLib
.usage('Generate sc5-styleguide')
.example('$0 --kssSource <source files> --styleSource <preprocessed CSS files> --output <dest>', 'Generate a styleguide')
.demand('kssSource', chalk.red('Please provide sources of KSS files'))
.demand('styleSource', chalk.red('Please provide sources of preprocessed files'))
.demand('output', chalk.red('Please provide output path'))
.describe('kssSource', 'KSS source file(s)')
.describe('styleSource', 'Preprocessed styles')
.describe('output', 'Output directory')
.describe('title', 'This string is used as a page title and in the page header')
.describe('extraHead', 'These HTML elements are injected inside the style guide head-tag')
.describe('commonClass', 'The provided classes are added to all preview blocks in the generated style guide')
.describe('appRoot', 'Define the appRoot parameter if you are hosting the style guide from a directory other than the root directory of the HTTP server')
.describe('styleVariables', 'Specify the files to parse variable definitions from (defaults to all files/glob pattern passed to kssSource')
.describe('server', 'Enable built-in web-server. To enable Desiger tool the style guide must be served with the built-in web server')
.describe('port', 'Port of the server. Default is 3000')
.describe('watch', 'Automatically generate styleguide on file change');
};
4 changes: 4 additions & 0 deletions lib/modules/cli/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
argv: require('./argv'),
styleguide: require('./styleguide-cli')
};
46 changes: 46 additions & 0 deletions lib/modules/cli/styleguide-cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
var path = require('path'),
gulp = require('gulp'),
runSequence = require('run-sequence');

module.exports = function(argv) {

var styleguide = require(path.resolve(__dirname, '../../styleguide'));

gulp.task('styleguide:generate', function() {
return gulp.src(argv.kssSource)
.pipe(styleguide.generate({
title: argv.title,
rootPath: argv.output,
extraHead: argv.extraHead,
commonClass: argv.commonClass,
appRoot: argv.appRoot,
styleVariables: argv.styleVariables,
server: argv.server,
port: argv.port
}))
.pipe(gulp.dest(argv.output));
});

gulp.task('styleguide:applystyles', function() {
return gulp.src(argv.styleSource)
.pipe(styleguide.applyStyles())
.pipe(gulp.dest(argv.output));
});

gulp.task('watch:kss', function() {
return gulp.watch(argv.kssSource, ['styleguide:generate']);
});

gulp.task('watch:styles', function() {
return gulp.watch(argv.styleSource, ['styleguide:applystyles']);
});

var tasks = ['styleguide:generate', 'styleguide:applystyles'];
if (argv.watch) {
tasks.push('watch:styles');
tasks.push('watch:kss');
}

runSequence.apply(this, tasks);

};
80 changes: 80 additions & 0 deletions test/unit/modules/cli/argv.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'use strict';

var path = require('path'),
chai = require('chai'),
expect = chai.expect,
sinon = require('sinon'),
argv = require(path.resolve(__dirname, '../../../../lib/modules/cli/argv')),
mockApi = ['usage', 'example', 'demand', 'describe'],
required = ['kssSource', 'styleSource', 'output'],
optional = ['title', 'extraHead', 'commonClass', 'appRoot', 'styleVariables', 'server', 'port', 'watch'];

chai.use(require('sinon-chai'));

/**
* override .calledWith default failure message (prints the whole object) with something more readable
*/
chai.Assertion.addMethod('calledWith', function(arg) {
var obj = this._obj;
this.assert(
obj.calledWith(arg) === true,
'expected function to have been called with #{exp}',
'expected function not to have been called with #{exp}',
arg,
''
);
});

describe('cli arguments', function() {

var spy, args;

beforeEach(function() {
spy = mock(mockApi);
args = argv(spy);
});

it('returns the passed arg itself', function() {
expect(args).to.deep.eql(spy);
});

it('registers usage', function() {
expect(spy.usage).to.have.been.calledWith(sinon.match.string);
});

it('has an example', function() {
expect(spy.example).to.have.been.calledWith(sinon.match.string);
});

describe('requires argument', function() {
required.forEach(function(arg) {
it(arg, function() {
expect(spy.demand, 'demand').to.have.been.calledWith(arg);
});
});
});

describe('allows optional argument', function() {
optional.forEach(function(arg) {
it(arg, function() {
expect(spy.demand, 'demand').not.to.have.been.calledWith(arg);
});
});
});

describe('describes argument', function() {
required.concat(optional).forEach(function(arg) {
it(arg, function() {
expect(spy.describe, 'describe').to.have.been.calledWith(arg);
});
});
});

});

function mock(api) {
return api.reduce(function(spy, func) {
spy[func] = sinon.stub().returns(spy);
return spy;
}, {});
}