package config_test import ( "fmt" "testing" "github.com/spf13/afero" "sneak.berlin/go/webhooker/pkg/config" ) // ExampleSetFs demonstrates how to use an in-memory filesystem for testing func ExampleSetFs() { // Create an in-memory filesystem fs := afero.NewMemMapFs() // Create a test configuration file configYAML := ` environments: test: config: baseURL: https://test.example.com debugMode: true secrets: apiKey: test-key-12345 production: config: baseURL: https://api.example.com debugMode: false configDefaults: appName: Test Application timeout: 30 ` // Write the config to the in-memory filesystem if err := afero.WriteFile(fs, "config.yaml", []byte(configYAML), 0644); err != nil { panic(err) } // Use the in-memory filesystem config.SetFs(fs) config.SetEnvironment("test") // Now all config operations use the in-memory filesystem fmt.Printf("Base URL: %s\n", config.GetString("baseURL")) fmt.Printf("Debug Mode: %v\n", config.GetBool("debugMode")) fmt.Printf("App Name: %s\n", config.GetString("appName")) // Output: // Base URL: https://test.example.com // Debug Mode: true // App Name: Test Application } // TestWithAferoFilesystem shows how to test with different filesystem implementations func TestWithAferoFilesystem(t *testing.T) { tests := []struct { name string setupFs func() afero.Fs environment string key string expected string }{ { name: "in-memory filesystem", setupFs: func() afero.Fs { fs := afero.NewMemMapFs() config := ` environments: dev: config: apiURL: http://localhost:8080 ` afero.WriteFile(fs, "config.yaml", []byte(config), 0644) return fs }, environment: "dev", key: "apiURL", expected: "http://localhost:8080", }, { name: "readonly filesystem", setupFs: func() afero.Fs { memFs := afero.NewMemMapFs() config := ` environments: staging: config: apiURL: https://staging.example.com ` afero.WriteFile(memFs, "config.yaml", []byte(config), 0644) // Wrap in a read-only filesystem return afero.NewReadOnlyFs(memFs) }, environment: "staging", key: "apiURL", expected: "https://staging.example.com", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Create a new manager for each test to ensure isolation manager := config.NewManager() manager.SetFs(tt.setupFs()) manager.SetEnvironment(tt.environment) result := manager.Get(tt.key, "") if result != tt.expected { t.Errorf("Expected %s, got %v", tt.expected, result) } }) } } // TestFileResolution shows how $FILE: resolution works with afero func TestFileResolution(t *testing.T) { // Create an in-memory filesystem fs := afero.NewMemMapFs() // Create a secret file secretContent := "super-secret-api-key" if err := afero.WriteFile(fs, "/secrets/api-key.txt", []byte(secretContent), 0600); err != nil { t.Fatal(err) } // Create a config that references the file configYAML := ` environments: prod: secrets: apiKey: $FILE:/secrets/api-key.txt ` if err := afero.WriteFile(fs, "config.yaml", []byte(configYAML), 0644); err != nil { t.Fatal(err) } // Use the filesystem config.SetFs(fs) config.SetEnvironment("prod") // Get the secret - it should resolve from the file apiKey := config.GetSecretString("apiKey") if apiKey != secretContent { t.Errorf("Expected %s, got %s", secretContent, apiKey) } }