UNPKG

6.17 kBMarkdownView Raw
1# @oclif/test
2
3test helpers for oclif CLIs
4
5[![Version](https://img.shields.io/npm/v/@oclif/test.svg)](https://npmjs.org/package/@oclif/test)
6[![Downloads/week](https://img.shields.io/npm/dw/@oclif/test.svg)](https://npmjs.org/package/@oclif/test)
7[![License](https://img.shields.io/npm/l/@oclif/test.svg)](https://github.com/oclif/test/blob/main/package.json)
8
9## Usage
10
11`@oclif/test` is an extension of [fancy-test](https://github.com/oclif/fancy-test). Please see the [fancy-test documentation](https://github.com/oclif/fancy-test#fancy-test) for all the features that are available.
12
13The following are the features that `@oclif/test` adds to `fancy-test`.
14
15### `.loadConfig()`
16
17`.loadConfig()` creates and returns a new [`Config`](https://github.com/oclif/core/blob/main/src/config/config.ts) instance. This instance will be available on the `ctx` variable that's provided in the callback.
18
19```typescript
20import {join} from 'node:path'
21import {expect, test} from '@oclif/test'
22
23const root = join(__dirname, 'fixtures/test-cli')
24test
25 .loadConfig({root})
26 .stdout()
27 .command(['foo:bar'])
28 .it('should run the command from the given directory', (ctx) => {
29 expect(ctx.stdout).to.equal('hello world!\n')
30 expect(ctx.config.root).to.equal(root)
31 const {name} = ctx.returned as {name: string}
32 expect(name).to.equal('world')
33 })
34```
35
36If you would like to run the same test without using `@oclif/test`:
37
38```typescript
39import {Config, ux} from '@oclif/core'
40import {expect} from 'chai'
41import {join} from 'node:path'
42import {SinonSandbox, SinonStub, createSandbox} from 'sinon'
43
44const root = join(__dirname, 'fixtures/test-cli')
45describe('non-fancy test', () => {
46 let sandbox: SinonSandbox
47 let config: Config
48 let stdoutStub: SinonStub
49
50 beforeEach(async () => {
51 sandbox = createSandbox()
52 stdoutStub = sandbox.stub(ux.write, 'stdout')
53 config = await Config.load({root})
54 })
55
56 afterEach(async () => {
57 sandbox.restore()
58 })
59
60 it('should run command from the given directory', async () => {
61 const {name} = await config.runCommand<{name: string}>('foo:bar')
62 expect(stdoutStub.calledWith('hello world!\n')).to.be.true
63 expect(config.root).to.equal(root)
64 expect(name).to.equal('world')
65 })
66})
67```
68
69### `.command()`
70
71`.command()` let's you run a command from your CLI.
72
73```typescript
74import {expect, test} from '@oclif/test'
75
76describe('hello world', () => {
77 test
78 .stdout()
79 .command(['hello:world'])
80 .it('runs hello world cmd', (ctx) => {
81 expect(ctx.stdout).to.contain('hello world!')
82 })
83})
84```
85
86For a [single command cli](https://oclif.io/docs/single_command_cli) you would provide `'.'` as the command. For instance:
87
88```typescript
89import {expect, test} from '@oclif/test'
90
91describe('hello world', () => {
92 test
93 .stdout()
94 .command(['.'])
95 .it('runs hello world cmd', (ctx) => {
96 expect(ctx.stdout).to.contain('hello world!')
97 })
98})
99```
100
101If you would like to run the same test without using `@oclif/test`:
102
103```typescript
104import {Config, ux} from '@oclif/core'
105import {expect} from 'chai'
106import {SinonSandbox, SinonStub, createSandbox} from 'sinon'
107
108describe('non-fancy test', () => {
109 let sandbox: SinonSandbox
110 let config: Config
111 let stdoutStub: SinonStub
112
113 beforeEach(async () => {
114 sandbox = createSandbox()
115 stdoutStub = sandbox.stub(ux.write, 'stdout')
116 config = await Config.load({root: process.cwd()})
117 })
118
119 afterEach(async () => {
120 sandbox.restore()
121 })
122
123 it('should run command', async () => {
124 // use '.' for a single command CLI
125 const {name} = await config.runCommand<{name: string}>('hello:world')
126 expect(stdoutStub.calledWith('hello world!\n')).to.be.true
127 expect(name).to.equal('world')
128 })
129})
130```
131
132### `.exit()`
133
134`.exit()` let's you test that a command exited with a certain exit code.
135
136```typescript
137import {join} from 'node:path'
138import {expect, test} from '@oclif/test'
139
140describe('exit', () => {
141 test
142 .loadConfig()
143 .stdout()
144 .command(['hello:world', '--code=101'])
145 .exit(101)
146 .do((output) => expect(output.stdout).to.equal('exiting with code 101\n'))
147 .it('should exit with code 101')
148})
149```
150
151If you would like to run the same test without using `@oclif/test`:
152
153```typescript
154import {Config, Errors, ux} from '@oclif/core'
155import {expect} from 'chai'
156import {SinonSandbox, createSandbox} from 'sinon'
157
158describe('non-fancy test', () => {
159 let sandbox: SinonSandbox
160 let config: Config
161
162 beforeEach(async () => {
163 sandbox = createSandbox()
164 sandbox.stub(ux.write, 'stdout')
165 config = await Config.load({root: process.cwd()})
166 })
167
168 afterEach(async () => {
169 sandbox.restore()
170 })
171
172 it('should run command from the given directory', async () => {
173 try {
174 await config.runCommand('.')
175 throw new Error('Expected CLIError to be thrown')
176 } catch (error) {
177 if (error instanceof Errors.CLIError) {
178 expect(error.oclif.exit).to.equal(101)
179 } else {
180 throw error
181 }
182 }
183 })
184})
185```
186
187### `.hook()`
188
189`.hook()` let's you test a hook in your CLI.
190
191```typescript
192import {join} from 'node:path'
193
194import {expect, test} from '@oclif/test'
195
196const root = join(__dirname, 'fixtures/test-cli')
197
198describe('hooks', () => {
199 test
200 .loadConfig({root})
201 .stdout()
202 .hook('foo', {argv: ['arg']}, {root})
203 .do((output) => expect(output.stdout).to.equal('foo hook args: arg\n'))
204 .it('should run hook')
205})
206```
207
208If you would like to run the same test without using `@oclif/test`:
209
210```typescript
211import {Config, ux} from '@oclif/core'
212import {expect} from 'chai'
213import {SinonSandbox, SinonStub, createSandbox} from 'sinon'
214
215describe('non-fancy test', () => {
216 let sandbox: SinonSandbox
217 let config: Config
218 let stdoutStub: SinonStub
219
220 beforeEach(async () => {
221 sandbox = createSandbox()
222 stdoutStub = sandbox.stub(ux.write, 'stdout')
223 config = await Config.load({root: process.cwd()})
224 })
225
226 afterEach(async () => {
227 sandbox.restore()
228 })
229
230 it('should run hook', async () => {
231 const {name} = await config.runHook('foo', {argv: ['arg']})
232 expect(stdoutStub.calledWith('foo hook args: arg\n')).to.be.true
233 })
234})
235```