Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

test: programmatic CLI harness for src/index.ts action handlers

Open
#363 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
67/100
Issue type
Refactor
Clarity
Mostly clear
Activity status
Quiet
Tech stack
typescript
Domain
cli, testing

Research direction

Start with src/index.ts and trace how Commander registers and parses the action handlers. Extract createProgram(), add the process.exit and console.error test helpers, and stub runner/authorization-server as described. Done means in-process tests cover authorization --file with valid, missing-url, unknown-key, bad-JSON, and missing-source cases.

Written by the indexing model from the issue text.

Description

src/index.ts currently has zero test coverage of its commander action handlers — all testing happens at the scenario/runner layer. This came up in #360: we wanted to test that authorization --file <path> rejects an invalid settings file, but there's no way to exercise the real codepath without either spawning a child process or duplicating the merge logic in the test (which can drift).

Proposed approach

Refactor src/index.ts so the Command can be constructed without auto-parsing:

// src/index.ts
export function createProgram(): Command { /* register all subcommands */ }

// only parse when run as the bin entrypoint
if (require.main === module) createProgram().parse();

Tests then drive it in-process:

const exit = vi.spyOn(process, 'exit').mockImplementation(((c) => {
  throw new Error(`exit:${c}`);
}) as never);
const stderr = vi.spyOn(console, 'error').mockImplementation(() => {});
vi.mock('./runner/authorization-server');  // stub the network layer

await expect(
  createProgram().exitOverride().parseAsync(
    ['node', 'x', 'authorization', '--file', tmpInvalidJson]
  )
).rejects.toThrow('exit:1');
expect(stderr.mock.calls.join('\n')).toContain("Invalid settings file");

Why not spawn the binary

execa against dist/ is the strongest guarantee but is slow (process per case) and depends on a build step. Programmatic .parseAsync() is fast enough to cover every flag/validation path and matches how commander's own suite tests itself.

Scope

  • Extract createProgram(); gate program.parse() on require.main === module (or move to a bin.ts shim)
  • Shared test helpers: process.exit / console.error spies, temp-file fixture writer
  • Initial coverage: authorization --file (valid file, missing url, unknown key, bad JSON, neither --url nor --file)
  • Follow-on: extend to server / client flag validation as needed

Related: #360, #225

Dominant language
TypeScript
Stars
127
Forks
101
Avg merge
4d 7h
Merged PRs (30d)
6

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from modelcontextprotocol/conformance

All issues in modelcontextprotocol/conformance

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.