| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- package config
- import (
- "bytes"
- "errors"
- "path/filepath"
- "strings"
- "testing"
- )
- func TestLoad_ValidTwoAccounts(t *testing.T) {
- var warn bytes.Buffer
- cfg, err := Load(filepath.Join("testdata", "valid_two_accounts.yaml"), &warn)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if len(cfg.Accounts) != 2 {
- t.Fatalf("want 2 accounts, got %d", len(cfg.Accounts))
- }
- if cfg.Accounts[0].Name != "personal" || cfg.Accounts[1].Name != "work" {
- t.Fatalf("wrong order or names: %+v", cfg.Accounts)
- }
- if warn.Len() != 0 {
- t.Fatalf("expected no warnings, got %q", warn.String())
- }
- }
- func TestLoad_DuplicateNames(t *testing.T) {
- _, err := Load(filepath.Join("testdata", "duplicate_names.yaml"), nil)
- if !errors.Is(err, ErrParse) {
- t.Fatalf("want ErrParse, got %v", err)
- }
- if !strings.Contains(err.Error(), "duplicate") {
- t.Fatalf("error message should mention duplicate, got %v", err)
- }
- }
- func TestLoad_MissingAPIKey(t *testing.T) {
- _, err := Load(filepath.Join("testdata", "missing_api_key.yaml"), nil)
- if !errors.Is(err, ErrParse) {
- t.Fatalf("want ErrParse, got %v", err)
- }
- if !strings.Contains(err.Error(), "api_key") {
- t.Fatalf("error message should mention api_key, got %v", err)
- }
- }
- func TestLoad_EmptyAccounts(t *testing.T) {
- _, err := Load(filepath.Join("testdata", "empty_accounts.yaml"), nil)
- if !errors.Is(err, ErrParse) {
- t.Fatalf("want ErrParse, got %v", err)
- }
- }
- func TestLoad_UnknownFieldsWarn(t *testing.T) {
- var warn bytes.Buffer
- cfg, err := Load(filepath.Join("testdata", "unknown_fields.yaml"), &warn)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if len(cfg.Accounts) != 1 {
- t.Fatalf("want 1 account, got %d", len(cfg.Accounts))
- }
- warnings := warn.String()
- if !strings.Contains(warnings, `"notifications"`) {
- t.Errorf("expected top-level warning for notifications, got %q", warnings)
- }
- if !strings.Contains(warnings, `"color"`) {
- t.Errorf("expected per-account warning for color, got %q", warnings)
- }
- }
- func TestLoad_Malformed(t *testing.T) {
- _, err := Load(filepath.Join("testdata", "malformed.yaml"), nil)
- if !errors.Is(err, ErrParse) {
- t.Fatalf("want ErrParse, got %v", err)
- }
- }
- func TestLoad_MissingFile(t *testing.T) {
- _, err := Load(filepath.Join("testdata", "does_not_exist.yaml"), nil)
- if err == nil {
- t.Fatal("expected error for missing file")
- }
- // Missing file is NOT an ErrParse — callers distinguish.
- if errors.Is(err, ErrParse) {
- t.Fatalf("missing file should not be ErrParse, got %v", err)
- }
- }
- func TestResolve_APIKeyBeatsConfig(t *testing.T) {
- cfg := &Config{Accounts: []Account{
- {Name: "personal", APIKey: "sk-p"},
- {Name: "work", APIKey: "sk-w"},
- }}
- accs, err := Resolve(cfg, ResolveFlags{APIKey: "sk-ad-hoc"})
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if len(accs) != 1 || accs[0].Name != "cli" || accs[0].APIKey != "sk-ad-hoc" {
- t.Fatalf("want single cli account with ad-hoc key, got %+v", accs)
- }
- }
- func TestResolve_AccountFilter(t *testing.T) {
- cfg := &Config{Accounts: []Account{
- {Name: "personal", APIKey: "sk-p"},
- {Name: "work", APIKey: "sk-w"},
- }}
- accs, err := Resolve(cfg, ResolveFlags{AccountName: "work"})
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if len(accs) != 1 || accs[0].Name != "work" {
- t.Fatalf("want work account, got %+v", accs)
- }
- }
- func TestResolve_AccountNotFound(t *testing.T) {
- cfg := &Config{Accounts: []Account{
- {Name: "personal", APIKey: "sk-p"},
- }}
- _, err := Resolve(cfg, ResolveFlags{AccountName: "missing"})
- if !errors.Is(err, ErrAccountNotFound) {
- t.Fatalf("want ErrAccountNotFound, got %v", err)
- }
- if !strings.Contains(err.Error(), "personal") {
- t.Fatalf("error should list available accounts, got %v", err)
- }
- }
- func TestResolve_AllAccountsInOrder(t *testing.T) {
- cfg := &Config{Accounts: []Account{
- {Name: "a", APIKey: "1"},
- {Name: "b", APIKey: "2"},
- {Name: "c", APIKey: "3"},
- }}
- accs, err := Resolve(cfg, ResolveFlags{})
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if len(accs) != 3 {
- t.Fatalf("want 3 accounts, got %d", len(accs))
- }
- for i, want := range []string{"a", "b", "c"} {
- if accs[i].Name != want {
- t.Errorf("accs[%d].Name = %q, want %q", i, accs[i].Name, want)
- }
- }
- }
- func TestResolve_EnvFallback(t *testing.T) {
- accs, err := Resolve(nil, ResolveFlags{EnvAPIKey: "sk-env"})
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if len(accs) != 1 || accs[0].Name != "env" || accs[0].APIKey != "sk-env" {
- t.Fatalf("want env account, got %+v", accs)
- }
- }
- func TestResolve_NoAccount(t *testing.T) {
- _, err := Resolve(nil, ResolveFlags{})
- if !errors.Is(err, ErrNoAccount) {
- t.Fatalf("want ErrNoAccount, got %v", err)
- }
- }
- func TestDefaultPath_XDGOverride(t *testing.T) {
- t.Setenv("XDG_CONFIG_HOME", "/custom/xdg")
- got := DefaultPath()
- want := filepath.Join("/custom/xdg", "zenmux-usage", "config.yaml")
- if got != want {
- t.Errorf("DefaultPath() = %q, want %q", got, want)
- }
- }
- func TestDefaultPath_HomeFallback(t *testing.T) {
- t.Setenv("XDG_CONFIG_HOME", "")
- t.Setenv("HOME", "/fake/home")
- got := DefaultPath()
- want := filepath.Join("/fake/home", ".config", "zenmux-usage", "config.yaml")
- if got != want {
- t.Errorf("DefaultPath() = %q, want %q", got, want)
- }
- }
|