1package main
2
3import (
4 "os"
5 "path/filepath"
6 "testing"
7)
8
9func writeJSON(t *testing.T, path, content string) {
10 t.Helper()
11 if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
12 t.Fatal(err)
13 }
14 if err := os.WriteFile(path, []byte(content), 0o600); err != nil {
15 t.Fatal(err)
16 }
17}
18
19func TestLoadConfigProjectOverridesGlobal(t *testing.T) {
20 home := t.TempDir()
21 proj := t.TempDir()
22 t.Setenv("ZOT_HOME", home)
23
24 writeJSON(t, filepath.Join(home, "mcp.json"), `{
25 "mcpServers": {
26 "shared": {"command": "global-cmd"},
27 "global-only": {"command": "g"}
28 }
29 }`)
30 writeJSON(t, filepath.Join(proj, ".zot", "mcp.json"), `{
31 "mcpServers": {
32 "shared": {"command": "project-cmd"}
33 }
34 }`)
35
36 cfg, err := loadConfig(proj)
37 if err != nil {
38 t.Fatalf("loadConfig: %v", err)
39 }
40 if got := cfg.MCPServers["shared"].Command; got != "project-cmd" {
41 t.Fatalf("project must override global: shared.command = %q", got)
42 }
43 if _, ok := cfg.MCPServers["global-only"]; !ok {
44 t.Fatal("global-only server lost in merge")
45 }
46 // Defaults applied during merge:
47 if got := cfg.MCPServers["shared"].RequestTimeout; got != 60 {
48 t.Fatalf("default requestTimeout = %d, want 60", got)
49 }
50}
51
52func TestLoadConfigMissingFilesIsNotAnError(t *testing.T) {
53 t.Setenv("ZOT_HOME", t.TempDir())
54 cfg, err := loadConfig(t.TempDir())
55 if err != nil {
56 t.Fatalf("loadConfig with no files: %v", err)
57 }
58 if len(cfg.MCPServers) != 0 {
59 t.Fatalf("expected empty config, got %+v", cfg.MCPServers)
60 }
61}
62
63func TestHandleSetupProjectRequiresCwd(t *testing.T) {
64 t.Setenv("ZOT_HOME", t.TempDir())
65 if _, err := handleSetup([]string{"add", "grep", "--project"}, ""); err == nil {
66 t.Fatal("expected error for --project with unknown working directory")
67 }
68}