Installations
npm install chai-exec
Releases
Unable to fetch releases
Developer
Developer Guide
Module System
CommonJS
Min. Node Version
>=10
Typescript Support
Yes
Node Version
10.21.0
NPM Version
6.14.4
Statistics
5 Stars
125 Commits
1 Forks
3 Watching
2 Branches
3 Contributors
Updated on 16 Jan 2024
Bundle Size
17.51 kB
Minified
5.86 kB
Minified + Gzipped
Languages
JavaScript (89.7%)
TypeScript (10.3%)
Total Downloads
Cumulative downloads
Total Downloads
61,474
Last day
-17.9%
32
Compared to previous day
Last week
-21.1%
131
Compared to previous week
Last month
-5.1%
614
Compared to previous month
Last year
29.8%
6,323
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Dependencies
1
Chai Exec
Chai assertions for testing your CLI
Features
-
Easy to use
Pass your CLI and arguments as a single string, an array of strings, or as separate parameters. -
Don't repeat yourself
Set your common defaults once. Each test ony needs to specify the arguments that are unique to it. -
Fluent assertions
Test your CLI using intuitive fluent syntax, such asmyCLI.should.exit.with.code(0)
ormyCLI.stdout.should.contain("some string")
. -
Async Support
Just useawait chaiExecAsync()
instead ofchaiExec()
. Everything else is the same. -
Windows Support
Excellent Windows support, thanks to cross-spawn.
Related Projects
- ez-spawn - Simple, consistent process spawning
Examples
1const chaiExec = require("@jsdevtools/chai-exec"); 2const chai = require("chai"); 3 4chai.use(chaiExec); 5 6describe("My CLI", () => { 7 it("should exit with a zero exit code", () => { 8 // Run your CLI 9 let myCLI = chaiExec('my-cli --arg1 --arg2 "some other arg"'); 10 11 // Should syntax 12 myCLI.should.exit.with.code(0); 13 myCLI.stdout.should.contain("Success!"); 14 myCLI.stderr.should.be.empty; 15 16 // Expect sytnax 17 expect(myCLI).to.exit.with.code(0); 18 expect(myCLI).stdout.to.contain("Success!"); 19 expect(myCLI).stderr.to.be.empty; 20 21 // Assert syntax 22 assert.exitCode(myCLI, 0); 23 assert.stdout(myCLI, "Success!"); 24 assert.stderr(myCLI, ""); 25 }); 26});
Installation
Install using npm:
1npm install @jsdevtools/chai-exec
Then require it in your test file and register it with Chai:
1const chaiExec = require("@jsdevtools/chai-exec"); 2const chai = require("chai"); 3 4chai.use(chaiExec);
Usage
chaiExec(cli, [args], [options])
You can pass your CLI and its arguments as a single string, an array of strings, or as separate parameters. The following examples all do the same thing:
1chaiExec(`git commit -am "Fixed a bug"`); // Pass the CLI and args as a single string 2chaiExec("git", "commit", "-am", "Fixed a bug"); // Pass the CLI and args as separate params 3chaiExec(["git", "commit", "-am", "Fixed a bug"]); // Pass the CLI and args as an array 4chaiExec("git", ["commit", "-am", "Fixed a bug"]); // Pass the CLI as a string and args as an array
See ez-spawn options for details about the options
parameter.
chaiExecAsync(cli, [args], [options])
The chaiExecAsync()
function works exactly the same as chaiExec()
, except that it runs your CLI asynchronously and returns a Promise
that resolves when the CLI exits. You'll need to explicitly require the chaiExecAsync
export, like this:
1const { chaiExecAsync } = require("@jsdevtools/chai-exec");
You can then use chaiExecAsync
exactly the same as chaiExec
, but remember to use the async
and await
keywords, since it's asynchronous.
1const { chaiExecAsync } = require("@jsdevtools/chai-exec"); 2const chai = require("chai"); 3 4chai.use(chaiExecAsync); 5 6describe("My CLI", () => { 7 it("should exit with a zero exit code", async () => { 8 // Run your CLI 9 let myCLI = await chaiExecAsync('my-cli --arg1 --arg2 "some other arg"'); 10 11 // Should syntax 12 myCLI.should.exit.with.code(0); 13 myCLI.stdout.should.contain("Success!"); 14 myCLI.stderr.should.be.empty; 15 16 // Expect sytnax 17 expect(myCLI).to.exit.with.code(0); 18 expect(myCLI).stdout.to.contain("Success!"); 19 expect(myCLI).stderr.to.be.empty; 20 21 // Assert syntax 22 assert.exitCode(myCLI, 0); 23 assert.stdout(myCLI, "Success!"); 24 assert.stderr(myCLI, ""); 25 }); 26});
chaiExec.defaults
When writing tests for a CLI, you'll often want to use the same command, args, and/or options for every test. Rather than repeating the same parameters every time you call chaiExec
, you can just set chaiExec.defaults
once. Your default values will be used for every subsequent chaiExec()
call. You can specify additional CLI arguments and/or options for each call, in addition to the defaults.
-
defaults.command
(string)
The name or path of your CLI. Set this once, and then you only ever need to pass arguments tochaiExec()
-
defaults.args
(string or array of strings)
Arguments to pass to your CLI every time. If you pass additional arguments when you callchaiExec()
, they will be appended to the default arguments. -
defaults.options
(options object)
Default options to use every time. If you pass additional options when you callchaiExec()
, they will be merged with the default arguments.
1const chaiExec = require("@jsdevtools/chai-exec"); 2const chai = require("chai"); 3 4chai.use(chaiExec); 5 6// Set some defaults 7chaiExec.defaults = { 8 command: "my-cli", 9 args: "--arg1 --arg2", 10 options: { 11 cwd: "/usr/bin" 12 } 13}; 14 15describe("My CLI", () => { 16 it("should use defaults", () => { 17 // Run your CLI using defaults + one-time args 18 let myCLI("--arg3 --arg4"); 19 20 myCLI.command.should.equal("my-cli"); 21 myCLI.args.should.deep.equal([ "--arg1", "--arg2", "--arg3", "--arg4" ]); 22 }); 23});
Assertions
.exitCode(number, [message])
aliases: .exit.code
or .status
Asserts on your CLI's exit code. You can test for a specific code, a list of codes, or a range.
1// Should syntax 2myCLI.exitCode.should.equal(0); 3myCLI.should.have.exitCode(0); 4myCLI.should.exit.with.code(0); 5myCLI.should.exit.with.a.code.that.is.oneOf(0, [0, 1, 2, 3]); 6myCLI.should.have.an.exit.code.of.at.least(0).and.at.most(5); 7 8// Expect sytnax 9expect(myCLI).exitCode.to.equal(0); 10expect(myCLI).to.have.exitCode(0); 11expect(myCLI).to.exit.with.code(0); 12expect(myCLI).to.exit.with.a.code.that.is.oneOf([0, 1, 2, 3]); 13expect(myCLI).to.have.an.exit.code.of.at.least(0).and.at.most(5); 14 15// Assert syntax 16assert.equal(myCLI.exitCode, 0); 17 18assert.exitCode(myCLI, 0); 19assert.exitCode(myCLI, [0, 1, 2, 3]); 20 21assert.notExitCode(myCLI, 1); 22assert.notExitCode(myCLI, [1, 2, 3]); 23 24assert.exitCodeBetween(myCLI, 0, 5); 25assert.exitCodeNotBetween(myCLI, 1, 5);
.stdout(string, [message])
Asserts on your CLI's standard output (non-error, non-warning output). You can test for a specific string, a substring, or a regular expression.
1// Should syntax 2myCLI.stdout.should.equal("Success!"); 3myCLI.should.have.stdout.that.contains("Success!"); 4myCLI.should.have.stdout.that.does.not.contain("Failure!"); 5myCLI.should.have.stdout.that.matches(/^Success!$/); 6myCLI.should.have.stdout.that.does.not.match(/^Failure!$/); 7 8// Expect syntax 9expect(myCLI).stdout.to.equal("Success!"); 10expect(myCLI).to.have.stdout.that.contains("Success!"); 11expect(myCLI).to.have.stdout.that.does.not.contain("Failure!"); 12expect(myCLI).to.have.stdout.that.matches(/^Success!$/); 13expect(myCLI).to.have.stdout.that.does.not.match(/^Failure!$/); 14 15// Assert syntax 16assert.stdout(myCLI, "Success!"); 17assert.stdout(myCLI, /^Success!$/); 18 19assert.include(myCLI.stdout, "Success!"); 20assert.notInclude(myCLI.stdout, "Failure!"); 21 22assert.match(myCLI.stdout, /^Success!$/); 23assert.notMatch(myCLI.stdout, /^Failure!$/);
.stderr(string, [message])
Asserts on your CLI's stderr output (errors and warnings). You can test for a specific string, a substring, or a regular expression.
1// Should syntax 2myCLI.stderr.should.equal("Failure!"); 3myCLI.should.have.stderr.that.contains("Failure!"); 4myCLI.should.have.stderr.that.does.not.contain("Success!"); 5myCLI.should.have.stderr.that.matches(/^Failure!$/); 6myCLI.should.have.stderr.that.does.not.match(/^Success!$/); 7 8// Expect syntax 9expect(myCLI).stderr.to.equal("Failure!"); 10expect(myCLI).to.have.stderr.that.contains("Failure!"); 11expect(myCLI).to.have.stderr.that.does.not.contain("Success!"); 12expect(myCLI).to.have.stderr.that.matches(/^Failure!$/); 13expect(myCLI).to.have.stderr.that.does.not.match(/^Success!$/); 14 15// Assert syntax 16assert.stderr(myCLI, "Failure!"); 17assert.stderr(myCLI, /^Failure!$/); 18 19assert.include(myCLI.stderr, "Failure!"); 20assert.notInclude(myCLI.stderr, "Success!"); 21 22assert.match(myCLI.stderr, /^Failure!$/); 23assert.notMatch(myCLI.stderr, /^Success!$/);
.output(string, [message])
Asserts on all of your CLI's output (stdout + output). You can test for a specific string, a substring, or a regular expression.
1// Should syntax 2myCLI.output.should.equal("Success!"); 3myCLI.should.have.output.that.contains("Failure!"); 4myCLI.should.have.output.that.does.not.contain("Success!"); 5myCLI.should.have.output.that.matches(/^(Success|Failure)!$/); 6myCLI.should.have.output.that.does.not.match(/^(Success|Failure)!$/); 7 8// Expect syntax 9expect(myCLI).output.to.equal("Success!"); 10expect(myCLI).to.have.output.that.contains("Failure!"); 11expect(myCLI).to.have.output.that.does.not.contain("Success!"); 12expect(myCLI).to.have.output.that.matches(/^(Success|Failure)!$/); 13expect(myCLI).to.have.output.that.does.not.match(/^(Success|Failure)!$/); 14 15// Assert syntax 16assert.output(myCLI, "Failure!"); 17assert.output(myCLI, /^(Success|Failure)!$/); 18 19assert.include(myCLI.output, "Failure!"); 20assert.notInclude(myCLI.output, "Success!"); 21 22assert.match(myCLI.output, /^Failure!$/); 23assert.notMatch(myCLI.output, /^Success!$/);
Contributing
Contributions, enhancements, and bug-fixes are welcome! Open an issue on GitHub and submit a pull request.
Building/Testing
To build/test the project locally on your computer:
-
Clone this repo
git clone hhttps://github.com/JS-DevTools/chai-exec.git
-
Install dependencies
npm install
-
Run the tests
npm test
License
Chai Exec is 100% free and open-source, under the MIT license. Use it however you want.
This package is Treeware. If you use it in production, then we ask that you buy the world a tree to thank us for our work. By contributing to the Treeware forest you’ll be creating employment for local families and restoring wildlife habitats.
Big Thanks To
Thanks to these awesome companies for their support of Open Source developers ❤
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
dependency not pinned by hash detected -- score normalized to 3
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/CI-CD.yaml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/JS-DevTools/chai-exec/CI-CD.yaml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/CI-CD.yaml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/JS-DevTools/chai-exec/CI-CD.yaml/master?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/CI-CD.yaml:56: update your workflow using https://app.stepsecurity.io/secureworkflow/JS-DevTools/chai-exec/CI-CD.yaml/master?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/CI-CD.yaml:68: update your workflow using https://app.stepsecurity.io/secureworkflow/JS-DevTools/chai-exec/CI-CD.yaml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/CI-CD.yaml:82: update your workflow using https://app.stepsecurity.io/secureworkflow/JS-DevTools/chai-exec/CI-CD.yaml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/CI-CD.yaml:85: update your workflow using https://app.stepsecurity.io/secureworkflow/JS-DevTools/chai-exec/CI-CD.yaml/master?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/CI-CD.yaml:91: update your workflow using https://app.stepsecurity.io/secureworkflow/JS-DevTools/chai-exec/CI-CD.yaml/master?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/CI-CD.yaml:102: update your workflow using https://app.stepsecurity.io/secureworkflow/JS-DevTools/chai-exec/CI-CD.yaml/master?enable=pin
- Info: 0 out of 4 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 4 third-party GitHubAction dependencies pinned
- Info: 2 out of 2 npmCommand dependencies pinned
Reason
Found 0/30 approved changesets -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: no topLevel permission defined: .github/workflows/CI-CD.yaml:1
- Info: no jobLevel write permissions found
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no SAST tool detected
Details
- Warn: no pull requests merged into dev branch
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'master'
Reason
28 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92
- Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw
- Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c
- Warn: Project is vulnerable to: GHSA-ff7x-qrg7-qggm
- Warn: Project is vulnerable to: GHSA-2j2x-2gpw-g8fm
- Warn: Project is vulnerable to: GHSA-4q6p-r6v2-jvc5
- Warn: Project is vulnerable to: GHSA-ww39-953v-wcq6
- Warn: Project is vulnerable to: GHSA-pfrx-2q88-qq97
- Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj
- Warn: Project is vulnerable to: GHSA-qqgx-2p2h-9c37
- Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h
- Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9
- Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm
- Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv
- Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3
- Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h
- Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9
- Warn: Project is vulnerable to: GHSA-g6ww-v8xp-vmwg
- Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw
- Warn: Project is vulnerable to: GHSA-hxcc-f52p-wc94
- Warn: Project is vulnerable to: GHSA-4rq4-32rv-6wp6
- Warn: Project is vulnerable to: GHSA-64g7-mvw6-v9qj
- Warn: Project is vulnerable to: GHSA-7p7h-4mm5-852v
- Warn: Project is vulnerable to: GHSA-g3ch-rx76-35fx
- Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7
- Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh
Score
2.7
/10
Last Scanned on 2024-11-25
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More