Skip to content

test: extract cli pure functions + CLI test suite (node:test) - #5

Closed
4222222 wants to merge 2 commits into
LouisYang841:mainfrom
4222222:feat/cli-tests
Closed

test: extract cli pure functions + CLI test suite (node:test)#5
4222222 wants to merge 2 commits into
LouisYang841:mainfrom
4222222:feat/cli-tests

Conversation

@4222222

@4222222 4222222 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

改动

为可测性重构(零行为变化)

  • cli/args.js(新):parseArgs() 纯函数——原 cli.js 顶层的 argv/provider/model 解析
  • cli/env.js(新):loadEnvFiles() + persistCredential() 纯函数
  • cli/cli.js:改为调用上述模块,行为不变
  • cli/skill-scanner.js:导出 parseFrontmatter/discover

测试套件(node:test,零新依赖)

  • 单测:args(8)/ env(7)/ skill-scanner(6)
  • 集成测试(fake LLM 驱动,无 key 全跑,不再 skip):
    • 管道多行输入全部被消费(不吞行)
    • 退出前 flush 写盘(200ms 批窗不丢)
    • 裸 /provider 不 fall-through 给模型

测试驱动的 3 个真实 bug 修复

  1. EOF 竞态:管道 stdin 在 REPL 就绪前关闭会丢弃已排队输入——close 时 defer 到队列排空
  2. /exit fall-through:exit 命令匹配后未 return,把 "/exit" 当 prompt 发给模型(裸命令 fall-through 变体)
  3. gracefulExit 500ms 猜测:改为 await ctx.sessionPersistence.flush() 完成再退出

新功能:DSH_FAKE_LLM 测试模式

FakeAdapter extends LlmAdapter(脚本化回复,无网络无 key)——DSH_FAKE_LLM=1 DSH_PROVIDER=fake 驱动完整 CLI 会话,让集成测试在 CI 里真实运行。

验证

  • conformance:Node + QuickJS 双引擎 IDENTICAL(114 events)
  • 测试:25/25 pass,0 skip,0 fail
  • CI:Run CLI tests 步骤已加入 conformance workflow

  • Node recursive mkdirSync 在 procfs 路径挂起(非快速失败)——不可写目标用例用 ENOTDIR fixture
  • 纯命令会话(只有 /stats /exit)无事件可写、不落盘——flush 测试先有对话再退出

4222222 added 2 commits August 14, 2026 17:50
Extract parseArgs (cli/args.js) and env loading/persistence
(cli/env.js) from cli.js as pure functions — behavior identical,
enabling unit tests for logic that was previously top-level-only.
Export parseFrontmatter/discover from skill-scanner.js (1-line each).

Add tests/ with node:test (zero deps):
- args: --resume absence, provider defaults, model position (8)
- env: KEY=VALUE parsing, no-override, idempotent persistence (7)
- skill-scanner: frontmatter scalars, discovery (6)
- CLI integration: --sessions boot smoke, EOF graceful exit;
  full-session cases (piped input, flush, bare /provider) auto-skip
  without an API key

Verification: conformance gate still IDENTICAL on both Node and
QuickJS (114 events); 23 pass / 3 skip / 0 fail locally.
CI now runs the suite after building the CLI.

Note: Node recursive mkdirSync hangs on procfs paths (not a fast
failure) — tests use an ENOTDIR fixture instead.
…h, flush await)

Add a scripted FakeAdapter (extends LlmAdapter, DSH_FAKE_LLM=1 +
DSH_PROVIDER=fake) so the CLI integration tests exercise real
sessions with no network and no API key — the three SKILL.md CLI
pitfalls now run in CI instead of being skipped.

Bug fixes found by the new tests:
1. EOF race: piped stdin closing before the REPL armed dropped
   queued lines (close handler exited while lineQueue still held
   input). Fix: defer exit until the queue drains; ask loop exits
   when EOF + drained.
2. /exit fall-through: the exit command matched but did not return,
   so "/exit" was sent to the model as a prompt during the 500ms
   exit grace (bare-command fall-through, SKILL.md L270 variant).
3. gracefulExit guessed 500ms for the JSONL flush; now awaits
   ctx.sessionPersistence.flush() before exiting (SKILL.md L304).

Tests: 25/25 pass (0 skip) — piped multi-line consumption, flush
writes session files, bare /provider never reaches the model.
Conformance still IDENTICAL on Node + QuickJS (114 events).
LouisYang841 pushed a commit that referenced this pull request Aug 16, 2026
Equivalent of PR #5, adapted to current main:
- add scripted DSH_FAKE_LLM fake provider so CLI sessions run without keys
- record stdin EOF during boot and exit only when idle and the line queue
  is drained, preserving queued piped input
- add integration coverage for piped input, /provider interception,
  /exit fall-through, flush-before-exit, and --sessions
@LouisYang841

Copy link
Copy Markdown
Owner

Implemented the equivalent change directly on main (commit f1d9440):

  • scripted DSH_FAKE_LLM=1 + DSH_PROVIDER=fake provider for keyless CLI integration tests
  • 6 integration tests covering piped multi-line input, bare /provider, /exit fall-through, flush-before-exit, EOF-queued input, and --sessions
  • finished the stdin EOF-race fix: EOF is recorded during boot and exit waits until the line queue drains

I intentionally did not extract cli/args.js/cli/env.js because current main has a more complete parser (FLAG_VALUE_ARGS, modes/reasoning/config); the credential CWD fallback finding was already fixed on main. CodeRabbit findings from the first pass were addressed; a second pass hit the plan rate limit and can be re-run later. Closing this PR as superseded — thanks for the contribution!

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.

2 participants