Q:

How to get full coverage of a CLI nodeJS app with istanbul?

I am using this config :Istanbul/Mocha/Chai/supertest(for http tests)/sinon (for timer tests) but I am having some problem with testing CLI tools
My question is simple: How can I test my cli program and achieve at the same time 100% code coverage with istanbul? No matter what tool you are using, I would like to understand how you are doing it please!
I found this article which was very helpful at the beginning but 

It was written in 2014
The module mock-utf8-stream does not seem standard
It does not explain clearly the code architecture 

cheers

A:

This will be done in 2 steps:

Make sure your test suite is set up to correctly spawn the CLI execution
Set up nyc (reason for switching from istanbul to nyc explained below) to go through the script files behind your CLI tool

Setting up your tests to run spawn subprocesses
I had to set up some CLI tests a few months ago on Fulky (the project is paused right now but it's temporary) and wrote my test suite as such:
const expect = require('chai').expect;
const spawnSync = require('child_process').spawnSync;

describe('Executing my CLI tool', function () {
  // If your CLI tool is taking some expected time to start up / tear down, you
  // might want to set this to avoid slowness warnings.
  this.slow(600);

  it('should pass given 2 arguments', () => {
    const result = spawnSync(
      './my-CLI-tool',
      ['argument1', 'argument2'],
      { encoding: 'utf-8' }
    );

    expect(result.status).to.equal(0);
    expect(result.stdout).to.include('Something from the output');
  });
});

You can see an example here but bear in mind that this is a test file run with Mocha, that runs Mocha in a spawned process.
A bit Inception for your need here so it might be confusing, but it's testing a Mocha plugin hence the added brain game. That should apply to your use case though if you forget about that complexity.
Setting up coverage
You will then want to install nyc with npm i nyc --save-dev, nowadays' CLI tool for Istanbul, because as opposed to the previous CLI (istanbul itself), it allows coverage for applications that spawn subprocesses.
Good thing is it's still the same tool, the same team, etc. behind nyc, so the switch is really trivial (for example, see this transition).
In your package.json, then add to your scripts:
"scripts": {
  "coverage": "nyc mocha"
}

You will then get a report with npm run coverage (you will probably have to set the reporter option in .nycrc) that goes through your CLI scripts as well.
I haven't set up this coverage part with the project mentioned above, but I have just applied these steps locally and it works as expected so I invite you to try it out on your end.

