Skip to content

test(cli): add CLI-level coverage for log and timeline option parsing - #46

Closed
mvanhorn wants to merge 3 commits into
mex-memory:mainfrom
mvanhorn:test/cli-option-parsing-43
Closed

test(cli): add CLI-level coverage for log and timeline option parsing#46
mvanhorn wants to merge 3 commits into
mex-memory:mainfrom
mvanhorn:test/cli-option-parsing-43

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

What

Adds CLI-level test coverage for the mex log and mex timeline Commander wiring so the option-parsing risks called out in the PR #39 Copilot review have explicit regression tests. Exports parseIntArg, parsePositiveIntArg, and program from src/cli.ts, and gates the auto-parse on the module being the main entry point so the new tests can import without consuming the test runner's argv.

Why

Closes #43. The PR #39 review flagged that mex log / mex timeline had module-level tests for the underlying runners but no coverage of the actual Commander wiring or option parsing - meaning a future tweak to --type, repeated --file, or --limit's positive-integer guard could silently break the CLI surface without any test signal. The new suite locks down those exact behaviors against the same program instance the binary uses, so changes to the option declarations show up in CI.

Type of change

  • Refactor
  • Tests / coverage

The runtime behavior of mex log and mex timeline is unchanged; the production bin still runs program.parse() on invocation (the new main-module guard evaluates true when run via dist/cli.js). The only export changes are the two parser helpers and program itself, which were previously module-private.

How to test

  1. npx vitest run test/cli.test.ts - 13 cases pass.
  2. npm test - full suite still green except the pre-existing test/tui.test.ts failure (missing react in the test environment, unrelated to this change).
  3. npm run build - tsup build still produces dist/cli.js with the shebang banner and dist/index.js library entry; running node dist/cli.js timeline --limit abc still errors at the option parser as before.

Checklist

  • Tests pass (npm test)
  • No breaking changes (or documented below)
  • Tested locally with a real project

Source for the original review: #39 (comment)

Closes mex-memory#43.

Adds direct tests for the Commander wiring of mex log / mex timeline so
the option-parsing risks called out in the PR mex-memory#39 review have explicit
regression coverage:

- parseIntArg / parsePositiveIntArg are now exported and unit-tested for
  the accept and reject paths (non-negative integers, positive integers,
  negative input, non-numeric input, zero).
- program is exported and parsed via program.parseAsync so the test
  exercises the same wiring path the production binary uses. findConfig
  and the events runners are mocked so the tests don't touch disk.
- mex log: covers single --file pass-through, repeated --file
  accumulator order, default --type='note', and the action's
  error-propagation path when runLog rejects.
- mex timeline: covers --limit parsed via parsePositiveIntArg, plus
  --json / --since / --type / --limit thread-through.

Auto-running program.parse() is now gated on this module being the main
entrypoint so test imports don't trip Commander on test runner argv.

@theDakshJaitly theDakshJaitly left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Matt — tests pass locally (13/13), build is clean, and dist/cli.js still rejects bad --limit the same as before. The coverage gap from #39 is closed nicely. Two small things to fix before merge:

1. Main-module guard isn't portable (src/cli.ts:303-310)

import.meta.url ===
(typeof process !== "undefined" && process.argv[1]
  ? new URL(`file://${process.argv[1]}`).href
  : undefined)

Hand-building file://${process.argv[1]} breaks on Windows paths (C:\…) and any path with spaces or unicode — no percent-encoding. Node ships the canonical helper, and engines.node >= 20 means it's always available:

import { pathToFileURL } from "node:url";
// …
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  program.parse();
}

macOS/Linux with ASCII paths happens to work today, but this'll bite the first Windows user or anyone npm link-ing from a path with a space.

2. Unused import (test/cli.test.ts:3)

import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";

writeFileSync is never referenced — drop it.

Optional nits (non-blocking)

  • The tmpDir / .mex/events scaffold in beforeEach is dead setup since every test mocks runLog/runTimeline. Could shrink to just the mexConfig object.
  • program is a Commander singleton with accumulating state across parseAsync calls — fine here since each test hits a distinct subcommand, but worth keeping in mind as this file grows.
  • Test "propagates an invalid --type" really exercises the generic action-handler error path, not anything --type-specific. Title is slightly misleading but the assertion is fine.

Happy to re-review once #1 and #2 are in.

@advancedresearcharray

Copy link
Copy Markdown
Contributor

Addressed both requested changes:

1. Portable main-module guard (src/cli.ts)

  • Import pathToFileURL from node:url
  • Replace hand-built file://${process.argv[1]} comparison with pathToFileURL(process.argv[1]).href

2. Unused import (test/cli.test.ts)

  • Dropped unused writeFileSync from the node:fs import

Verified locally: npx vitest run test/cli.test.ts — 13/13 passing.

Commit: https://github.com/advancedresearcharray/mex/commit/3f6e17d (branch test/cli-option-parsing-43)

@mvanhorn — ready to cherry-pick or merge that commit onto this PR branch when convenient.

@advancedresearcharray

Copy link
Copy Markdown
Contributor

Addressed the review feedback from @theDakshJaitly — with one important context update:

Test coverage already merged via #47. The CLI-level mex log / mex timeline option-parsing tests from this PR landed on main in May (using the buildProgram() approach rather than exporting the program singleton). That closes the original #43 coverage gap.

Remaining review item (portable main-module guard) is in a rebased follow-up: #67#67

Changes in #67 (on current main):

  1. Import pathToFileURL from node:url
  2. Replace unconditional program.parse() with the portable main-module guard:
    if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { program.parse(); }

The unused writeFileSync import nit no longer applies — current main test/cli.test.ts (from #47) doesn't have it.

Verified locally: npx vitest run test/cli.test.ts — 11/11 passing; npm run typecheck — clean.

Could not push directly to this branch (403 to mvanhorn/mex). #46 can be closed in favor of #47 + #67. Also opened mvanhorn/mex#2 earlier as a cherry-pick path for the original branch if preferred.

@advancedresearcharray

Copy link
Copy Markdown
Contributor

Both blocking review items are implemented on branch test/cli-option-parsing-43:

Commit: https://github.com/advancedresearcharray/mex/commit/0956383

  1. Portable main-module guard (src/cli.ts) — pathToFileURL(process.argv[1]).href replaces the hand-built file:// URL.
  2. Unused import (test/cli.test.ts) — writeFileSync removed.

Verified: npx vitest run test/cli.test.ts — 13/13 passing.

Could not push directly to mvanhorn/mex:test/cli-option-parsing-43 (403). Opened mvanhorn/mex#3 so @mvanhorn can merge the fix onto this PR's head branch; @theDakshJaitly can also push via maintainer edits if preferred.

Note: CLI test coverage from this PR already landed on main via #47 (buildProgram() approach). The remaining portable guard for current main is in #67. Once #3 is merged here (or #46 is closed in favor of #47 + #67), the review feedback is fully addressed.

@advancedresearcharray

Copy link
Copy Markdown
Contributor

Updated fix commit (no co-author trailer): https://github.com/advancedresearcharray/mex/commit/7bf6508mvanhorn/mex#3 tracks the same branch for merging onto this PR's head.

Addresses review on mex-memory#46: replace hand-built file:// URL with Node's
pathToFileURL helper for Windows/unicode path safety, and drop unused
writeFileSync import from test/cli.test.ts.
@advancedresearcharray

Copy link
Copy Markdown
Contributor

Both blocking review items are implemented and verified on advancedresearcharray/mex@test/cli-option-parsing-43 (commit 20d66e4):

  1. src/cli.ts — import pathToFileURL from node:url; gate program.parse() with if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href).
  2. test/cli.test.ts — drop unused writeFileSync import.

npx vitest run test/cli.test.ts — 13/13 passing.

Could not push to mvanhorn/mex:test/cli-option-parsing-43 (403). To land this on the PR head branch, either:

  • @theDakshJaitly — maintainer edit push (allowed on this PR):
    git fetch https://github.com/advancedresearcharray/mex.git test/cli-option-parsing-43
    git push https://github.com/mvanhorn/mex.git FETCH_HEAD:test/cli-option-parsing-43
  • @mvanhorn — merge mvanhorn/mex#3 (same commit, already mergeable).

Once the head branch includes 20d66e4, both requested fixes are complete and this is ready for re-review.

@mvanhorn

mvanhorn commented Jun 6, 2026

Copy link
Copy Markdown
Contributor Author

Merged @advancedresearcharray's fix onto the PR head (20d66e4, merge 661b3d1). src/cli.ts now gates program.parse() with pathToFileURL(process.argv[1]).href, and the unused writeFileSync import is removed from test/cli.test.ts. Verified locally with npx vitest run test/cli.test.ts: 13/13 passing. Ready for re-review.

@theDakshJaitly

Copy link
Copy Markdown
Collaborator

Thanks @mvanhorn. Closing this as superseded, with a clear note on what happened:

That leaves this PR with nothing unique left, and it has since gone conflicting with main. So this is closed in favor of #47 (yours, merged) + #67. Thanks again for the coverage work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add CLI-level tests for log and timeline option parsing

3 participants