Seed CLISeed CLI

Testing

Test your CLI commands by capturing stdout/stderr, exit codes, and temporary environment variables.

npm install @seedcli/testing

The testing module provides utilities for testing CLI commands in isolation by capturing output, checking exit codes, setting temporary environment variables with env(), creating mock Seed contexts with mockSeed(), and using createInterceptor() directly when needed.

Creating a Test CLI

import { build } from '@seedcli/core'
import { createTestCli } from '@seedcli/testing'
import { describe, test, expect } from 'vitest'

// Build your runtime as usual
const runtime = build('my-cli')
  .src('./src')
  .create()

describe('greet command', () => {
  test('greets the user', async () => {
    const cli = createTestCli(runtime)
    const result = await cli.run('greet Alice')

    expect(result.stdout).toContain('Hello, Alice!')
    expect(result.exitCode).toBe(0)
  })

  test('shows error for missing name', async () => {
    const cli = createTestCli(runtime)
    const result = await cli.run('greet')

    expect(result.stderr).toContain('required')
    expect(result.exitCode).toBe(1)
  })
})

Test Result

PropertyTypeDescription
stdoutstringCaptured standard output
stderrstringCaptured standard error
exitCodenumberProcess exit code

Builder Methods

createTestCli(runtime) returns a chainable builder with mockPrompt(), mockConfig(), mockSystem(), env(), and run().

In the current implementation, only env() affects run(). The mockPrompt(), mockConfig(), and mockSystem() methods are exposed on the builder but are not applied during execution yet.

Mock Seed

Create a mock seed context for unit testing command handlers directly. All module methods are no-ops by default — override specific properties when you need custom behavior:

import { mockSeed } from '@seedcli/testing'

test('deploy handler', async () => {
  const seed = mockSeed({
    args: { environment: 'staging' },
    flags: { force: true },
  })

  await deployCommand.run(seed)
})

MockSeedOptions

OptionTypeDescription
argsRecord<string, unknown>Mock argument values
flagsRecord<string, unknown>Mock flag values
commandNamestringCommand name (default: 'test')
brandstringCLI brand (default: 'test-cli')
versionstringVersion string (default: '0.0.0')

Output Interceptor

Capture console output and exit codes by intercepting console.log, console.error, and process.exitCode:

import { createInterceptor } from '@seedcli/testing'

test('output formatting', async () => {
  const interceptor = createInterceptor()
  interceptor.start()

  console.log('Hello, world!')
  console.error('Something went wrong')

  interceptor.stop()

  expect(interceptor.stdout).toContain('Hello, world!')
  expect(interceptor.stderr).toContain('Something went wrong')
  expect(interceptor.exitCode).toBe(0)
})

Note: createTestCli uses an interceptor internally — you don't need to create one manually when using createTestCli.

Testing Patterns

Testing flag validation

test('rejects invalid port', async () => {
  const result = await createTestCli(runtime).run('serve --port 99999')
  expect(result.stderr).toContain('Port must be between')
  expect(result.exitCode).toBe(1)
})

On this page