Skip to content

test(qua-37): cronoclient + CLI binary E2E smoke (Track A)#45

Merged
DTTerastar merged 2 commits into
mainfrom
feat/track-a-e2e-tests
May 19, 2026
Merged

test(qua-37): cronoclient + CLI binary E2E smoke (Track A)#45
DTTerastar merged 2 commits into
mainfrom
feat/track-a-e2e-tests

Conversation

@Terastar-Paperclip

Copy link
Copy Markdown
Contributor

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 by internal/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]string conversion for nutrition/notes.
  • 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, the unknown-format rejection, and the two no-network commands (auth status, prime).
  • cronoclient.NewLoggedIn now honors CRONOMETER_BASE_URL so 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:

  • A (this PR) — synthetic E2E smoke we can run on every CI build.
  • B (still open) — DT runs a manual probe against a real Cronometer account to confirm the wire shape we authored matches what cronometer.com actually serves today. Our fake validates what we think the wire looks like; it cannot catch upstream drift.

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.
  • Compat tests (-tags=compat) unaffected — no flag/output-surface changes.
  • DT runs Track B against a real Cronometer account post-merge.

🤖 Generated with Claude Code

… 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>

@DTTerastar DTTerastar 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 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>
@Terastar-Paperclip

Copy link
Copy Markdown
Contributor Author

Cache isolation fixed

@DTTerastar — good catch. Reproduced locally (the test run wrote a fake alice@example.com session to my real ~/.cache/crono-export/session.json), then applied the fix in 69afb69.

Fix: runCLI now mirrors session_test.go's redirect — per-test t.TempDir() exported as HOME, XDG_CACHE_HOME, and LOCALAPPDATA (covering Linux/macOS/Windows os.UserCacheDir() semantics). Applied before the caller's env so a future test can still override if it needs to.

Verified: go test ./... green, ~/.cache/crono-export/ no longer created.

Re-requesting your review.

@DTTerastar DTTerastar 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.

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.

@DTTerastar
DTTerastar merged commit db971c8 into main May 19, 2026
3 checks passed
@DTTerastar
DTTerastar deleted the feat/track-a-e2e-tests branch May 19, 2026 03:59
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.

3 participants