first commit
This commit is contained in:
246
cli/internal/harness/harness_test.go
Normal file
246
cli/internal/harness/harness_test.go
Normal file
@@ -0,0 +1,246 @@
|
||||
package harness
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
)
|
||||
|
||||
func TestClaudePreLaunchPinsSelectedModelAcrossClaudeTiers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
env, cleanup, err := claudePreLaunch("https://example.com/anthropic", "test-key", "openai/gpt-5")
|
||||
if err != nil {
|
||||
t.Fatalf("claudePreLaunch() error = %v", err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
for _, want := range []string{
|
||||
"CLAUDE_CODE_SIMPLE=1",
|
||||
"ANTHROPIC_DEFAULT_SONNET_MODEL=openai/gpt-5",
|
||||
"ANTHROPIC_DEFAULT_OPUS_MODEL=openai/gpt-5",
|
||||
"ANTHROPIC_DEFAULT_HAIKU_MODEL=openai/gpt-5",
|
||||
} {
|
||||
parts := strings.SplitN(want, "=", 2)
|
||||
if got := envValue(env, parts[0]); got != parts[1] {
|
||||
t.Fatalf("env[%q] = %q, want %q", parts[0], got, parts[1])
|
||||
}
|
||||
}
|
||||
|
||||
if got := envValue(env, "ANTHROPIC_MODEL"); got != "" {
|
||||
t.Fatalf("did not expect ANTHROPIC_MODEL in env, got %#v", env)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClaudeWriteNativeConfigPinsTierDefaults(t *testing.T) {
|
||||
home := t.TempDir()
|
||||
t.Setenv("HOME", home)
|
||||
|
||||
settingsDir := filepath.Join(home, ".claude")
|
||||
if err := os.MkdirAll(settingsDir, 0o755); err != nil {
|
||||
t.Fatalf("mkdir settings dir: %v", err)
|
||||
}
|
||||
settingsPath := filepath.Join(settingsDir, "settings.json")
|
||||
initial := `{"env":{"EXISTING":"keep","ANTHROPIC_MODEL":"stale-model"}}`
|
||||
if err := os.WriteFile(settingsPath, []byte(initial), 0o600); err != nil {
|
||||
t.Fatalf("write initial settings: %v", err)
|
||||
}
|
||||
|
||||
if err := claudeWriteNativeConfig("https://example.com/anthropic", "test-key", "openai/gpt-5"); err != nil {
|
||||
t.Fatalf("claudeWriteNativeConfig() error = %v", err)
|
||||
}
|
||||
|
||||
b, err := os.ReadFile(settingsPath)
|
||||
if err != nil {
|
||||
t.Fatalf("read settings: %v", err)
|
||||
}
|
||||
|
||||
var settings map[string]any
|
||||
if err := sonic.Unmarshal(b, &settings); err != nil {
|
||||
t.Fatalf("unmarshal settings: %v", err)
|
||||
}
|
||||
|
||||
envRaw, ok := settings["env"]
|
||||
if !ok {
|
||||
t.Fatalf("expected env map in settings, got %#v", settings)
|
||||
}
|
||||
envMap, ok := envRaw.(map[string]any)
|
||||
if !ok {
|
||||
t.Fatalf("env map type = %T, want map[string]any", envRaw)
|
||||
}
|
||||
|
||||
for key, want := range map[string]string{
|
||||
"EXISTING": "keep",
|
||||
"ANTHROPIC_BASE_URL": "https://example.com/anthropic",
|
||||
"ANTHROPIC_API_KEY": "test-key",
|
||||
"ANTHROPIC_DEFAULT_SONNET_MODEL": "openai/gpt-5",
|
||||
"ANTHROPIC_DEFAULT_OPUS_MODEL": "openai/gpt-5",
|
||||
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "openai/gpt-5",
|
||||
} {
|
||||
if got, _ := envMap[key].(string); got != want {
|
||||
t.Fatalf("env[%q] = %q, want %q", key, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := envMap["ANTHROPIC_MODEL"]; ok {
|
||||
t.Fatalf("did not expect legacy ANTHROPIC_MODEL in settings env: %#v", envMap)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpencodeModelRef(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if got := opencodeModelRef("gpt-4.1"); got != "bifrost/gpt-4.1" {
|
||||
t.Fatalf("opencodeModelRef() = %q, want %q", got, "bifrost/gpt-4.1")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpencodePreLaunchWritesCustomProviderConfig(t *testing.T) {
|
||||
xdg := t.TempDir()
|
||||
t.Setenv("XDG_CONFIG_HOME", xdg)
|
||||
|
||||
env, cleanup, err := opencodePreLaunch("https://example.com/openai", "test-key", "gpt-4.1")
|
||||
if err != nil {
|
||||
t.Fatalf("opencodePreLaunch() error = %v", err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
if len(env) != 2 {
|
||||
t.Fatalf("unexpected env returned: %#v", env)
|
||||
}
|
||||
|
||||
configPath := envValue(env, "OPENCODE_CONFIG")
|
||||
if configPath == "" {
|
||||
t.Fatalf("expected OPENCODE_CONFIG in env, got %#v", env)
|
||||
}
|
||||
b, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
t.Fatalf("read generated config: %v", err)
|
||||
}
|
||||
|
||||
cfg := string(b)
|
||||
for _, want := range []string{
|
||||
`"model": "bifrost/gpt-4.1"`,
|
||||
`"bifrost": {`,
|
||||
`"npm": "@ai-sdk/openai-compatible"`,
|
||||
`"baseURL": "https://example.com/openai"`,
|
||||
`"apiKey": "test-key"`,
|
||||
`"gpt-4.1": {`,
|
||||
} {
|
||||
if !strings.Contains(cfg, want) {
|
||||
t.Fatalf("expected generated config to contain %q, got %s", want, cfg)
|
||||
}
|
||||
}
|
||||
|
||||
tuiPath := envValue(env, "OPENCODE_TUI_CONFIG")
|
||||
if tuiPath == "" {
|
||||
t.Fatalf("expected OPENCODE_TUI_CONFIG in env, got %#v", env)
|
||||
}
|
||||
tuiCfg, err := os.ReadFile(tuiPath)
|
||||
if err != nil {
|
||||
t.Fatalf("read generated tui config: %v", err)
|
||||
}
|
||||
if !strings.Contains(string(tuiCfg), `"theme": "system"`) {
|
||||
t.Fatalf("expected generated tui config to set system theme, got %s", string(tuiCfg))
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpencodePreLaunchPreservesExistingTheme(t *testing.T) {
|
||||
xdg := t.TempDir()
|
||||
t.Setenv("XDG_CONFIG_HOME", xdg)
|
||||
|
||||
tuiPath := filepath.Join(xdg, "opencode", "tui.json")
|
||||
if err := os.MkdirAll(filepath.Dir(tuiPath), 0o755); err != nil {
|
||||
t.Fatalf("mkdir tui dir: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(tuiPath, []byte("{\n \"theme\": \"light\"\n}\n"), 0o600); err != nil {
|
||||
t.Fatalf("write tui config: %v", err)
|
||||
}
|
||||
|
||||
env, cleanup, err := opencodePreLaunch("https://example.com/openai", "test-key", "gpt-4.1")
|
||||
if err != nil {
|
||||
t.Fatalf("opencodePreLaunch() error = %v", err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
if got := envValue(env, "OPENCODE_TUI_CONFIG"); got != "" {
|
||||
t.Fatalf("did not expect OPENCODE_TUI_CONFIG override when user theme exists, got %#v", env)
|
||||
}
|
||||
if got := envValue(env, "OPENCODE_CONFIG"); got == "" {
|
||||
t.Fatalf("expected OPENCODE_CONFIG to remain present, got %#v", env)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpencodePreLaunchAddsSystemThemeWithoutModel(t *testing.T) {
|
||||
xdg := t.TempDir()
|
||||
t.Setenv("XDG_CONFIG_HOME", xdg)
|
||||
|
||||
env, cleanup, err := opencodePreLaunch("https://example.com/openai", "test-key", "")
|
||||
if err != nil {
|
||||
t.Fatalf("opencodePreLaunch() error = %v", err)
|
||||
}
|
||||
|
||||
tuiPath := envValue(env, "OPENCODE_TUI_CONFIG")
|
||||
if tuiPath == "" {
|
||||
t.Fatalf("expected OPENCODE_TUI_CONFIG in env, got %#v", env)
|
||||
}
|
||||
if got := envValue(env, "OPENCODE_CONFIG"); got != "" {
|
||||
t.Fatalf("did not expect OPENCODE_CONFIG without a model, got %#v", env)
|
||||
}
|
||||
if _, err := os.Stat(tuiPath); err != nil {
|
||||
t.Fatalf("expected generated tui config to exist: %v", err)
|
||||
}
|
||||
|
||||
cleanup()
|
||||
if _, err := os.Stat(tuiPath); !os.IsNotExist(err) {
|
||||
t.Fatalf("expected generated tui config to be removed after cleanup, stat err=%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadOpencodeTUIConfigSupportsJSONC(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
path := filepath.Join(t.TempDir(), "tui.json")
|
||||
content := "{\n // keep my choice\n \"theme\": \"light\",\n \"foo\": true,\n}\n"
|
||||
if err := os.WriteFile(path, []byte(content), 0o600); err != nil {
|
||||
t.Fatalf("write tui config: %v", err)
|
||||
}
|
||||
|
||||
cfg, hasTheme, err := loadOpencodeTUIConfig(path)
|
||||
if err != nil {
|
||||
t.Fatalf("loadOpencodeTUIConfig() error = %v", err)
|
||||
}
|
||||
if !hasTheme {
|
||||
t.Fatal("expected theme to be detected")
|
||||
}
|
||||
if cfg["theme"] != "light" {
|
||||
t.Fatalf("cfg[theme] = %#v, want %q", cfg["theme"], "light")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpencodeTUIConfigPathPrefersXDG(t *testing.T) {
|
||||
xdg := t.TempDir()
|
||||
t.Setenv("XDG_CONFIG_HOME", xdg)
|
||||
|
||||
got, err := opencodeTUIConfigPath()
|
||||
if err != nil {
|
||||
t.Fatalf("opencodeTUIConfigPath() error = %v", err)
|
||||
}
|
||||
want := filepath.Join(xdg, "opencode", "tui.json")
|
||||
if got != want {
|
||||
t.Fatalf("opencodeTUIConfigPath() = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func envValue(env []string, key string) string {
|
||||
prefix := key + "="
|
||||
for _, entry := range env {
|
||||
if strings.HasPrefix(entry, prefix) {
|
||||
return strings.TrimPrefix(entry, prefix)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user