Scenario
We are creating a Commander based CLI and we wish to unit test the result of running it with Jest.
Approach
First we will scaffold an example project.
mkdir cli
cd cli
npm init -y
npm i -S commander
npm i -D jest
touch index.js //The commander script
touch index.spec.js //The JEST Unit test
Commander Script
In index.js
implement the script:
#!/usr/bin/env nodevar program = require('commander');program
.version('1.0.0')
.option('-p, --parameters [type]', 'Add parameter')
.parse(process.argv);if (program.parameter) console.log(' - %s parameter', program.parameter);
Jest Unit Test
The cli
function runs the command line defined in index.js
returns a Promise
that contains the result of running the Commander
command line script:
let path = require('path');
let exec = require('child_process').exec;
test('Code should be 0', async () => {
let result = await cli(['-p', 'parameter'], '.');
expect(result.code).toBe(0);
})function cli(args, cwd) {
return new Promise(resolve => {
exec(`node ${path.resolve('./index')} ${args.join(' ')}`,
{ cwd },
(error, stdout, stderr) => { resolve({
code: error && error.code ? error.code : 0,
error,
stdout,
stderr })
})
})}
Make sure that scripts
is configured properly in package.json
:
"scripts": {
"test": "jest"
}
Run npm test
. This will run the unit test in index.spec.js
.
Change Runtime Directory
We pass .
as the current runtime directory in the statement:
let result = await cli(['-p', 'parameter'], '.');
The .
is the cwd
or current working directory parameter. If you change this to something else like ./sandbox/
then the script will consider ./sandbox
to be the current runtime directory.
Real World Example
Check out index.spec.js
for the SuperflyCSS CLI: