-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d0b3c69
commit d5bf7ae
Showing
1 changed file
with
230 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,236 @@ | ||
@oclif/test | ||
============ | ||
# @oclif/test | ||
|
||
test helpers for oclif components | ||
test helpers for oclif CLIs | ||
|
||
[![Version](https://img.shields.io/npm/v/@oclif/test.svg)](https://npmjs.org/package/@oclif/test) | ||
[![Known Vulnerabilities](https://snyk.io/test/npm/@oclif/test/badge.svg)](https://snyk.io/test/npm/@oclif/test) | ||
[![Downloads/week](https://img.shields.io/npm/dw/@oclif/test.svg)](https://npmjs.org/package/@oclif/test) | ||
[![License](https://img.shields.io/npm/l/@oclif/test.svg)](https://github.com/oclif/test/blob/main/package.json) | ||
|
||
## Usage | ||
|
||
`@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. | ||
|
||
The following are the features that `@oclif/test` adds to `fancy-test`. | ||
|
||
### `.loadConfig()` | ||
|
||
`.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. | ||
|
||
```typescript | ||
import {join} from 'node:path' | ||
import {expect, test} from '@oclif/test' | ||
|
||
const root = join(__dirname, 'fixtures/test-cli') | ||
test | ||
.loadConfig({root}) | ||
.stdout() | ||
.command(['foo:bar']) | ||
.it('should run the command from the given directory', (ctx) => { | ||
expect(ctx.stdout).to.equal('hello world!\n') | ||
expect(ctx.config.root).to.equal(root) | ||
const {name} = ctx.returned as {name: string} | ||
expect(name).to.equal('world') | ||
}) | ||
``` | ||
|
||
If you would like to run the same test without using `@oclif/test`: | ||
|
||
```typescript | ||
import {Config, ux} from '@oclif/core' | ||
import {expect} from 'chai' | ||
import {join} from 'node:path' | ||
import {SinonSandbox, SinonStub, createSandbox} from 'sinon' | ||
|
||
const root = join(__dirname, 'fixtures/test-cli') | ||
describe('non-fancy test', () => { | ||
let sandbox: SinonSandbox | ||
let config: Config | ||
let stdoutStub: SinonStub | ||
|
||
beforeEach(async () => { | ||
sandbox = createSandbox() | ||
stdoutStub = sandbox.stub(ux.write, 'stdout') | ||
config = await Config.load({root}) | ||
}) | ||
|
||
afterEach(async () => { | ||
sandbox.restore() | ||
}) | ||
|
||
it('should run command from the given directory', async () => { | ||
const {name} = await config.runCommand<{name: string}>('foo:bar') | ||
expect(stdoutStub.calledWith('hello world!\n')).to.be.true | ||
expect(config.root).to.equal(root) | ||
expect(name).to.equal('world') | ||
}) | ||
}) | ||
``` | ||
|
||
### `.command()` | ||
|
||
`.command()` let's you run a command from your CLI. | ||
|
||
```typescript | ||
import {expect, test} from '@oclif/test' | ||
|
||
describe('hello world', () => { | ||
test | ||
.stdout() | ||
.command(['hello:world']) | ||
.it('runs hello world cmd', (ctx) => { | ||
expect(ctx.stdout).to.contain('hello world!') | ||
}) | ||
}) | ||
``` | ||
|
||
For a [single command cli](https://oclif.io/docs/single_command_cli) you would provide `'.'` as the command. For instance: | ||
|
||
```typescript | ||
import {expect, test} from '@oclif/test' | ||
|
||
describe('hello world', () => { | ||
test | ||
.stdout() | ||
.command(['.']) | ||
.it('runs hello world cmd', (ctx) => { | ||
expect(ctx.stdout).to.contain('hello world!') | ||
}) | ||
}) | ||
``` | ||
|
||
If you would like to run the same test without using `@oclif/test`: | ||
|
||
```typescript | ||
import {Config, ux} from '@oclif/core' | ||
import {expect} from 'chai' | ||
import {SinonSandbox, SinonStub, createSandbox} from 'sinon' | ||
|
||
describe('non-fancy test', () => { | ||
let sandbox: SinonSandbox | ||
let config: Config | ||
let stdoutStub: SinonStub | ||
|
||
beforeEach(async () => { | ||
sandbox = createSandbox() | ||
stdoutStub = sandbox.stub(ux.write, 'stdout') | ||
config = await Config.load({root: process.cwd()}) | ||
}) | ||
|
||
afterEach(async () => { | ||
sandbox.restore() | ||
}) | ||
|
||
it('should run command', async () => { | ||
// use '.' for a single command CLI | ||
const {name} = await config.runCommand<{name: string}>('hello:world') | ||
expect(stdoutStub.calledWith('hello world!\n')).to.be.true | ||
expect(name).to.equal('world') | ||
}) | ||
}) | ||
``` | ||
|
||
### `.exit()` | ||
|
||
`.exit()` let's you test that a command exited with a certain exit code. | ||
|
||
```typescript | ||
import {join} from 'node:path' | ||
import {expect, test} from '@oclif/test' | ||
|
||
describe('exit', () => { | ||
test | ||
.loadConfig() | ||
.stdout() | ||
.command(['hello:world', '--code=101']) | ||
.exit(101) | ||
.do((output) => expect(output.stdout).to.equal('exiting with code 101\n')) | ||
.it('should exit with code 101') | ||
}) | ||
``` | ||
|
||
If you would like to run the same test without using `@oclif/test`: | ||
|
||
```typescript | ||
import {Config, Errors, ux} from '@oclif/core' | ||
import {expect} from 'chai' | ||
import {SinonSandbox, createSandbox} from 'sinon' | ||
|
||
describe('non-fancy test', () => { | ||
let sandbox: SinonSandbox | ||
let config: Config | ||
|
||
beforeEach(async () => { | ||
sandbox = createSandbox() | ||
sandbox.stub(ux.write, 'stdout') | ||
config = await Config.load({root: process.cwd()}) | ||
}) | ||
|
||
afterEach(async () => { | ||
sandbox.restore() | ||
}) | ||
|
||
it('should run command from the given directory', async () => { | ||
try { | ||
await config.runCommand('.') | ||
throw new Error('Expected CLIError to be thrown') | ||
} catch (error) { | ||
if (error instanceof Errors.CLIError) { | ||
expect(error.oclif.exit).to.equal(101) | ||
} else { | ||
throw error | ||
} | ||
} | ||
}) | ||
}) | ||
``` | ||
|
||
### `.hook()` | ||
|
||
`.hook()` let's you test a hook in your CLI. | ||
|
||
```typescript | ||
import {join} from 'node:path' | ||
|
||
import {expect, test} from '@oclif/test' | ||
|
||
const root = join(__dirname, 'fixtures/test-cli') | ||
|
||
describe('hooks', () => { | ||
test | ||
.loadConfig({root}) | ||
.stdout() | ||
.hook('foo', {argv: ['arg']}, {root}) | ||
.do((output) => expect(output.stdout).to.equal('foo hook args: arg\n')) | ||
.it('should run hook') | ||
}) | ||
``` | ||
|
||
If you would like to run the same test without using `@oclif/test`: | ||
|
||
```typescript | ||
import {Config, ux} from '@oclif/core' | ||
import {expect} from 'chai' | ||
import {SinonSandbox, SinonStub, createSandbox} from 'sinon' | ||
|
||
describe('non-fancy test', () => { | ||
let sandbox: SinonSandbox | ||
let config: Config | ||
let stdoutStub: SinonStub | ||
|
||
beforeEach(async () => { | ||
sandbox = createSandbox() | ||
stdoutStub = sandbox.stub(ux.write, 'stdout') | ||
config = await Config.load({root: process.cwd()}) | ||
}) | ||
|
||
afterEach(async () => { | ||
sandbox.restore() | ||
}) | ||
|
||
it('should run hook', async () => { | ||
const {name} = await config.runHook('foo', {argv: ['arg']}) | ||
expect(stdoutStub.calledWith('foo hook args: arg\n')).to.be.true | ||
}) | ||
}) | ||
``` |