test helpers for oclif components


Keywords
oclif
License
MIT
Install
npm install @oclif/test@1.2.6

Documentation

@oclif/test

test helpers for oclif CLIs

Version Downloads/week License

Usage

@oclif/test is an extension of fancy-test. Please see the fancy-test documentation 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 instance. This instance will be available on the ctx variable that's provided in the callback.

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:

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.

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 you would provide '.' as the command. For instance:

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:

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.

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:

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.

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:

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
  })
})