package config import ( "os" "path/filepath" "strings" "testing" "github.com/stretchr/testify/require" ) func TestDevelopmentConfigMatchesLocalWorkspaceContract(t *testing.T) { t.Setenv("SENLIN_APP_MODE", "dev") cfg, err := LoadFromDir(filepath.Join("..", "..", "etc")) require.NoError(t, err) require.Equal(t, "development", cfg.Env) require.Equal(t, "9150", cfg.Port) require.Equal(t, "postgres://agent:agent@localhost:5432/agent?sslmode=disable", cfg.DSN) require.NotEmpty(t, strings.TrimSpace(cfg.StorageDir)) require.Equal(t, int64(32<<20), cfg.MaxUploadBytes) require.ElementsMatch(t, []string{ "http://localhost:5173", "http://127.0.0.1:5173", "http://localhost:4173", "http://127.0.0.1:4173", "http://localhost:4174", "http://127.0.0.1:4174", "http://localhost:4175", "http://127.0.0.1:4175", "http://localhost:4176", "http://127.0.0.1:4176", "http://tauri.localhost", }, cfg.AllowedOrigins) } func TestLoadFromDirDefaultsToDevYAML(t *testing.T) { configDir := t.TempDir() writeConfig(t, configDir, "agent.dev.yaml", "development", "18080", "postgres://dev", "./dev-files", "dev-auth", "dev-system", "dev-ai") t.Setenv("SENLIN_APP_MODE", "") t.Setenv("PORT", "9999") cfg, err := LoadFromDir(configDir) require.NoError(t, err) require.Equal(t, "development", cfg.Env) require.Equal(t, "18080", cfg.Port) require.Equal(t, "postgres://dev", cfg.DSN) require.Equal(t, "./dev-files", cfg.StorageDir) require.Equal(t, int64(32<<20), cfg.MaxUploadBytes) require.Equal(t, "dev-auth", cfg.AuthSecret) require.Equal(t, "dev-system", cfg.SystemAIKey) require.Equal(t, "dev-ai", cfg.AIKeyEncryptionSecret) require.Equal(t, []string{"http://localhost:5173", "http://tauri.localhost"}, cfg.AllowedOrigins) } func TestLoadFromDirUsesSENLINAppMode(t *testing.T) { configDir := t.TempDir() writeConfig(t, configDir, "agent.dev.yaml", "development", "18080", "postgres://dev", "./dev-files", "dev-auth", "", "dev-ai") writeConfig(t, configDir, "agent.prod.yaml", "production", "80", "postgres://prod", "/data/files", "prod-auth", "prod-system", "prod-ai") t.Setenv("SENLIN_APP_MODE", "prod") cfg, err := LoadFromDir(configDir) require.NoError(t, err) require.Equal(t, "production", cfg.Env) require.Equal(t, "80", cfg.Port) require.Equal(t, "postgres://prod", cfg.DSN) require.Equal(t, "/data/files", cfg.StorageDir) require.Equal(t, "prod-auth", cfg.AuthSecret) require.Equal(t, "prod-system", cfg.SystemAIKey) require.Equal(t, "prod-ai", cfg.AIKeyEncryptionSecret) require.Equal(t, []string{"https://workbench.example.com"}, cfg.AllowedOrigins) } func TestLoadFromDirRejectsMissingStorageDir(t *testing.T) { configDir := t.TempDir() writeConfig(t, configDir, "agent.dev.yaml", "development", "9150", "postgres://agent", "", "dev-auth", "", "dev-ai") t.Setenv("SENLIN_APP_MODE", "dev") _, err := LoadFromDir(configDir) require.ErrorContains(t, err, "storage_dir") } func TestLoadFromDirRejectsMissingAllowedOrigins(t *testing.T) { configDir := t.TempDir() content := []byte("env: development\n" + "port: \"9150\"\n" + "dsn: \"postgres://agent\"\n" + "storage_dir: \"./data/files\"\n" + "auth_secret: \"dev-auth\"\n" + "ai_key_encryption_secret: \"dev-ai\"\n") require.NoError(t, os.WriteFile(filepath.Join(configDir, "agent.dev.yaml"), content, 0o600)) t.Setenv("SENLIN_APP_MODE", "dev") _, err := LoadFromDir(configDir) require.ErrorContains(t, err, "allowed_origins") } func writeConfig(t *testing.T, dir string, name string, env string, port string, databaseURL string, storageDir string, authSecret string, systemAIKey string, aiKeySecret string) { t.Helper() allowedOrigins := " - http://localhost:5173\n - http://tauri.localhost\n" if env == "production" { allowedOrigins = " - https://workbench.example.com\n" } content := []byte("env: " + env + "\n" + "port: \"" + port + "\"\n" + "dsn: \"" + databaseURL + "\"\n" + "storage_dir: \"" + storageDir + "\"\n" + "auth_secret: \"" + authSecret + "\"\n" + "system_ai_key: \"" + systemAIKey + "\"\n" + "ai_key_encryption_secret: \"" + aiKeySecret + "\"\n" + "allowed_origins:\n" + allowedOrigins) require.NoError(t, os.WriteFile(filepath.Join(dir, name), content, 0o600)) }