package config
import (
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
cmdutil "gitcode.com/gitcode-cli/cli/pkg/cmdutil"
"gitcode.com/gitcode-cli/cli/pkg/config"
"gitcode.com/gitcode-cli/cli/pkg/iostreams"
)
func TestNewCmdList(t *testing.T) {
cmd := newCmdList(cmdutil.TestFactory())
if cmd == nil {
t.Fatal("newCmdList returned nil")
}
if cmd.Use != "list" {
t.Fatalf("cmd.Use = %q, want %q", cmd.Use, "list")
}
}
func TestNewCmdListFlagsExist(t *testing.T) {
cmd := newCmdList(cmdutil.TestFactory())
if cmd.Flags().Lookup("json") == nil {
t.Fatal("json flag missing")
}
}
func TestNewCmdClearCache(t *testing.T) {
cmd := newCmdClearCache(cmdutil.TestFactory())
if cmd == nil {
t.Fatal("newCmdClearCache returned nil")
}
if cmd.Use != "clear-cache" {
t.Fatalf("cmd.Use = %q, want %q", cmd.Use, "clear-cache")
}
}
func TestListConfig(t *testing.T) {
t.Setenv("GC_CONFIG_DIR", t.TempDir())
cfg := config.New()
_ = cfg.Set(defaultHost, "browser", "firefox")
_ = cfg.Set(defaultHost, "default_repo", "owner/repo")
_ = cfg.Write()
items, err := listConfig(cfg)
if err != nil {
t.Fatalf("listConfig() error = %v", err)
}
if len(items) != 5 {
t.Fatalf("len(items) = %d, want 5", len(items))
}
want := map[string]string{
"browser": "config",
"default_repo": "config",
"editor": "default",
"pager": "default",
"update.mode": "default",
}
for _, item := range items {
if src, ok := want[item.Key]; ok {
if item.Source != src {
t.Errorf("key %q: source = %q, want %q", item.Key, item.Source, src)
}
}
}
}
func TestListConfigEnvOverride(t *testing.T) {
t.Setenv("GC_CONFIG_DIR", t.TempDir())
t.Setenv("GC_BROWSER", "chrome")
cfg := config.New()
items, _ := listConfig(cfg)
for _, item := range items {
if item.Key == "browser" {
if item.Value != "chrome" {
t.Fatalf("browser value = %q, want %q", item.Value, "chrome")
}
if item.Source != "environment" {
t.Fatalf("browser source = %q, want %q", item.Source, "environment")
}
}
}
}
func TestListConfigUpdateModeDefault(t *testing.T) {
t.Setenv("GC_CONFIG_DIR", t.TempDir())
cfg := config.New()
items, _ := listConfig(cfg)
for _, item := range items {
if item.Key == "update.mode" {
if item.Value != "notify" {
t.Fatalf("update.mode value = %q, want %q", item.Value, "notify")
}
if item.Source != "default" {
t.Fatalf("update.mode source = %q, want %q", item.Source, "default")
}
}
}
}
func TestListConfigJSONOutput(t *testing.T) {
t.Setenv("GC_CONFIG_DIR", t.TempDir())
f := cmdutil.TestFactory()
cmd := newCmdList(f)
var buf strings.Builder
cmd.SetOut(&buf)
cmd.SetArgs([]string{"--json"})
if err := cmd.Execute(); err != nil {
t.Fatalf("Execute() error = %v", err)
}
var items []configListItem
if err := json.Unmarshal([]byte(buf.String()), &items); err != nil {
t.Fatalf("output is not valid JSON: %v; raw: %s", err, buf.String())
}
if len(items) != 5 {
t.Fatalf("len(items) = %d, want 5", len(items))
}
}
func TestListConfigHumanReadable(t *testing.T) {
t.Setenv("GC_CONFIG_DIR", t.TempDir())
f := cmdutil.TestFactory()
cmd := newCmdList(f)
var buf strings.Builder
cmd.SetOut(&buf)
cmd.SetArgs([]string{})
if err := cmd.Execute(); err != nil {
t.Fatalf("Execute() error = %v", err)
}
out := buf.String()
for _, key := range []string{"browser", "editor", "pager", "update.mode", "default_repo"} {
if !strings.Contains(out, key) {
t.Errorf("output missing key %q; output=%s", key, out)
}
}
}
func TestClearCacheEmpty(t *testing.T) {
t.Setenv("GC_CONFIG_DIR", t.TempDir())
io, _, out, _ := iostreams.Test()
if err := clearCache(io); err != nil {
t.Fatalf("clearCache() error = %v", err)
}
if !strings.Contains(out.String(), "No cache to clear") {
t.Fatalf("output should say no cache; got: %s", out.String())
}
}
func TestClearCacheWithFiles(t *testing.T) {
dir := t.TempDir()
t.Setenv("GC_CONFIG_DIR", dir)
cacheDir := filepath.Join(dir, "cache")
if err := os.MkdirAll(cacheDir, 0o700); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(cacheDir, "test.tmp"), []byte("test"), 0o600); err != nil {
t.Fatal(err)
}
io, _, out, _ := iostreams.Test()
if err := clearCache(io); err != nil {
t.Fatalf("clearCache() error = %v", err)
}
if !strings.Contains(out.String(), "Cleared 1 cache") {
t.Fatalf("output should say cleared 1; got: %s", out.String())
}
entries, _ := os.ReadDir(cacheDir)
if len(entries) != 0 {
t.Fatalf("cache dir should be empty; has %d entries", len(entries))
}
}
func TestResolveConfigValueEnv(t *testing.T) {
t.Setenv("GC_BROWSER", "safari")
cfg := config.New()
value, source := resolveConfigValue(cfg, "browser")
if value != "safari" || source != "environment" {
t.Fatalf("value=%q source=%q, want safari/environment", value, source)
}
}
func TestResolveConfigValueConfig(t *testing.T) {
t.Setenv("GC_CONFIG_DIR", t.TempDir())
cfg := config.New()
_ = cfg.Set(defaultHost, "editor", "vim")
_ = cfg.Write()
value, source := resolveConfigValue(cfg, "editor")
if value != "vim" || source != "config" {
t.Fatalf("value=%q source=%q, want vim/config", value, source)
}
}
func TestResolveConfigValueDefault(t *testing.T) {
t.Setenv("GC_CONFIG_DIR", t.TempDir())
cfg := config.New()
value, source := resolveConfigValue(cfg, "default_repo")
if value != "" || source != "default" {
t.Fatalf("value=%q source=%q, want empty/default", value, source)
}
}
func TestResolveConfigValueUpdateModeDefault(t *testing.T) {
t.Setenv("GC_CONFIG_DIR", t.TempDir())
cfg := config.New()
value, source := resolveConfigValue(cfg, "update.mode")
if value != "notify" || source != "default" {
t.Fatalf("value=%q source=%q, want notify/default", value, source)
}
}
func TestConfigDirFromEnv(t *testing.T) {
dir := t.TempDir()
t.Setenv("GC_CONFIG_DIR", dir)
got := configDir()
if got != dir {
t.Fatalf("configDir() = %q, want %q", got, dir)
}
}
func TestPluralEntry(t *testing.T) {
if got := pluralEntry(1); got != "y" {
t.Errorf("pluralEntry(1) = %q, want %q", got, "y")
}
if got := pluralEntry(2); got != "ies" {
t.Errorf("pluralEntry(2) = %q, want %q", got, "ies")
}
}