From babb542ca918509e45bd76e5dbd76a421362f1eb Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Sat, 1 Feb 2020 12:51:16 +0100 Subject: [PATCH] resolves #86 exit process consistency --- lib/invoker.js | 53 ++++++++++++++++++++++---------------------------- test/test.js | 42 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/lib/invoker.js b/lib/invoker.js index b185fe7..61fe699 100644 --- a/lib/invoker.js +++ b/lib/invoker.js @@ -19,18 +19,28 @@ class Invoker { this.showVersion() process.exit(0) } + if (files.length === 0 && !this.options.stdin) { + // nothing to do... + this.showHelp() + process.exit(0) + } Invoker.prepareProcessor(args, asciidoctor) const options = this.options.options const failureLevel = options['failure_level'] - if (this.options.stdin) { - await Invoker.convertFromStdin(options, args) - Invoker.exit(failureLevel) - } else if (files && files.length > 0) { - Invoker.processFiles(files, verbose, args['timings'], options) + try { + if (this.options.stdin) { + await Invoker.convertFromStdin(options, args) + } else if (files && files.length > 0) { + Invoker.convertFiles(files, verbose, args['timings'], options) + } Invoker.exit(failureLevel) - } else { - this.showHelp() - process.exit(0) + } catch (e) { + if (e && e.name === 'NotImplementedError' && e.message === `asciidoctor: FAILED: missing converter for backend '${options.backend}'. Processing aborted.`) { + console.error(`> Error: missing converter for backend '${options.backend}'. Processing aborted.`) + console.error(`> You might want to require a Node.js package with --require option to support this backend.`) + process.exit(1) + } + throw e } } @@ -69,31 +79,14 @@ CLI version ${pkg.version}` if (args['timings']) { const timings = asciidoctor.Timings.create() const instanceOptions = Object.assign({}, options, { timings }) - Invoker.convert(asciidoctor.convert, data, instanceOptions) + asciidoctor.convert(data, instanceOptions) timings.printReport(process.stderr, '-') } else { - Invoker.convert(asciidoctor.convert, data, options) - } - } - - static convert (processorFn, input, options) { - try { - processorFn.apply(asciidoctor, [input, options]) - } catch (e) { - if (e && e.name === 'NotImplementedError' && e.message === `asciidoctor: FAILED: missing converter for backend '${options.backend}'. Processing aborted.`) { - console.error(`> Error: missing converter for backend '${options.backend}'. Processing aborted.`) - console.error(`> You might want to require a Node.js package with --require option to support this backend.`) - process.exit(1) - } - throw e + asciidoctor.convert(data, options) } } - static convertFile (file, options) { - Invoker.convert(asciidoctor.convertFile, file, options) - } - - static processFiles (files, verbose, timings, options) { + static convertFiles (files, verbose, timings, options) { files.forEach((file) => { if (verbose) { console.log(`converting file ${file}`) @@ -101,10 +94,10 @@ CLI version ${pkg.version}` if (timings) { const timings = asciidoctor.Timings.create() const instanceOptions = Object.assign({}, options, { timings }) - Invoker.convertFile(file, instanceOptions) + asciidoctor.convertFile(file, instanceOptions) timings.printReport(process.stderr, file) } else { - Invoker.convertFile(file, options) + asciidoctor.convertFile(file, options) } }) } diff --git a/test/test.js b/test/test.js index d6b4275..028328c 100644 --- a/test/test.js +++ b/test/test.js @@ -156,6 +156,7 @@ describe('Help', () => { describe('Print timings report', () => { it('should print timings report', () => { sinon.stub(process.stderr, 'write') + sinon.stub(process.stdout, 'write') sinon.stub(process, 'exit') try { new Invoker(new Options().parse(['node', 'asciidoctor', `${__dirname}/fixtures/sample.adoc`, '--timings', '-o', '-'])).invoke() @@ -166,6 +167,43 @@ describe('Print timings report', () => { expect(process.stderr.write.getCall(3).args[0]).to.include('Total time (read, parse and convert):') } finally { process.stderr.write.restore() + process.stdout.write.restore() + process.exit.restore() + } + }) +}) + +describe('Write to stdout', () => { + it('should write to stdout', () => { + sinon.stub(process.stdout, 'write') + sinon.stub(process, 'exit') + try { + new Invoker(new Options().parse(['node', 'asciidoctor', `${__dirname}/fixtures/sample.adoc`, '-a', 'nofooter', '-o', '-'])).invoke() + expect(process.stdout.write.called).to.be.true() + expect(process.stdout.write.getCall(0).args[0]).to.include(` + +
+
+
+
+

This is a sample document

+
+
+
+
+

First section

+
+
+

This is a paragraph.

+
+
+
+
+`) + } finally { + process.stdout.write.restore() process.exit.restore() } }) @@ -227,7 +265,7 @@ describe('Process files', () => { it('should exit with code 1 when failure level is lower than the maximum logging level', () => { sinon.stub(process, 'exit') try { - Invoker.processFiles([bookFilePath], false, false) + Invoker.convertFiles([bookFilePath], false, false) Invoker.exit(3) // ERROR: 3 expect(process.exit.called).to.be.true() expect(process.exit.calledWith(1)).to.be.true() @@ -239,7 +277,7 @@ describe('Process files', () => { it('should exit with code 0 when failure level is lower than the maximum logging level', () => { sinon.stub(process, 'exit') try { - Invoker.processFiles([bookFilePath], false, false) + Invoker.convertFiles([bookFilePath], false, false) Invoker.exit(4) // FATAL: 4 expect(process.exit.called).to.be.true() expect(process.exit.calledWith(0)).to.be.true()