From a2714f7506b2e018742c331f986569bab3beea14 Mon Sep 17 00:00:00 2001 From: yetone Date: Thu, 1 Oct 2026 13:51:22 +0800 Subject: [PATCH] =?UTF-8?q?claude:=20a=20Claude=20account's=20usage=20rese?= =?UTF-8?q?ts=20are=20read=20in=20the=20zone=20/usage=20names=20on=20Windo?= =?UTF-8?q?ws=20too,=20and=20the=20provider=20tests=20pass=20whole=20on=20?= =?UTF-8?q?Windows=20(goal:=20=E6=8F=92=E4=BB=B6=E8=AE=A2=E9=98=85=20provi?= =?UTF-8?q?der=20=E8=B7=9F=E5=86=85=E7=BD=AE=E7=9A=84=E6=89=80=E6=9C=89?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E9=83=BD=E8=A6=81=E4=B8=80=E6=A8=A1=E4=B8=80?= =?UTF-8?q?=E6=A0=B7,=20run=20on=20Windows=20and=20Linux)=20=E2=80=94=20Wi?= =?UTF-8?q?ndows=20has=20no=20time=20zone=20database,=20so=20"resets=20Oct?= =?UTF-8?q?=201=20at=203:30pm=20(Asia/Shanghai)"=20was=20read=20in=20the?= =?UTF-8?q?=20machine's=20own=20zone,=20hours=20off=20for=20anyone=20not?= =?UTF-8?q?=20in=20that=20zone;=20magpie=20now=20carries=20the=20database?= =?UTF-8?q?=20(time/tzdata).=20The=20provider=20tests=20set=20HOME=20but?= =?UTF-8?q?=20not=20USERPROFILE,=20which=20Windows=20takes=20the=20home=20?= =?UTF-8?q?from,=20so=20on=20Windows=20they=20read=20the=20test=20box's=20?= =?UTF-8?q?own=20agent=20sign-ins=20(Gemini=20models=20in=20a=20list,=20an?= =?UTF-8?q?=20extra=20provider,=20a=20Cursor=20version);=20every=20test=20?= =?UTF-8?q?home=20sets=20both=20now.=20Tests=20whose=20fake=20CLI=20is=20a?= =?UTF-8?q?=20shell=20script=20(Claude=20Code's=20auth=20status,=20codex?= =?UTF-8?q?=20--version,=20macOS's=20security)=20skip=20on=20Windows,=20as?= =?UTF-8?q?=20the=20fake=20devin=20did,=20and=20file=20mode=20bits=20go=20?= =?UTF-8?q?unchecked=20there.=20TestParseClaudeUsage=20fails=20on=20Window?= =?UTF-8?q?s=20without=20the=20change.=20On=20Windows=20and=20on=20Linux?= =?UTF-8?q?=20(WSL)=20the=20provider=20package=20passes=20whole,=20three?= =?UTF-8?q?=20times=20on=20Windows=20(15=20failed=20before),=20the=20plugi?= =?UTF-8?q?n=20package=20and=20the=20move/plugin/Grok/Devin/usage=20tests?= =?UTF-8?q?=20five=20times=20over=20on=20Linux.=20go=20vet,=20go=20build?= =?UTF-8?q?=20-tags=20nogui=20(darwin,=20GOOS=3Dlinux),=20GOOS=3Dwindows?= =?UTF-8?q?=20go=20build,=20go=20test=20-tags=20nogui=20./...=20pass.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/provider/account_test.go | 1 + internal/provider/antigravity_models_test.go | 1 + internal/provider/balance_test.go | 2 ++ internal/provider/bedrock_test.go | 1 + internal/provider/catalogs_test.go | 2 ++ internal/provider/claude_status_test.go | 3 +++ internal/provider/claude_usage_cli.go | 3 +++ internal/provider/codex_daemon_test.go | 1 + internal/provider/codex_models_test.go | 4 ++++ internal/provider/context_test.go | 1 + internal/provider/copy_test.go | 1 + internal/provider/cursor_names_test.go | 1 + internal/provider/cursor_status_test.go | 1 + internal/provider/cursor_test.go | 3 +++ internal/provider/decide_test.go | 8 ++++++++ internal/provider/devin_models_test.go | 1 + internal/provider/devin_test.go | 12 ++++++++++-- internal/provider/favicon_test.go | 1 + internal/provider/fixv1_test.go | 2 ++ internal/provider/grok_price_test.go | 1 + internal/provider/group_test.go | 2 ++ internal/provider/groupeffort_test.go | 1 + internal/provider/groupnest_test.go | 1 + internal/provider/grouprename_test.go | 1 + internal/provider/grouprule_test.go | 2 ++ internal/provider/hidden_models_test.go | 1 + internal/provider/icon_test.go | 2 ++ internal/provider/install_test.go | 2 +- internal/provider/key_quota_last_test.go | 1 + internal/provider/kiro_test.go | 1 + internal/provider/limits_test.go | 1 + internal/provider/logins_test.go | 3 ++- internal/provider/maker_efforts_test.go | 1 + internal/provider/modelprefs_test.go | 1 + internal/provider/models_test.go | 3 +++ internal/provider/modelsurl_test.go | 1 + internal/provider/native_test.go | 1 + internal/provider/off_test.go | 1 + internal/provider/planquota_test.go | 1 + internal/provider/plugin_icon_test.go | 1 + internal/provider/price_override_test.go | 1 + internal/provider/provider_test.go | 2 ++ internal/provider/rename_test.go | 1 + internal/provider/signedout_test.go | 3 +++ internal/provider/signin_stale_test.go | 1 + internal/provider/stepfun_plan_test.go | 3 ++- internal/provider/symlink_test.go | 3 ++- internal/provider/test_test.go | 3 +++ internal/provider/zhipu_team_key_test.go | 1 + 49 files changed, 90 insertions(+), 6 deletions(-) diff --git a/internal/provider/account_test.go b/internal/provider/account_test.go index de2d1fa0..0530ddda 100644 --- a/internal/provider/account_test.go +++ b/internal/provider/account_test.go @@ -462,6 +462,7 @@ func TestCopilotSignAndModels(t *testing.T) { // Logging out of Claude Code can leave its credentials behind; what the CLI // says wins, so a signed-out account is not a provider. func TestClaudeSignedOut(t *testing.T) { + shellFakes(t) home := claudeHome(t) claudeSignIn(t, home, time.Now().Add(time.Hour)) status := `{"loggedIn": true, "email": "me@example.com", "subscriptionType": "max"}` diff --git a/internal/provider/antigravity_models_test.go b/internal/provider/antigravity_models_test.go index 47f6c27b..524925a1 100644 --- a/internal/provider/antigravity_models_test.go +++ b/internal/provider/antigravity_models_test.go @@ -92,6 +92,7 @@ func TestCollapseAntigravityModels(t *testing.T) { func TestAntigravityLegacyPicks(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) if err := catalog.SaveLive("antigravity", "", antigravityListed); err != nil { diff --git a/internal/provider/balance_test.go b/internal/provider/balance_test.go index ffcea922..53fb02fa 100644 --- a/internal/provider/balance_test.go +++ b/internal/provider/balance_test.go @@ -105,6 +105,7 @@ func TestKeyBalances(t *testing.T) { isolate(t) h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) t.Setenv("PATH", h) @@ -320,6 +321,7 @@ func TestBalanceURLNamesTheKey(t *testing.T) { isolate(t) h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) t.Setenv("PATH", h) diff --git a/internal/provider/bedrock_test.go b/internal/provider/bedrock_test.go index 3497dfb4..bf7deaa5 100644 --- a/internal/provider/bedrock_test.go +++ b/internal/provider/bedrock_test.go @@ -9,6 +9,7 @@ import ( func TestBedrockPreset(t *testing.T) { t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) t.Setenv("XDG_CACHE_HOME", t.TempDir()) p, err := FromPreset("bedrock") diff --git a/internal/provider/catalogs_test.go b/internal/provider/catalogs_test.go index d8f3eaf7..aa1936eb 100644 --- a/internal/provider/catalogs_test.go +++ b/internal/provider/catalogs_test.go @@ -13,6 +13,7 @@ import ( func TestSeveralCatalogs(t *testing.T) { isolate(t) t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) cache := t.TempDir() t.Setenv("XDG_CACHE_HOME", cache) @@ -53,6 +54,7 @@ func TestSeveralCatalogs(t *testing.T) { func TestOpenCodeModelAPIs(t *testing.T) { isolate(t) t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) cache := t.TempDir() t.Setenv("XDG_CACHE_HOME", cache) diff --git a/internal/provider/claude_status_test.go b/internal/provider/claude_status_test.go index 783a0254..9f39ca0a 100644 --- a/internal/provider/claude_status_test.go +++ b/internal/provider/claude_status_test.go @@ -12,9 +12,11 @@ import ( // its saved login is, so it is the one Active and not also served beside // itself; the env magpie runs in is not handed to the CLI (#177). func TestClaudeAccountNamedAsItsLogin(t *testing.T) { + shellFakes(t) isolate(t) home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("CLAUDE_CONFIG_DIR", "") t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("ANTHROPIC_AUTH_TOKEN", "magpie") @@ -55,6 +57,7 @@ func TestClaudeAccountNamedAsItsLogin(t *testing.T) { // a second look at Claude Code's sign-in serves the last answer at once and // asks the CLI again behind it (#123) func TestClaudeIdentityServedWhileAsked(t *testing.T) { + shellFakes(t) dir := t.TempDir() exe, who := filepath.Join(dir, "claude"), filepath.Join(dir, "who") os.WriteFile(who, []byte("a@example.com"), 0o600) diff --git a/internal/provider/claude_usage_cli.go b/internal/provider/claude_usage_cli.go index 1054ef90..6a6f551a 100644 --- a/internal/provider/claude_usage_cli.go +++ b/internal/provider/claude_usage_cli.go @@ -12,6 +12,9 @@ import ( "strconv" "strings" "time" + // the zone /usage names its resets in: Windows has no zone database, + // and without one a reset was read in the machine's own zone + _ "time/tzdata" ) // claudeCLIUsage runs Claude Code's /usage for the account it is signed in diff --git a/internal/provider/codex_daemon_test.go b/internal/provider/codex_daemon_test.go index e30505e8..a2999083 100644 --- a/internal/provider/codex_daemon_test.go +++ b/internal/provider/codex_daemon_test.go @@ -96,6 +96,7 @@ func TestFindCodexDaemon(t *testing.T) { func fakeDaemon(t *testing.T) *int { t.Helper() t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) pid := new(int) old, oldHome := listProcesses, processCodexHome t.Cleanup(func() { diff --git a/internal/provider/codex_models_test.go b/internal/provider/codex_models_test.go index 0bb5f6be..fafea929 100644 --- a/internal/provider/codex_models_test.go +++ b/internal/provider/codex_models_test.go @@ -50,8 +50,10 @@ func TestCodexModelsOfTheAccount(t *testing.T) { // The models list is asked for with the newest Codex known: the CLI // installed over the version its cache was written with. func TestCodexVersion(t *testing.T) { + shellFakes(t) home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) writeFile(t, filepath.Join(home, ".codex", "models_cache.json"), map[string]any{"client_version": "0.160.0"}) exe := filepath.Join(t.TempDir(), "codex") if err := os.WriteFile(exe, []byte("#!/bin/sh\necho codex-cli 0.161.1\n"), 0o755); err != nil { @@ -86,6 +88,7 @@ func TestCodexVersion(t *testing.T) { // Codex's requests count, and never an older version. func TestCodexVersionSeen(t *testing.T) { t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("CODEX_HOME", "") old := codexExecutable codexExecutable = func() string { return "" } @@ -150,6 +153,7 @@ func TestCodexExecutableOffPath(t *testing.T) { t.Run(name, func(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("PATH", "/usr/bin:/bin") os.WriteFile(filepath.Join(home, ".npmrc"), []byte("registry=https://registry.npmjs.org/\nprefix = ~/custom-npm\n"), 0o644) exe := filepath.Join(home, dir, "codex") diff --git a/internal/provider/context_test.go b/internal/provider/context_test.go index 4cecfb04..f12c9ad4 100644 --- a/internal/provider/context_test.go +++ b/internal/provider/context_test.go @@ -8,6 +8,7 @@ import ( func TestContextSetByUser(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) // set, not empty: a group saved lists what Devin's CLI reports, and // Devin given an empty one writes its config into the working directory t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) diff --git a/internal/provider/copy_test.go b/internal/provider/copy_test.go index 2abd8cc6..30ff1f69 100644 --- a/internal/provider/copy_test.go +++ b/internal/provider/copy_test.go @@ -14,6 +14,7 @@ func TestAddCopy(t *testing.T) { isolate(t) home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) src := Provider{ID: "relay", Name: "Relay", Chat: "https://api.relay.example/v1", Key: "sk-1", KeyName: "main", diff --git a/internal/provider/cursor_names_test.go b/internal/provider/cursor_names_test.go index ef6afb15..10b698a1 100644 --- a/internal/provider/cursor_names_test.go +++ b/internal/provider/cursor_names_test.go @@ -49,6 +49,7 @@ func TestCursorNamesWithoutCapacity(t *testing.T) { func TestCursorAvailableNames(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) was := cursorStatus diff --git a/internal/provider/cursor_status_test.go b/internal/provider/cursor_status_test.go index be12a7bc..60261037 100644 --- a/internal/provider/cursor_status_test.go +++ b/internal/provider/cursor_status_test.go @@ -76,6 +76,7 @@ func TestAskCursorStatus(t *testing.T) { } home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) exe := filepath.Join(home, "cursor-agent") wasExe, wasOut := CursorExecutable, cursorSignedOut t.Cleanup(func() { CursorExecutable, cursorSignedOut = wasExe, wasOut }) diff --git a/internal/provider/cursor_test.go b/internal/provider/cursor_test.go index f2d45652..c8f274a3 100644 --- a/internal/provider/cursor_test.go +++ b/internal/provider/cursor_test.go @@ -94,6 +94,7 @@ func TestCollapseCursorModels(t *testing.T) { func TestCursorLegacyPicks(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) was := cursorStatus @@ -161,6 +162,7 @@ func TestCursorContext(t *testing.T) { func TestCursorClientVersion(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) exe := CursorExecutable defer func() { CursorExecutable = exe }() CursorExecutable = func() string { return "" } @@ -204,6 +206,7 @@ func TestTokenExpiry(t *testing.T) { func TestCursorPluginContext(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) os.MkdirAll(filepath.Dir(catalog.CachePath()), 0o755) diff --git a/internal/provider/decide_test.go b/internal/provider/decide_test.go index 4ac238c1..931cc2ea 100644 --- a/internal/provider/decide_test.go +++ b/internal/provider/decide_test.go @@ -17,6 +17,7 @@ import ( // effort is picked only by it. func TestDecider(t *testing.T) { t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) if err := Save(Provider{ID: "a", Name: "a", Key: "k", Chat: "http://127.0.0.1:1/v1", Models: []string{"m"}}); err != nil { t.Fatal(err) @@ -79,6 +80,7 @@ func TestAPIErrorDetail(t *testing.T) { // as each names it, and a key checked by the gateway's own free call. func TestDecideGateways(t *testing.T) { t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) t.Setenv("XDG_CACHE_HOME", t.TempDir()) for id, want := range map[string][2]string{"typesafe": {ViaSystemOne, "jev-latest"}, "vercel-jev": {ViaVercel, "typesafe-ai/jev"}, "cloudflare-jev": {ViaCloudflare, "typesafe/jev"}} { @@ -166,6 +168,7 @@ func TestFetchDecideOpenAIJevIDs(t *testing.T) { isolate(t) h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) var auth string @@ -240,6 +243,7 @@ func TestFetchDecideOpenAIJevIDs(t *testing.T) { func TestRouteDecider(t *testing.T) { h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) if _, _, err := RouteDecider(""); err == nil || !strings.Contains(err.Error(), "names no model") { @@ -313,6 +317,7 @@ func TestRouteDecider(t *testing.T) { func TestRouteDeciderVercelAlias(t *testing.T) { h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) if err := Save(Provider{ID: "vercel-jev", Name: "Vercel", Key: "k", Decide: "https://ai-gateway.vercel.sh/typesafe"}); err != nil { @@ -342,6 +347,7 @@ func TestRouteDeciderVercelAlias(t *testing.T) { func TestRouteDeciderCloudflareAlias(t *testing.T) { h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) if err := Save(Provider{ID: "cloudflare-jev", Name: "CF", Key: "k", Decide: "https://api.cloudflare.com/client/v4"}); err != nil { @@ -361,6 +367,7 @@ func TestRouteDeciderCloudflareAlias(t *testing.T) { func TestRouteDeciderUnfetchedAmbiguous(t *testing.T) { h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) for _, p := range []Provider{ @@ -378,6 +385,7 @@ func TestRouteDeciderUnfetchedAmbiguous(t *testing.T) { // two System One providers, catalogs not fetched, both default to jev-latest h2 := t.TempDir() t.Setenv("HOME", h2) + t.Setenv("USERPROFILE", h2) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h2, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h2, ".cache")) for _, p := range []Provider{ diff --git a/internal/provider/devin_models_test.go b/internal/provider/devin_models_test.go index 70afe875..8aef8305 100644 --- a/internal/provider/devin_models_test.go +++ b/internal/provider/devin_models_test.go @@ -119,6 +119,7 @@ func TestDevinVariantIn(t *testing.T) { func TestDevinEfforts(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) devinFamiliesCached(devinListed) diff --git a/internal/provider/devin_test.go b/internal/provider/devin_test.go index 64e84652..03ce96f1 100644 --- a/internal/provider/devin_test.go +++ b/internal/provider/devin_test.go @@ -147,6 +147,7 @@ func TestDevinCredentialsPath(t *testing.T) { } home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_DATA_HOME", filepath.Join(home, "data")) got := DevinCredentialsPath() if got != filepath.Join(home, "data", "devin", "credentials.toml") { @@ -366,11 +367,18 @@ const devinUnreachable = `printf '%s\n' 'Logged in (via Devin).' '' 'User / team // the CLI and the identity back when it ends: an ask that couldn't tell now // leaves the last account served, so a test after this one must not find // either. -func fakeDevin(t *testing.T, exe string) { +// shellFakes skips a test whose fake CLI is a shell script, which Windows +// can't run. +func shellFakes(t *testing.T) { t.Helper() if runtime.GOOS == "windows" { - t.Skip("the fake devin is a shell script") + t.Skip("the fake CLI is a shell script") } +} + +func fakeDevin(t *testing.T, exe string) { + t.Helper() + shellFakes(t) old := DevinExecutable DevinExecutable = func() string { return exe } t.Cleanup(func() { diff --git a/internal/provider/favicon_test.go b/internal/provider/favicon_test.go index 377a0f38..1053dde1 100644 --- a/internal/provider/favicon_test.go +++ b/internal/provider/favicon_test.go @@ -37,6 +37,7 @@ func TestFaviconSites(t *testing.T) { func TestFavicon(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) png := []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR") diff --git a/internal/provider/fixv1_test.go b/internal/provider/fixv1_test.go index 44b33267..2e40e58d 100644 --- a/internal/provider/fixv1_test.go +++ b/internal/provider/fixv1_test.go @@ -16,6 +16,7 @@ func TestFetchAddsMissingV1(t *testing.T) { isolate(t) h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) t.Setenv("PATH", h) @@ -74,6 +75,7 @@ func TestArkBaseKeepsItsPath(t *testing.T) { isolate(t) h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) t.Setenv("PATH", h) diff --git a/internal/provider/grok_price_test.go b/internal/provider/grok_price_test.go index eeb5b2c0..99254578 100644 --- a/internal/provider/grok_price_test.go +++ b/internal/provider/grok_price_test.go @@ -13,6 +13,7 @@ import ( func TestGrokEffortListPrice(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) os.MkdirAll(filepath.Dir(catalog.CachePath()), 0o755) diff --git a/internal/provider/group_test.go b/internal/provider/group_test.go index ade7c4f1..88d110ae 100644 --- a/internal/provider/group_test.go +++ b/internal/provider/group_test.go @@ -36,6 +36,7 @@ func TestAutoGroupsSameModel(t *testing.T) { // the one that answers. func TestGroupImages(t *testing.T) { t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", "") e := func(p, m string, images bool) Entry { return Entry{ID: p + "/" + m, Model: m, Name: m, Provider: Provider{ID: p}, Images: images} @@ -55,6 +56,7 @@ func TestGroupImages(t *testing.T) { func TestGroupImagesKeepUnknownMemberUnknown(t *testing.T) { t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", "") yes := true entries := []Entry{ diff --git a/internal/provider/groupeffort_test.go b/internal/provider/groupeffort_test.go index 013901b5..948014ab 100644 --- a/internal/provider/groupeffort_test.go +++ b/internal/provider/groupeffort_test.go @@ -12,6 +12,7 @@ import ( func effortHome(t *testing.T) { t.Helper() t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) t.Setenv("XDG_CACHE_HOME", t.TempDir()) for _, p := range []Provider{ diff --git a/internal/provider/groupnest_test.go b/internal/provider/groupnest_test.go index 0f0bfd45..4b00154d 100644 --- a/internal/provider/groupnest_test.go +++ b/internal/provider/groupnest_test.go @@ -10,6 +10,7 @@ import ( // has one anyway. func TestGroupsInGroups(t *testing.T) { t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) for _, id := range []string{"a", "b", "c"} { if err := Save(Provider{ID: id, Name: id, Key: "k", Chat: "http://127.0.0.1:1/v1", Models: []string{"m", "x"}}); err != nil { diff --git a/internal/provider/grouprename_test.go b/internal/provider/grouprename_test.go index a6890e97..7d2656de 100644 --- a/internal/provider/grouprename_test.go +++ b/internal/provider/grouprename_test.go @@ -10,6 +10,7 @@ import ( // name it by the new one. func TestRenameGroup(t *testing.T) { t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) for _, id := range []string{"a", "b"} { if err := Save(Provider{ID: id, Name: id, Key: "k", Chat: "http://127.0.0.1:1/v1", Models: []string{"gpt-6-astra", "x"}}); err != nil { diff --git a/internal/provider/grouprule_test.go b/internal/provider/grouprule_test.go index ce5baf39..90fc91d9 100644 --- a/internal/provider/grouprule_test.go +++ b/internal/provider/grouprule_test.go @@ -228,6 +228,7 @@ func TestRuledEntry(t *testing.T) { // doesn't have is refused. func TestSaveGroupRules(t *testing.T) { t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) for _, id := range []string{"a", "b"} { if err := Save(Provider{ID: id, Name: id, Key: "k", Chat: "http://127.0.0.1:1/v1", Models: []string{"m", "big"}}); err != nil { @@ -251,6 +252,7 @@ func TestSaveGroupRules(t *testing.T) { // another group, never itself. Without intents it keeps none. func TestSaveGroupClassifier(t *testing.T) { t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) for _, id := range []string{"a", "b"} { if err := Save(Provider{ID: id, Name: id, Key: "k", Chat: "http://127.0.0.1:1/v1", Models: []string{"m", "big"}}); err != nil { diff --git a/internal/provider/hidden_models_test.go b/internal/provider/hidden_models_test.go index 776fea68..a83229b9 100644 --- a/internal/provider/hidden_models_test.go +++ b/internal/provider/hidden_models_test.go @@ -21,6 +21,7 @@ func ids(es []Entry) []string { func TestHiddenModels(t *testing.T) { isolate(t) t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) t.Setenv("XDG_CACHE_HOME", t.TempDir()) for _, id := range []string{"relay", "other"} { diff --git a/internal/provider/icon_test.go b/internal/provider/icon_test.go index 1087a48d..8f2326d3 100644 --- a/internal/provider/icon_test.go +++ b/internal/provider/icon_test.go @@ -18,6 +18,7 @@ import ( func TestStoreIcon(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) png := []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR") @@ -55,6 +56,7 @@ func TestStoreIcon(t *testing.T) { func TestFetchIcon(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) png := []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR") diff --git a/internal/provider/install_test.go b/internal/provider/install_test.go index 8d96c88e..23a2b89d 100644 --- a/internal/provider/install_test.go +++ b/internal/provider/install_test.go @@ -86,7 +86,7 @@ func TestSignInInstallFails(t *testing.T) { t.Fatal(err) } st = waitPast(t, st.ID, "installing") - if st.State != "failed" || !strings.Contains(st.Error, "Error: Failed to download") || !strings.Contains(st.Error, "install.") { + if st.State != "failed" || !strings.Contains(st.Error, "Error: Failed to download") || !strings.Contains(st.Error, "install it yourself") { t.Fatalf("state %+v", st) } } diff --git a/internal/provider/key_quota_last_test.go b/internal/provider/key_quota_last_test.go index 5a82d735..d8761cff 100644 --- a/internal/provider/key_quota_last_test.go +++ b/internal/provider/key_quota_last_test.go @@ -18,6 +18,7 @@ func TestKeyQuotasKeepLast(t *testing.T) { isolate(t) h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) t.Setenv("PATH", h) diff --git a/internal/provider/kiro_test.go b/internal/provider/kiro_test.go index b22c077c..493b00a8 100644 --- a/internal/provider/kiro_test.go +++ b/internal/provider/kiro_test.go @@ -19,6 +19,7 @@ func kiroSandbox(t *testing.T) string { t.Helper() home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) db, ide, exe, ask := kiroCLIDB, kiroIDEDir, KiroExecutable, askKiroIdentity diff --git a/internal/provider/limits_test.go b/internal/provider/limits_test.go index 02608c5c..9c5e7306 100644 --- a/internal/provider/limits_test.go +++ b/internal/provider/limits_test.go @@ -15,6 +15,7 @@ func limitsHome(t *testing.T) { t.Helper() home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) catalog.Reset() diff --git a/internal/provider/logins_test.go b/internal/provider/logins_test.go index 809039f2..309c22aa 100644 --- a/internal/provider/logins_test.go +++ b/internal/provider/logins_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "os" "path/filepath" + "runtime" "strings" "testing" "time" @@ -42,7 +43,7 @@ func TestCodexLogins(t *testing.T) { if strings.Join(users, ",") != "me@example.com,work@example.com" || active != "work@example.com" { t.Fatalf("logins %v, active %q", users, active) } - if fi, err := os.Stat(loginsPath()); err != nil || fi.Mode().Perm() != 0o600 { + if fi, err := os.Stat(loginsPath()); err != nil || runtime.GOOS != "windows" && fi.Mode().Perm() != 0o600 { t.Fatalf("logins.json mode: %v %v", fi, err) } // the agent refreshes the active login in place; a switch keeps that diff --git a/internal/provider/maker_efforts_test.go b/internal/provider/maker_efforts_test.go index ca932412..e9ac5f81 100644 --- a/internal/provider/maker_efforts_test.go +++ b/internal/provider/maker_efforts_test.go @@ -33,6 +33,7 @@ func makerHome(t *testing.T) { t.Helper() home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) if err := os.MkdirAll(filepath.Dir(catalog.CachePath()), 0o755); err != nil { diff --git a/internal/provider/modelprefs_test.go b/internal/provider/modelprefs_test.go index 04bb4552..c1302df7 100644 --- a/internal/provider/modelprefs_test.go +++ b/internal/provider/modelprefs_test.go @@ -24,6 +24,7 @@ func prefsHome(t *testing.T) { t.Helper() home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) t.Setenv("CLAUDE_CONFIG_DIR", filepath.Join(home, ".claude")) diff --git a/internal/provider/models_test.go b/internal/provider/models_test.go index a6988473..bc59f230 100644 --- a/internal/provider/models_test.go +++ b/internal/provider/models_test.go @@ -14,6 +14,7 @@ import ( func TestExplicitTextOnlyBeatsCrossProviderImageGuess(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) if err := os.MkdirAll(filepath.Dir(catalog.CachePath()), 0o755); err != nil { @@ -114,6 +115,7 @@ func TestOffKeyIsNotFetched(t *testing.T) { isolate(t) h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) t.Setenv("PATH", h) @@ -199,6 +201,7 @@ func modelNamed(ms []catalog.Model, id string) (catalog.Model, bool) { func TestRejectsTemperatureFromFetchedList(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CACHE_HOME", home) no, yes := false, true diff --git a/internal/provider/modelsurl_test.go b/internal/provider/modelsurl_test.go index 9c33b277..6516ae2a 100644 --- a/internal/provider/modelsurl_test.go +++ b/internal/provider/modelsurl_test.go @@ -15,6 +15,7 @@ func TestFetchFromModelsURL(t *testing.T) { isolate(t) h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) t.Setenv("PATH", h) diff --git a/internal/provider/native_test.go b/internal/provider/native_test.go index 3c274d4c..27ba21de 100644 --- a/internal/provider/native_test.go +++ b/internal/provider/native_test.go @@ -12,6 +12,7 @@ import ( func TestNative(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) catalog.Reset() diff --git a/internal/provider/off_test.go b/internal/provider/off_test.go index c0127ade..4afbf88c 100644 --- a/internal/provider/off_test.go +++ b/internal/provider/off_test.go @@ -9,6 +9,7 @@ import ( // off: an account's too, which keeps only the user's settings. func TestProviderOffKept(t *testing.T) { t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) t.Setenv("XDG_CACHE_HOME", t.TempDir()) if err := Save(Provider{ID: "relay", Name: "Relay", Key: "sk-1", Chat: "https://relay.example.com/v1", Models: []string{"m"}}); err != nil { diff --git a/internal/provider/planquota_test.go b/internal/provider/planquota_test.go index 5ec8f72d..587f3448 100644 --- a/internal/provider/planquota_test.go +++ b/internal/provider/planquota_test.go @@ -217,6 +217,7 @@ func TestPlanQuotas(t *testing.T) { isolate(t) h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) t.Setenv("PATH", h) diff --git a/internal/provider/plugin_icon_test.go b/internal/provider/plugin_icon_test.go index 327623ae..31a0e1c4 100644 --- a/internal/provider/plugin_icon_test.go +++ b/internal/provider/plugin_icon_test.go @@ -21,6 +21,7 @@ import ( func TestPluginOwnIcon(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) t.Setenv("MAGPIE_PLUGIN_MARKET", "off") diff --git a/internal/provider/price_override_test.go b/internal/provider/price_override_test.go index 61742c37..5c4f967e 100644 --- a/internal/provider/price_override_test.go +++ b/internal/provider/price_override_test.go @@ -16,6 +16,7 @@ func priceHome(t *testing.T) { t.Helper() home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) catalog.Reset() diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index b85c8102..48f03a36 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -37,6 +37,7 @@ func TestAddNameWithoutLatin(t *testing.T) { isolate(t) home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) for _, c := range []struct{ name, url, key, want string }{ @@ -62,6 +63,7 @@ func TestAddSecondOfPreset(t *testing.T) { isolate(t) home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) add := func(ws string) string { diff --git a/internal/provider/rename_test.go b/internal/provider/rename_test.go index dcb1f296..3643cc07 100644 --- a/internal/provider/rename_test.go +++ b/internal/provider/rename_test.go @@ -12,6 +12,7 @@ import ( func TestRename(t *testing.T) { isolate(t) t.Setenv("HOME", t.TempDir()) + t.Setenv("USERPROFILE", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) t.Setenv("XDG_CACHE_HOME", t.TempDir()) for _, id := range []string{"relay", "other"} { diff --git a/internal/provider/signedout_test.go b/internal/provider/signedout_test.go index da40eafb..8bcb6611 100644 --- a/internal/provider/signedout_test.go +++ b/internal/provider/signedout_test.go @@ -14,6 +14,7 @@ func TestSavedButSignedOut(t *testing.T) { isolate(t) home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("CLAUDE_CONFIG_DIR", "") if err := writeLogins([]savedLogin{ @@ -65,6 +66,7 @@ func TestSavedButSignedOutClaudeSaysWhy(t *testing.T) { if w := why(); !strings.Contains(w, "nothing at "+filepath.Join(home, ".claude", ".credentials.json")) { t.Fatalf("no credentials: %q", w) } + shellFakes(t) claudeSignIn(t, home, time.Now().Add(time.Hour)) exe := filepath.Join(home, "claude") os.WriteFile(exe, []byte("#!/bin/sh\necho '{\"loggedIn\": false}'\n"), 0o755) @@ -116,6 +118,7 @@ func TestSavedButSignedOutCanBeRemoved(t *testing.T) { // under its account: another item for the same service (one an earlier // sign-in left) that comes first by service alone isn't taken for it. func TestClaudeKeychainReadsItsAccount(t *testing.T) { + shellFakes(t) home := claudeHome(t) t.Setenv("CLAUDE_CONFIG_DIR", "") t.Setenv("USER", "tester") diff --git a/internal/provider/signin_stale_test.go b/internal/provider/signin_stale_test.go index 3b9e043c..1eeaffcf 100644 --- a/internal/provider/signin_stale_test.go +++ b/internal/provider/signin_stale_test.go @@ -14,6 +14,7 @@ import ( // through magpie then is the account Claude Code uses, not one kept beside a // stale one, and it shows up as a provider (#31). func TestClaudeSignInOverStaleCredentials(t *testing.T) { + shellFakes(t) home := claudeHome(t) fake := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { diff --git a/internal/provider/stepfun_plan_test.go b/internal/provider/stepfun_plan_test.go index ee4a2dee..91640e59 100644 --- a/internal/provider/stepfun_plan_test.go +++ b/internal/provider/stepfun_plan_test.go @@ -6,6 +6,7 @@ import ( "net/http" "net/http/httptest" "os" + "runtime" "strings" "sync/atomic" "testing" @@ -129,7 +130,7 @@ func TestStepFunSession(t *testing.T) { if err := SaveStepFunSession(ctx, "ai", acc, ref, "web-1"); err != nil { t.Fatal(err) } - if fi, err := os.Stat(stepfunPath()); err != nil || fi.Mode().Perm() != 0o600 { + if fi, err := os.Stat(stepfunPath()); err != nil || runtime.GOOS != "windows" && fi.Mode().Perm() != 0o600 { t.Fatalf("session file: %v %v", fi, err) } p := Provider{ID: "stepfun", Name: "StepFun", Icon: "stepfun-color", Chat: "https://api.stepfun.ai/step_plan/v1"} diff --git a/internal/provider/symlink_test.go b/internal/provider/symlink_test.go index 8695b117..a72c238f 100644 --- a/internal/provider/symlink_test.go +++ b/internal/provider/symlink_test.go @@ -3,6 +3,7 @@ package provider import ( "os" "path/filepath" + "runtime" "testing" ) @@ -31,7 +32,7 @@ func TestPrivateWritesKeepSymlink(t *testing.T) { if string(b) != `{"a":1}` { t.Errorf("%s: target %q", name, b) } - if st, _ := os.Stat(target); st.Mode().Perm() != 0o600 { + if st, _ := os.Stat(target); runtime.GOOS != "windows" && st.Mode().Perm() != 0o600 { t.Errorf("%s: mode %v", name, st.Mode().Perm()) } } diff --git a/internal/provider/test_test.go b/internal/provider/test_test.go index d569288d..b9ae827e 100644 --- a/internal/provider/test_test.go +++ b/internal/provider/test_test.go @@ -16,6 +16,7 @@ import ( func TestTestUsesEachEndpointsKey(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) seen := map[string]string{} // path → key and model it got @@ -66,6 +67,7 @@ func TestTestUsesEachEndpointsKey(t *testing.T) { func TestTestModels(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) var mu sync.Mutex @@ -114,6 +116,7 @@ func TestTestModels(t *testing.T) { func TestTestModelsDraws(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) var mu sync.Mutex diff --git a/internal/provider/zhipu_team_key_test.go b/internal/provider/zhipu_team_key_test.go index c4602c95..23a66a0d 100644 --- a/internal/provider/zhipu_team_key_test.go +++ b/internal/provider/zhipu_team_key_test.go @@ -18,6 +18,7 @@ func TestZhipuKeyTeamFields(t *testing.T) { isolate(t) h := t.TempDir() t.Setenv("HOME", h) + t.Setenv("USERPROFILE", h) t.Setenv("XDG_CONFIG_HOME", filepath.Join(h, ".config")) t.Setenv("XDG_CACHE_HOME", filepath.Join(h, ".cache")) t.Setenv("PATH", h)