test: [ENG-3025] add command-level tests for Curate continuation orchestration
Closes the four-round-carryover finding by pinning the load-bearing
orchestration invariants. Three consecutive review rounds had each
introduced a subtle behavioral change in the emitter / orchestration
surface caught only by manual interactive verification:
abd82ba — deferred unlink until after dispatch
316ece0 — switched cleanup-failure from warnings[] to errors[]
60b613d — made text-mode iterate companion errors[] on the done branch
Each would have been caught by a small command-level test with stubbed
seams. Adding both the seams and the tests.
Refactor (src/oclif/commands/curate/index.ts):
- Extract the dispatch path into a protected dispatchContinuation()
method that wraps withDaemonRetry + continueSession. Throws on
daemon-error so the caller can map to a daemon-error envelope AND
skip the post-success unlink — that ordering is the load-bearing
invariant.
- Extract loadCurateResponseFile, deleteCurateResponseFile,
peekCurateSession, and resolveProjectRoot calls into protected
methods so a TestableCurate subclass can inject in-memory doubles.
- Switch the removed-flag check from process.argv.slice(2) to
this.argv so testable subclasses scope to their own argv (mocha's
--timeout was leaking into the curate flag parser otherwise).
New test file (test/commands/curate/index.test.ts) — 13 tests pinning:
flag combinations:
- --response + --response-file together
- --delete-response-file without --response-file
- continuation-only flags on kickoff (no --session)
pre-dispatch local validation:
- whitespace payload → empty-response, no dispatch
- invalid JSON → invalid-response-format, no dispatch
- unknown session → unknown-session, no unlink
- --response-file read error → response-file-read-error, no dispatch
daemon-error path preserves the response file (regression abd82ba):
- dispatch throws → daemon-error envelope, NO unlink call fired
cleanup-failure-post-success → done with appended errors[] (316ece0):
- done + unlink throws → ok=true, status=done, errors[0].kind=response-file-delete-error
- failed + unlink throws → existing errors preserved, cleanup appended
- done + unlink succeeds → clean done envelope (no companion errors)
text-mode emitter surfaces companion errors on done (60b613d):
- text-mode done + cleanup error → both ✓ and ⚠ lines surface
- text-mode done + writer warnings → existing behavior unchanged
Pattern follows test/commands/status.test.ts: TestableCurate subclasses
Curate, overrides protected seams via constructor-injected behavior
callbacks, captures stdout via sinon.stub(process.stdout, 'write')
because writeJsonResponse bypasses this.log.
Full suite: 8890 passing (13 new, 1 added earlier this session). N
Nguyễn Thuận Phát committed
176906890867bf2ba64af589414a858809d42f7b
Parent: 60b613d