Skip to content

Commit 718bfd7

Browse files
test(razorpaybilling): drive coverage 8.5% -> 100%
Every Portal method (SubscriptionID, CancelAtCycleEnd, CancelImmediately, ListSubscriptionInvoices, PaymentUpdateURL, ChangePlan, FetchSubscriptionDetails) plus the toInt64 / pickInvoiceTimestamp helpers now exercise their happy path, every error branch (4xx/5xx upstream, no-config, DB error, sql.ErrNoRows, malformed/missing fields), and every callWithBreaker arm — including the open-state rejection and the WithOnOpen callback on the singleton breaker. The Razorpay REST surface is mocked via httptest.Server; no live API calls. A one-line test seam in portal.go (newClientForPortal) lets tests retarget the SDK's BaseURL at the mock; production callers go through the original NewTimeoutClient unchanged. Coverage: 8.5% -> 100.0% of statements (go test -cover). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3308465 commit 718bfd7

2 files changed

Lines changed: 1278 additions & 1 deletion

File tree

internal/razorpaybilling/portal.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,21 @@ type Portal struct {
136136
Cfg *config.Config
137137
}
138138

139+
// newClientForPortal is the factory used by Portal.client(). It is a
140+
// package-level variable so unit tests in this package can install a
141+
// version that points its BaseURL at an httptest.Server mock of the
142+
// Razorpay API. Production code path is unchanged — the default is
143+
// NewTimeoutClient verbatim.
144+
var newClientForPortal = NewTimeoutClient
145+
139146
func (p *Portal) client() (*razorpay.Client, error) {
140147
if p.Cfg.RazorpayKeyID == "" || p.Cfg.RazorpayKeySecret == "" {
141148
return nil, fmt.Errorf("billing not configured")
142149
}
143150
// P0-2: 30s HTTP timeout via ApplyHTTPTimeout — never the bare SDK
144151
// default (10s) which is below Razorpay's documented p99 for
145152
// subscription create.
146-
return NewTimeoutClient(p.Cfg.RazorpayKeyID, p.Cfg.RazorpayKeySecret), nil
153+
return newClientForPortal(p.Cfg.RazorpayKeyID, p.Cfg.RazorpayKeySecret), nil
147154
}
148155

149156
// SubscriptionID returns the Razorpay subscription id stored on the team (stripe_customer_id column).

0 commit comments

Comments
 (0)