chore(test): migrate from Jest to Vitest#236
Merged
Merged
Conversation
- Replace jest+ts-jest with vitest+@vitest/coverage-v8 - vitest.config.ts mirrors the previous Jest config (Node env, same test glob, v8 coverage at 70% thresholds) - Test API stays Jest-compatible via 'globals: true': describe/it/expect unchanged, jest.fn/jest.mock/jest.spyOn renamed to vi.* equivalents - Type annotations: jest.SpyInstance -> MockInstance, jest.Mock -> Mock, imported as types from 'vitest' in the four files that use them - Convert arrow-function mockImplementation factories to regular functions in 3 places (factory/transports/keychain tests) so 'new MockedClass()' works under vitest (arrow functions are not constructable) - Use vi.hoisted() in grep.test.ts where the chalk mock factory referenced a const declared after vi.mock() - Drop the chalk/ora transformIgnorePatterns workarounds; vitest runs ESM natively - Update test/README.md and the keychain.ts comment to drop Jest references Build, lint, and full unit suite (581 tests) pass locally. CI workflow unchanged (still 'pnpm run test:unit').
MQ37
added a commit
that referenced
this pull request
May 18, 2026
Two-piece pattern (kubectl/gh/cobra-style): - 'mcpc completion <bash|zsh|fish>' prints a thin shell script that registers a completion function for the user's shell. - 'mcpc __complete -- <words...> <partial>' is a hidden subcommand the script calls on every TAB. Returns candidates on stdout (one per line) plus an optional ':<bitflag>' directive line. - 'mcpc completion install [shell]' auto-detects the user's shell and writes the script to the standard path. Completes top-level commands, session subcommands, @session names from ~/.mcpc/sessions.json, auth-server hosts, log levels, all known flags (introspected from Commander's tree at runtime so there is no static drift), and tool / resource URI / prompt names for connected sessions. Tool/resource/prompt names are mirrored to ~/.mcpc/completion/<session>.json whenever the user runs 'tools-list' / 'resources-list' / 'prompts-list', so TAB completion is fast and never triggers network calls or OAuth flows. The cache file is removed alongside the session by 'mcpc clean sessions'. createTopLevelProgram, createSessionProgram, and registerSessionCommands are now exported from src/cli/index.ts so commands/completion.ts can walk the Commander tree to extract option flags. index.ts no longer self-runs on import; bin/mcpc calls mod.run() explicitly, and a small direct-run guard supports 'tsx src/cli/index.ts' invocation for the README-help test. Reading package.json via JSON import attribute replaces the old createRequire(import.meta.url) pattern. Stacks on top of #236 (Jest -> Vitest migration); the vitest move removes the need for chalk mocking and the src/cli/main.ts split that earlier revisions of this branch carried.
MQ37
added a commit
that referenced
this pull request
May 18, 2026
Two-piece pattern (kubectl/gh/cobra-style): - 'mcpc completion <bash|zsh|fish>' prints a thin shell script that registers a completion function for the user's shell. - 'mcpc __complete -- <words...> <partial>' is a hidden subcommand the script calls on every TAB. Returns candidates on stdout (one per line) plus an optional ':<bitflag>' directive line. - 'mcpc completion install [shell]' auto-detects the user's shell and writes the script to the standard path. Completes top-level commands, session subcommands, @session names from ~/.mcpc/sessions.json, auth-server hosts, log levels, all known flags (introspected from Commander's tree at runtime so there is no static drift), and tool / resource URI / prompt names for connected sessions. Tool/resource/prompt names are mirrored to ~/.mcpc/completion/<session>.json whenever the user runs 'tools-list' / 'resources-list' / 'prompts-list', so TAB completion is fast and never triggers network calls or OAuth flows. The cache file is removed alongside the session by 'mcpc clean sessions'. createTopLevelProgram, createSessionProgram, and registerSessionCommands are now exported from src/cli/index.ts so commands/completion.ts can walk the Commander tree to extract option flags. index.ts no longer self-runs on import; bin/mcpc calls mod.run() explicitly, and a small direct-run guard supports 'tsx src/cli/index.ts' invocation for the README-help test. Reading package.json via JSON import attribute replaces the old createRequire(import.meta.url) pattern. Stacks on top of #236 (Jest -> Vitest migration); the vitest move removes the need for chalk mocking and the src/cli/main.ts split that earlier revisions of this branch carried.
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Jest's ESM story is rough on this repo: pure-ESM deps like
chalkandoraneedtransformIgnorePatternsworkarounds,import.metainsrc/cli/index.tstrips the CJS transform when any test transitively loads it, andjest-runtime@30.4.2has aclearMocksOnScoperegression that breaks unit tests on some local setups. Came up while opening #234.Solution
Swap Jest + ts-jest for Vitest +
@vitest/coverage-v8. The API stays Jest-compatible (describe/it/expect, plusvi.fn/vi.mockin place ofjest.fn/jest.mock) so the test bodies are mostly unchanged. CI script is identical (pnpm run test:unit).Full suite (581 tests) goes from ~5 s under ts-jest to ~1 s with vitest.
Worth your attention
globals: trueinvitest.config.tskeepsdescribe/it/expectavailable without import churn; only the four files that usedjest.SpyInstance/jest.Mocktypes now importMockInstance/Mockfrom'vitest'.mockImplementationfactories were converted to regular functions infactory.test.ts,transports.test.ts, andkeychain.test.ts— vitest's stricter constructor-call semantics reject arrows as constructors (new (() => ...)throws "not a constructor"). Functionally equivalent.vi.hoisted()ingrep.test.ts— vitest hoistsvi.mockcalls above localconstdeclarations more aggressively than Jest, so the chalk-identity helpers had to move into a hoisted block.transformIgnorePatternsforchalk/cli-table3is gone — vitest runs ESM natively, so the allow-list is no longer needed. New ESM deps (e.g.ora) will Just Work without config tweaks.Follow-up
feat(cli): add shell tab-completion) is now stacked on top of this PR. Once this lands, feat(cli): add shell tab-completion (bash, zsh, fish) #234 will be ready for review on its own merits.