Skip to content

Commit 4845760

Browse files
test(api): 100% patch coverage on cli-complete + ignored_fields/recycle branches
Closes the 100%-patch-coverage CI gate on #283. The e2e tests that exercised these lines are build-tagged (excluded from the -short coverage run), so the new handler error-arms showed as uncovered. Added UNIT tests + two minimal test seams. cli_auth.go (CompleteCLISessionHandler, D2): white-box tests in cli_auth_coverage_test.go drive every error arm — missing/blank session id, Redis-read failure, corrupt session blob, idempotent already-complete, non-UUID team/user locals, team-not-found + team-lookup DB error, keygen failure, CreateAPIKey failure, best-effort resource-list failure, happy-path session flip (incl. the token-gathering loop), and the final session-write failure (injected via a go-redis SET-failing hook). Handler now 100%. provision_helper.go: - recycleClaimURL (F1): the existing mint-failed test could not force the failure (HMAC over any []byte key signs), so issueOnboardingJWT is now reached through the issueOnboardingJWTFn seam; rewrote the test to force the bare-URL fallback and added the mint-success (embeds-JWT) arm. 100%. - knownJSONFields / collectJSONFields (D7): added reflection-edge tests — typed nil pointer, non-struct input, pointer-to-pointer, anonymous *struct embed, unexported non-embedded field, non-struct in collectJSONFields, non-object body, empty object. Both 100%. - parseProvisionBody content-type charset-strip + 415 arm covered directly. Test seams generateAPIKeyPlaintextFn (cli_auth.go) and issueOnboardingJWTFn (provision_helper.go) both default to the real func/method — zero prod behavior change — mirroring the existing promoteDeploymentTTLsForTeamFn pattern in billing.go. diff-cover vs origin/master: 213 changed lines, 0 missing, 100%. golangci-lint ./internal/handlers/ → 0 issues. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent fac6626 commit 4845760

5 files changed

Lines changed: 733 additions & 23 deletions

File tree

internal/handlers/cli_auth.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ func (h *CLIAuthHandler) CompleteCLISessionHandler(c *fiber.Ctx) error {
280280
// Mint the long-lived team API key the CLI persists. Plaintext is returned
281281
// to the caller exactly once (here, via the completed Redis state → the
282282
// CLI's poll); only the SHA-256 is stored.
283-
plaintext, err := models.GenerateAPIKeyPlaintext()
283+
plaintext, err := generateAPIKeyPlaintextFn()
284284
if err != nil {
285285
slog.Error("cli_auth.complete.keygen", "request_id", requestID, "error", err)
286286
return respondError(c, fiber.StatusServiceUnavailable, "key_generation_failed",
@@ -337,6 +337,14 @@ func (h *CLIAuthHandler) CompleteCLISessionHandler(c *fiber.Ctx) error {
337337
// dashboard-minted ones in the team's key list.
338338
const cliAPIKeyName = "CLI login"
339339

340+
// generateAPIKeyPlaintextFn is the seam through which CompleteCLISessionHandler
341+
// mints the CLI PAT. It indirects to models.GenerateAPIKeyPlaintext in prod;
342+
// tests override it to exercise the (otherwise-unreachable) crypto/rand failure
343+
// arm — GenerateAPIKeyPlaintext only errors when crypto/rand.Read does, which
344+
// cannot be injected without a seam. Mirrors the promoteDeploymentTTLsForTeamFn
345+
// pattern in billing.go.
346+
var generateAPIKeyPlaintextFn = models.GenerateAPIKeyPlaintext
347+
340348
// CompleteCLISession is called by the OAuth callback handler after a user
341349
// successfully authenticates. It writes the result into Redis so the CLI's
342350
// polling loop picks it up.

0 commit comments

Comments
 (0)