var fs = require('fs'), path = require('path'), chai = require('chai'), expect = chai.expect, chaiMatch = require('chai-match'), execSync = require('child_process').execSync, spawnSync = require('child_process').spawnSync, cmd = 'node src/cli/cli.js', packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8')); require('sinon'); chai.should(); chai.use(chaiMatch); /** * Spawns a CLI process synchrously * @param {string|null} command * @param {string[]} args * @param {{}} [options] * @returns {{output: *, stdout: string, stderr: string, status: number}} */ function spawnCLI (command, args, options) { 'use strict'; var nargs = ['src/cli/cli.js']; if (command) { nargs.push(command);} args = nargs.concat(args); var otp = spawnSync('node', args, options), stdout = otp.stdout.toString(), stderr = otp.stderr.toString(), output = otp.output[0], status = otp.status; return {stdout: stdout, stderr: stderr, output: output, status: status}; } describe('showdown cli', function () { 'use strict'; describe('without commands', function () { it('should display help if no commands are specified', function () { var proc = spawnCLI(null, [], {}); proc.status.should.equal(1); proc.stderr.should.contain('CLI to Showdownjs markdown parser'); proc.stderr.should.contain('Usage:'); proc.stderr.should.contain('Options:'); proc.stderr.should.contain('Commands:'); proc.stdout.should.equal(''); }); describe('-h', function () { it('should display help', function () { var proc = spawnCLI(null, ['-h'], {}); proc.status.should.equal(0); proc.stdout.should.contain('CLI to Showdownjs markdown parser'); proc.stdout.should.contain('Usage:'); proc.stdout.should.contain('Options:'); proc.stdout.should.contain('Commands:'); proc.stderr.should.equal(''); }); }); describe('-v', function () { it('should display version', function () { var proc = spawnCLI(null, ['-V'], {}); proc.status.should.equal(0); proc.stdout.should.match(/^\d{1,2}\.\d{1,3}\.\d{1,3}/); proc.stdout.should.match(/^(\d{1,2}\.\d{1,3}\.\d{1,3})/).and.capture(0).equals(packageJson.version); proc.stderr.should.equal(''); }); }); }); describe('makehtml command', function () { describe('makehtml without flags', function () { it('should read from stdin and output to stdout', function () { var proc = spawnCLI('makehtml', [], { input: '**foo**', encoding: 'utf-8' }); proc.status.should.equal(0); proc.stdout.should.equal('

foo

'); proc.stderr.should.not.equal(''); }); }); describe('makehtml -p', function () { it('should enable a flavor', function () { var proc = spawnCLI('makehtml', ['-p', 'github'], { input: 'this is a :smile:', // test the emoji option as a proxy encoding: 'utf-8' }); proc.status.should.equal(0); proc.stderr.should.contain('Enabling flavor github...'); proc.stdout.should.equal('

this is a 😄

'); //'Here in London'.should.match(/(here|there) in (\w+)/i).and.capture(1).equals('London'); }); it('should give an error if a flavor is not recognised', function () { var proc = spawnCLI('makehtml', ['-p', 'foobar'], { input: '**foo**', encoding: 'utf-8' }); proc.status.should.equal(1); }); }); describe('makehtml -c', function () { it('should not parse emoji if config option is not passed', function () { var proc = spawnCLI('makehtml', [], { input: 'this is a :smile:', encoding: 'utf-8' }); proc.status.should.equal(0); proc.stderr.should.not.contain('Enabling option emoji'); proc.stdout.should.equal('

this is a :smile:

'); }); it('should enable a showdown option', function () { var proc = spawnCLI('makehtml', ['-c', 'emoji'], { input: 'this is a :smile:', encoding: 'utf-8' }); proc.status.should.equal(0); proc.stderr.should.contain('Enabling option emoji'); proc.stdout.should.equal('

this is a 😄

'); }); it('should enable 2 showdown options (emoji and strikethrough)', function () { var proc = spawnCLI('makehtml', ['-c', 'emoji', '-c', 'strikethrough'], { input: 'this is ~~not~~ a :smile:', encoding: 'utf-8' }); proc.status.should.equal(0); proc.stderr.should.contain('Enabling option emoji'); proc.stdout.should.equal('

this is not a 😄

'); }); it('should ignore unrecognized options', function () { var proc = spawnCLI('makehtml', ['-c', 'foobar'], { input: 'foo', encoding: 'utf-8' }); proc.status.should.equal(0); proc.stderr.should.contain('Enabling option foobar'); proc.stdout.should.equal('

foo

'); }); }); describe('makehtml -m', function () { it('should mute information', function () { var proc = spawnCLI('makehtml', ['-m', '-i'], {input: '**foo**'}); proc.status.should.equal(0); expect(proc.output).to.be.null; // jshint ignore:line proc.stdout.should.equal('

foo

'); proc.stderr.should.equal(''); }); it('should mute everything, even errors', function () { var proc = spawnCLI('makehtml', ['-m', '-i']); proc.status.should.equal(1); expect(proc.output).to.be.null; // jshint ignore:line proc.stdout.should.equal(''); proc.stderr.should.equal(''); }); it('should not mute parsed html', function () { var proc = spawnCLI('makehtml', ['-m', '-i'], { input: '**foo**', encoding: 'utf-8' }); proc.status.should.equal(0); proc.stdout.should.equal('

foo

'); proc.stderr.should.equal(''); }); }); describe('makehtml -q', function () { it('should not display information', function () { var proc = spawnCLI('makehtml', ['-q', '-i'], {input: '**foo**'}); proc.status.should.equal(0); expect(proc.output).to.be.null; // jshint ignore:line proc.stdout.should.equal('

foo

'); proc.stderr.should.match(/^\s*DONE!\s*$/); }); it('should display errors', function () { var proc = spawnCLI('makehtml', ['-q', '-i']); proc.status.should.equal(1); expect(proc.output).to.be.null; // jshint ignore:line proc.stdout.should.equal(''); proc.stderr.should.match(/^ERROR:/); }); it('should not mute parsed html', function () { var proc = spawnCLI('makehtml', ['-q', '-i'], { input: '**foo**', encoding: 'utf-8' }); proc.status.should.equal(0); proc.stdout.should.equal('

foo

'); proc.stderr.should.match(/^\s*DONE!\s*$/); }); }); describe('makehtml -i -o', function () { it('should read from stdin and output to stdout', function () { var proc = spawnCLI('makehtml', ['-i', '-o'], { input: '**foo**', encoding: 'utf-8' }); proc.status.should.equal(0); proc.stdout.should.equal('

foo

'); proc.stderr.should.not.equal(''); }); }); describe('makehtml -i -o', function () { it('should read from a file and output to stdout', function () { var expectedOtp = fs.readFileSync('test/cli/basic.html', 'utf8').toString().trim(), proc = spawnCLI('makehtml', ['-i', 'test/cli/basic.md'], {encoding: 'utf-8'}); proc.status.should.equal(0); proc.stdout.should.equal(expectedOtp); proc.stderr.should.not.equal(''); }); }); describe('makehtml -i -o ', function () { it('should read from stdin and output to a file', function () { execSync(cmd + ' makehtml -m -i -o .build/io1.html', { encoding: 'utf8', input: '**foo**' }); var otp = fs.readFileSync('.build/io1.html', 'utf8').toString().trim(), expectedOtp = '

foo

'; otp.trim().should.equal(expectedOtp); }); }); describe('makehtml -i -o ', function () { it('should read from a file and output to a file', function () { var expectedOtp = fs.readFileSync('test/cli/basic.html', 'utf8').toString().trim(), proc = spawnCLI('makehtml', ['-i', 'test/cli/basic.md', '-o', '.build/io2.html'], {encoding: 'utf-8'}), otp = fs.readFileSync('.build/io2.html', 'utf8').toString().trim(); otp.trim().should.equal(expectedOtp); proc.stdout.should.not.equal(expectedOtp); proc.stderr.should.equal(''); proc.status.should.equal(0); }); }); describe('makehtml -a', function () { it('should read from stdin and append to a file', function () { fs.writeFileSync('.build/io3.html', '

foo

'); var expectedOtp = '

foo

foo

', proc = spawnCLI('makehtml', ['-i', '-o', '.build/io3.html', '-a'], { encoding: 'utf8', input: '**foo**' }), otp = fs.readFileSync('.build/io3.html', 'utf8').toString().trim(); proc.status.should.equal(0); otp.trim().should.equal(expectedOtp); // since the output is to a file, messages are logged to stdout proc.stdout.should.not.equal(expectedOtp); // stderr should be empty proc.stderr.should.equal(''); }); it('should ignore -a flag if -o is missing', function () { var expectedOtp = '

foo

', proc = spawnCLI('makehtml', ['-a'], {encoding: 'utf8', input: '**foo**'}); proc.status.should.equal(0); proc.stderr.should.not.equal(''); proc.stdout.should.equal(expectedOtp); }); }); describe('makehtml -e', function () { it('should load the extension', function () { var expectedOtp = '

bar

', extPath = path.resolve(__dirname + '/../mocks/mock-extension.js'), proc = spawnCLI('makehtml', ['-i', '-o', '-e', extPath], { encoding: 'utf8', input: '**foo**' }); proc.status.should.equal(0, 'Process exited with error state'); proc.stdout.trim().should.equal(expectedOtp); }); }); }); });