Files
magpie/internal/dimagent/usage_test.go
T
Ethan Xuandyetone 2f00db65e6 feat: add DimAgent subscription support (#226)
* feat: add DimAgent subscription support

Add OAuth PKCE login with automatic and pasted callbacks, account management, model discovery, quota reporting and gateway integration. Safely rotate credentials during concurrent requests and preserve fresh tokens when updating model caches. Cover protocol, provider, GUI and callback behavior with regression tests.

* dimagent: a refresh hiccup inside the day's lead keeps the token that still runs

The fallback checked !dimagentNearExpiry, which is false whenever a refresh
runs at all, so a 5xx/timeout on /oauth/token failed every request for the
last 24h of a still-valid token. A 401/403 still lapses the account.

* dimagent: review tests (sign forwarding, parallel refresh once, hiccup in lead, LoginUsage)

* dimagent: signing in again takes the callback port from the sign-in it replaces

StartSignIn begins the new flow before it cancels the old one, so the new
flow's listen on 54321 failed (ignored) and the old listener then shut
down a second later: the browser's callback was refused and only pasting
could finish. The older DimAgent flow is now ended and its server closed
first, and the listen retried briefly while the port is let go.

* dimagent: the fake-upstream tests get a name of their own

---------

Co-authored-by: yetone <yetoneful@gmail.com>
2026-09-30 01:11:29 +08:00

117 lines
4.0 KiB
Go

package dimagent
import (
"encoding/json"
"strings"
"testing"
"time"
)
// A reply as the upstream sends it, with the plan record, a bucket holding a
// window, an add-on, a meter and the two reset counters.
const usageBody = `{"success":true,"data":{
"account_id":"42",
"subscription":{"product":{"name":"DimAgent Pro"},
"subscription":{"status":"active","cancel_at_period_end":false},
"current_term":{"start_at":"2026-09-01T00:00:00Z","end_at":"2026-10-01T00:00:00Z"}},
"credits":{
"subscription_bucket":{"id":1,"bucket_kind":"credits","total_units":700,"used_units":210,
"remaining_units":490,"expires_at":"2026-10-01T00:00:00Z",
"window_states":[{"id":9,"bucket_id":1,"window_duration_hours":5,"window_token_cap":250000,
"window_token_used":100000,"window_started_at":"2026-09-29T09:00:00Z",
"window_expires_at":"2026-09-29T14:00:00Z"}]},
"addon_buckets":[{"id":2,"total_units":100,"remaining_units":40,"expires_at":"2026-12-31T00:00:00Z"}],
"total_units":700,"used_units":210,"remaining_units":490},
"resets":{"window":{"available_count":2,"nearest_expires_at":"2026-09-30T00:00:00Z"},
"monthly_full":{"available_count":0}},
"feature_meters":[{"feature_key":"web_search","unit":"call","total_allowance":1000,"total_remaining":940}]}}`
func TestParseUsage(t *testing.T) {
u, err := ParseUsage([]byte(usageBody))
if err != nil {
t.Fatal(err)
}
if u.AccountID != "42" {
t.Fatalf("account id read from a string: %q", u.AccountID)
}
if u.Plan.Name != "DimAgent Pro" || !u.Plan.RenewKnown || !u.Plan.Renew {
t.Fatalf("plan: %+v", u.Plan)
}
if got := u.Plan.EndsAt.Format(time.RFC3339); got != "2026-10-01T00:00:00Z" {
t.Fatalf("term end: %s", got)
}
b := u.Subscription
if b.Total != 700 || b.Used != 210 || b.Remaining != 490 {
t.Fatalf("bucket: %+v", b)
}
if len(b.Windows) != 1 {
t.Fatalf("windows: %+v", b.Windows)
}
w := b.Windows[0]
if w.Hours != 5 || w.Cap != 250000 || w.Used != 100000 || w.Expires.IsZero() {
t.Fatalf("window: %+v", w)
}
if len(u.AddOns) != 1 || u.AddOns[0].Used != 60 {
t.Fatalf("add-on: %+v", u.AddOns)
}
if len(u.Meters) != 1 || u.Meters[0].Feature != "web_search" || u.Meters[0].Used != 60 {
t.Fatalf("meters: %+v", u.Meters)
}
if u.Resets.Window.Available != 2 || u.Resets.Monthly.Available != 0 {
t.Fatalf("resets: %+v", u.Resets)
}
}
// A plan record with no product is named by the subscription's status; one
// that says cancel_at_period_end off shows as not renewing.
func TestParseUsagePlanFallback(t *testing.T) {
var v map[string]any
if err := json.Unmarshal([]byte(usageBody), &v); err != nil {
t.Fatal(err)
}
data := v["data"].(map[string]any)
sub := data["subscription"].(map[string]any)
delete(sub, "product")
sub["subscription"].(map[string]any)["cancel_at_period_end"] = true
body, _ := json.Marshal(v)
u, err := ParseUsage(body)
if err != nil {
t.Fatal(err)
}
if u.Plan.Name != "active" {
t.Fatalf("status fallback: %q", u.Plan.Name)
}
if u.Plan.RenewKnown && u.Plan.Renew {
t.Fatalf("renew: %+v", u.Plan)
}
}
// A bucket whose only window is the flat placeholder an older reply leaves
// says nothing, so the tile falls back on the credits themselves.
func TestParseUsageEmptyWindow(t *testing.T) {
body := `{"data":{"credits":{"subscription_bucket":{"total_units":10,"used_units":3,
"window_duration_hours":0,"window_token_cap":0,"window_token_used":0,
"window_started_at":null,"window_expires_at":null}}}}`
u, err := ParseUsage([]byte(body))
if err != nil {
t.Fatal(err)
}
if len(u.Subscription.Windows) != 0 {
t.Fatalf("placeholder window kept: %+v", u.Subscription.Windows)
}
}
func TestParseUsageNoAllowance(t *testing.T) {
_, err := ParseUsage([]byte(`{"data":{"account_id":"1"}}`))
if err == nil || !strings.Contains(err.Error(), "no allowance") {
t.Fatalf("err: %v", err)
}
}
func TestParseUsageRefused(t *testing.T) {
_, err := ParseUsage([]byte(`{"success":false,"message":"plan expired"}`))
if err == nil || err.Error() != "dimagent usage: plan expired" {
t.Fatalf("err: %v", err)
}
}