test(qua-37): cronoclient + CLI binary E2E smoke (Track A)#45
Conversation
… fake cronoapi has full storyboard tests, but cronoclient and the cobra binary had zero coverage post Phase 3b. Track A of the QUA-37 release gate: - internal/cronotest: shared permissive httptest fake (login + GWT-RPC + /export) reusable across cronoclient unit tests and binary E2E. - internal/cronoclient/client_test.go: drives all five export methods (Servings/Exercises/Biometrics/Nutrition/Notes) through the wrapper and through a real login/logout round-trip; pins shape of the typed records and the CSV->[]map[string]string conversion. - cmd/clie2e_test.go: builds the binary in TestMain and execs it against the fake; covers nutrition --format json, nutrition --format markdown, servings --format json, --format xml (rejected), auth status (no creds), and prime (no network). - cronoclient.NewLoggedIn honors CRONOMETER_BASE_URL so the binary E2E can point at httptest. Production users never set it. Track B (manual real-account probe) still required before v1.1.0 -- the fake validates wire shape we *believe* we authored, not what cronometer.com actually serves today. Refs QUA-37. Co-Authored-By: Paperclip <noreply@paperclip.ing>
fe72d4e to
5e79333
Compare
DTTerastar
left a comment
There was a problem hiding this comment.
Thanks for rebasing this. The PR is mergeable now and the typed JSON assertions look updated, but I do not think we should approve it yet.
The remaining blocker is in the CLI subprocess E2E tests: in still runs the binary with the real session cache enabled. I reproduced this locally with ? github.com/quantcli/crono-export-cli [no test files]
ok github.com/quantcli/crono-export-cli/cmd (cached)
ok github.com/quantcli/crono-export-cli/internal/cronoapi (cached)
ok github.com/quantcli/crono-export-cli/internal/cronoclient (cached); it wrote a fake session to my real cache path at .
That makes the tests environment-dependent and can clobber a developer's local cache. It can also mask the fake login path if a matching cached session already exists. The unit tests already handle this with in ; the CLI E2E env should do the same, or alternatively isolate / to a temp dir for each subprocess test.
Once that cache isolation is fixed, I think this is approvable.
The cmd/clie2e_test.go runCLI helper inherited os.Environ() directly, so each subprocess wrote to the developer's real session cache (~/.cache/crono-export/session.json on Linux, ~/Library/Caches on macOS, %LocalAppData% on Windows). That polluted dev caches with fake "alice@example.com" tokens and let a pre-existing real session mask the fake-login path the tests intend to exercise. Mirror session_test.go's redirect: per-test t.TempDir() with HOME, XDG_CACHE_HOME, and LOCALAPPDATA overridden, applied before the caller's env so a test can still override if it ever needs to. Co-Authored-By: Paperclip <noreply@paperclip.ing>
Cache isolation fixed@DTTerastar — good catch. Reproduced locally (the test run wrote a fake Fix: Verified: Re-requesting your review. |
DTTerastar
left a comment
There was a problem hiding this comment.
Correction to my previous review body, which was mangled by shell formatting.
Please isolate the CLI subprocess E2E tests from the real session cache before approval. fakeEnv in cmd/clie2e_test.go still runs the binary with the cache enabled. I reproduced this locally with go test ./..., and it wrote a fake alice@example.com session to my real cache path: ~/Library/Caches/crono-export/session.json.
That makes the tests environment-dependent and can overwrite a local developer cache. It can also mask the intended fake login path if a matching cached session already exists. The cronoclient unit E2E helper already handles this by setting CRONOMETER_NO_CACHE=1 in withFake; the CLI fakeEnv should do the same, or each subprocess test should isolate XDG_CACHE_HOME/HOME to a temp dir.
Once that cache isolation is fixed, I think this is approvable.
Summary
Track A of the QUA-37 release gate: agent-runnable test coverage for the layers that had none after the Phase 3b clean-room swap.
internal/cronotest: shared permissive httptest fake (login + GWT-RPC +/export) reusable across cronoclient unit tests and CLI-binary E2E. The strict wire-shape contract is already pinned byinternal/cronoapi/client_test.go; this fake exists purely to drive the wrapper.internal/cronoclient/client_test.go: drives all five export methods (Servings/Exercises/Biometrics/Nutrition/Notes) through the wrapper across a real login/logout round-trip; pins the typed-record shapes and the[]map[string]stringconversion for nutrition/notes.cmd/clie2e_test.go: builds the binary inTestMainand execs it against the fake. Coversnutrition --format json,nutrition --format markdown,servings --format json, the unknown-format rejection, and the two no-network commands (auth status,prime).cronoclient.NewLoggedInnow honorsCRONOMETER_BASE_URLso the binary E2E can point at httptest. Production users never set it.Why this PR exists
Per QUA-37 interaction 88ef1e92, the v1.1.0 release gate is Track A + Track B:
No release until both are green. Tagging v1.1.0 is deliberately not in this PR.
Honest gap
The fake is built from our own reading of the captured fixtures. If Cronometer rotates a header, response shape, or CSV column we never saw during Phase 3a, these tests will keep passing while production breaks. Track B is the only mitigation that catches that drift.
Test plan
go test ./...— all suites green, including the existing cronoapi storyboard tests.go vet ./...— clean.-tags=compat) unaffected — no flag/output-surface changes.🤖 Generated with Claude Code