modelcontextprotocol / modelcontextprotocol/conformance
test: programmatic CLI harness for src/index.ts action handlers
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 127
- Forks
- 101
- Avg merge
- 6d 1h
- Merged PRs (30d)
- 7
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(); gateprogram.parse()onrequire.main === module(or move to abin.tsshim) - Shared test helpers:
process.exit/console.errorspies, temp-file fixture writer - Initial coverage:
authorization --file(valid file, missingurl, unknown key, bad JSON, neither--urlnor--file) - Follow-on: extend to
server/clientflag validation as needed
Related: #360, #225
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
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.
Assessment
- Tech stack
- typescript
- Domain
- cli, testing
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 67/100