Skip to content

Commit

Permalink
[X-Ref: twbs#179] Begin adding tests for CLI
Browse files Browse the repository at this point in the history
[X-Ref: twbs#179] Begin adding tests for CLI
  • Loading branch information
Kevin Kirsche committed Mar 1, 2015
1 parent f454029 commit 269b240
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 88 deletions.
186 changes: 98 additions & 88 deletions src/cli.js
Original file line number Diff line number Diff line change
@@ -1,105 +1,115 @@
#!/usr/bin/env node
/*eslint-env node */
/*eslint no-process-exit: 0 */
'use strict';

var Deferred = require('bluebird');
var chalk = require('chalk');
var program = require('commander');
var readFile = Deferred.promisify(require('fs').readFile);
var glob = Deferred.promisify(require('glob'));
var bootlint = require('./bootlint');

program
.version(require('../package.json').version)
.description('Lint the HTML of Bootstrap projects')
.usage('[options] [files...]')
.option('-d, --disable <IDs>', 'Comma-separated list of disabled lint problem IDs', function (val) {
return val.split(',');
})
.parse(process.argv);

var disabledIds = program.disable === undefined ? [] : program.disable;
var totalErrCount = 0;
var totalFileCount = 0;
var lintedFiles = [];

function buildReporter(origin) {
return function (lint) {
var lintId = (lint.id[0] === 'E') ? chalk.bgGreen.white(lint.id) : chalk.bgRed.white(lint.id);
var output = false;
if (lint.elements) {
lint.elements.each(function (_, element) {
var loc = element.startLocation;
console.log(origin + ":" + (loc.line + 1) + ":" + (loc.column + 1), lintId, lint.message);
(function () {
'use strict';

var Deferred = require('bluebird');
var chalk = require('chalk');
var program = require('commander');
var readFile = Deferred.promisify(require('fs').readFile);
var glob = Deferred.promisify(require('glob'));
var bootlint = require('./bootlint');

program
.version(require('../package.json').version)
.description('Lint the HTML of Bootstrap projects')
.usage('[options] [files...]')
.option('-d, --disable <IDs>', 'Comma-separated list of disabled lint problem IDs', function (val) {
return val.split(',');
})
.parse(process.argv);

var disabledIds = program.disable === undefined ? [] : program.disable;
var totalErrCount = 0;
var totalFileCount = 0;
var lintedFiles = [];

function buildReporter(origin) {
return function (lint) {
var lintId = (lint.id[0] === 'E') ? chalk.bgGreen.white(lint.id) : chalk.bgRed.white(lint.id);
var output = false;
if (lint.elements) {
lint.elements.each(function (_, element) {
var loc = element.startLocation;
console.log(origin + ":" + (loc.line + 1) + ":" + (loc.column + 1), lintId, lint.message);
totalErrCount++;
output = true;
});
}
if (!output) {
console.log(origin + ":", lintId, lint.message);
totalErrCount++;
output = true;
});
}
if (!output) {
console.log(origin + ":", lintId, lint.message);
totalErrCount++;
}
};
}
}
};
}

function handleStdin() {
return new Deferred(function (resolve) {
if (process.stdin.isTTY) {
return resolve();
}
exports.buildReporter = buildReporter;

var stdInput = [];
function handleStdin() {
return new Deferred(function (resolve) {
if (process.stdin.isTTY) {
return resolve();
}

process.stdin.setEncoding('utf8');
var stdInput = [];

process.stdin.on('data', function (chunk) {
stdInput.push(chunk);
});
process.stdin.setEncoding('utf8');

process.stdin.on('end', function () {
bootlint.lintHtml(stdInput.join(''), buildReporter('<stdin>'), disabledIds);
totalFileCount++;
resolve();
});
});
}

function handlePath(pattern) {
return glob(pattern)
.map(function (name) {
return Deferred.props({
contents: readFile(name, {encoding: 'utf8'}),
name: name
process.stdin.on('data', function (chunk) {
stdInput.push(chunk);
});
})
.each(function (file) {
bootlint.lintHtml(file.contents, buildReporter(file.name), disabledIds);
totalFileCount++;
return Deferred.resolve();
});
}

if (!program.args.length) {
program.args.push('-');
}
process.stdin.on('end', function () {
bootlint.lintHtml(stdInput.join(''), buildReporter('<stdin>'), disabledIds);
totalFileCount++;
resolve();
});
});
}

program.args.forEach(function (pattern) {
lintedFiles.push(pattern === '-' ? handleStdin() : handlePath(pattern));
});
exports.handleStdin = handleStdin;

function handlePath(pattern) {
return glob(pattern)
.map(function (name) {
return Deferred.props({
contents: readFile(name, {encoding: 'utf8'}),
name: name
});
})
.each(function (file) {
bootlint.lintHtml(file.contents, buildReporter(file.name), disabledIds);
totalFileCount++;
return Deferred.resolve();
});
}

Deferred.all(lintedFiles).then(function () {
console.log("");
exports.handlePath = handlePath;

if (totalErrCount > 0) {
console.log("For details, look up the lint problem IDs in the Bootlint wiki: https://github.com/twbs/bootlint/wiki");
if (!program.args.length) {
program.args.push('-');
}

console.log("" + totalErrCount + " lint error(s) found across " + totalFileCount + " file(s).");
program.args.forEach(function (pattern) {
lintedFiles.push(pattern === '-' ? handleStdin() : handlePath(pattern));
});

if (totalErrCount) {
process.exit(1);
}
}, function (err) {
console.error(err.stack);
});
exports.program = program;

Deferred.all(lintedFiles).then(function () {
console.log("");

if (totalErrCount > 0) {
console.log("For details, look up the lint problem IDs in the Bootlint wiki: https://github.com/twbs/bootlint/wiki");
}

console.log("" + totalErrCount + " lint error(s) found across " + totalFileCount + " file(s).");

if (totalErrCount) {
process.exit(1);
}
}, function (err) {
console.error(err.stack);
});
})();
88 changes: 88 additions & 0 deletions test/cli_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*eslint-env node */
/*eslint no-process-env: 0 */

'use strict';

var cli = (process.env.BOOTLINT_COV === '1') ? require('../src-cov/cli.js') : require('../src/cli.js');

/*
======== A Handy Little Nodeunit Reference ========
https://github.com/caolan/nodeunit
Test methods:
test.expect(numAssertions)
test.done()
Test assertions:
test.ok(value, [message])
test.deepEqual(actual, expected, [message])
test.notDeepEqual(actual, expected, [message])
test.strictEqual(actual, expected, [message])
test.notStrictEqual(actual, expected, [message])
test.throws(block, [error], [message])
test.doesNotThrow(block, [error], [message])
test.ifError(value)
*/

exports.bootlint = {
setUp: function (done) {
// setup here
done();
},
'Program details': function (test) {
test.expect(3);
test.strictEqual(cli.program.version(), '0.11.0', 'should give the current Bootlint version.');
test.strictEqual(cli.program.description(), 'Lint the HTML of Bootstrap projects', 'should provide a description of Bootlint.');
test.strictEqual(cli.program.usage(), '[options] [files...]', 'should tell how to use Bootlint.');
test.done();
},
'Disabled options': function (test) {
test.expect(5);
test.strictEqual(cli.program.option('')._allowUnknownOption, false, 'Don\'t allow unknown command line options.');
test.strictEqual(cli.program.option('')._name, 'grunt', 'should list the program\'s name.');
test.strictEqual(cli.program.option('')._version, '0.11.0', 'should list the program\'s version.');
test.strictEqual(cli.program.option('')._description, 'Lint the HTML of Bootstrap projects',
'should provide a description of Bootlint.');
test.strictEqual(cli.program.option('')._usage, '[options] [files...]', 'should provide Bootlint usage options.');
test.done();
},
'Version flag': function (test) {
test.expect(7);
test.strictEqual(cli.program.option('').options[0].flags, '-V, --version', 'should list the version flag');
test.strictEqual(cli.program.option('').options[0].required, 0, 'should not require the version flag.');
test.strictEqual(cli.program.option('').options[0].optional, 0, 'should return whether the version flag is optional.');
test.strictEqual(cli.program.option('').options[0].bool, true, 'should return whether the version flag is optional.');
test.strictEqual(cli.program.option('').options[0].short, '-V', 'should list the short version flag');
test.strictEqual(cli.program.option('').options[0].long, '--version', 'should list the long version flag');
test.strictEqual(cli.program.option('').options[0].description, 'output the version number',
'should provide a description of the version flag');
test.done();
},
'Disabled flag': function (test) {
test.expect(7);
test.strictEqual(cli.program.option('').options[1].flags, '-d, --disable <IDs>', 'should list the disable flag');
test.strictEqual(cli.program.option('').options[1].required, -15, 'should not require the disabled flag.');
test.strictEqual(cli.program.option('').options[1].optional, 0, 'should return whether the version flag is optional.');
test.strictEqual(cli.program.option('').options[1].bool, true, 'should return whether the version flag is optional.');
test.strictEqual(cli.program.option('').options[1].short, '-d', 'should list the short disable flag');
test.strictEqual(cli.program.option('').options[1].long, '--disable', 'should list the long disable flag');
test.strictEqual(cli.program.option('').options[1].description, 'Comma-separated list of disabled lint problem IDs',
'should provide a description of the disable flag');
test.done();
},
'Handle standard input': function (test) {
test.expect(6);
test.strictEqual(cli.handleStdin('-d')._bitField, 268435456, 'Should calculate bitfield of argument');
test.strictEqual(cli.handleStdin('-d')._fulfillmentHandler0, undefined, 'Should leave fulfillment handler as undefined.');
test.strictEqual(cli.handleStdin('-d')._rejectionHandler0, undefined, 'Should leave rejection handler as undefined');
test.strictEqual(cli.handleStdin('-d')._promise0, undefined, 'Should leave promise undefined.');
test.strictEqual(cli.handleStdin('-d')._receiver0, undefined, 'Should leave receiver as undefined');
test.strictEqual(cli.handleStdin('-d')._settledValue, undefined, 'Should leave settled value as undefined.');
test.done();
},
'Build reporter': function (test) {
test.expect(1);
var reporter = cli.buildReporter('<stdin>');
test.strictEqual(typeof reporter, 'function', 'Reporter should be a function');
test.done();
}
};

0 comments on commit 269b240

Please sign in to comment.