406 lines
9.7 KiB
Go
406 lines
9.7 KiB
Go
package ezconf
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestPrintEnvVars(t *testing.T) {
|
|
loader := New()
|
|
loader.envVars = []EnvVar{
|
|
{
|
|
Name: "LOG_LEVEL",
|
|
Description: "Log level",
|
|
Required: false,
|
|
Default: "info",
|
|
CurrentValue: "debug",
|
|
},
|
|
{
|
|
Name: "DATABASE_URL",
|
|
Description: "Database connection",
|
|
Required: true,
|
|
Default: "",
|
|
CurrentValue: "postgres://localhost/db",
|
|
},
|
|
}
|
|
|
|
// Test without values
|
|
t.Run("without values", func(t *testing.T) {
|
|
buf := &bytes.Buffer{}
|
|
err := loader.PrintEnvVars(buf, false)
|
|
if err != nil {
|
|
t.Fatalf("PrintEnvVars failed: %v", err)
|
|
}
|
|
|
|
output := buf.String()
|
|
if !strings.Contains(output, "LOG_LEVEL") {
|
|
t.Error("output should contain LOG_LEVEL")
|
|
}
|
|
if !strings.Contains(output, "Log level") {
|
|
t.Error("output should contain description")
|
|
}
|
|
if !strings.Contains(output, "(default: info)") {
|
|
t.Error("output should contain default value")
|
|
}
|
|
if strings.Contains(output, "debug") {
|
|
t.Error("output should not contain current value when showValues is false")
|
|
}
|
|
})
|
|
|
|
// Test with values
|
|
t.Run("with values", func(t *testing.T) {
|
|
buf := &bytes.Buffer{}
|
|
err := loader.PrintEnvVars(buf, true)
|
|
if err != nil {
|
|
t.Fatalf("PrintEnvVars failed: %v", err)
|
|
}
|
|
|
|
output := buf.String()
|
|
if !strings.Contains(output, "LOG_LEVEL=debug") {
|
|
t.Error("output should contain LOG_LEVEL=debug")
|
|
}
|
|
if !strings.Contains(output, "DATABASE_URL=postgres://localhost/db") {
|
|
t.Error("output should contain DATABASE_URL value")
|
|
}
|
|
if !strings.Contains(output, "(required)") {
|
|
t.Error("output should indicate required variables")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestGenerateEnvFile(t *testing.T) {
|
|
loader := New()
|
|
loader.envVars = []EnvVar{
|
|
{
|
|
Name: "LOG_LEVEL",
|
|
Description: "Log level",
|
|
Required: false,
|
|
Default: "info",
|
|
CurrentValue: "debug",
|
|
},
|
|
{
|
|
Name: "DATABASE_URL",
|
|
Description: "Database connection",
|
|
Required: true,
|
|
Default: "postgres://localhost/db",
|
|
CurrentValue: "",
|
|
},
|
|
}
|
|
|
|
tempDir := t.TempDir()
|
|
|
|
t.Run("generate with defaults", func(t *testing.T) {
|
|
envFile := filepath.Join(tempDir, "test1.env")
|
|
|
|
err := loader.GenerateEnvFile(envFile, false)
|
|
if err != nil {
|
|
t.Fatalf("GenerateEnvFile failed: %v", err)
|
|
}
|
|
|
|
content, err := os.ReadFile(envFile)
|
|
if err != nil {
|
|
t.Fatalf("failed to read generated file: %v", err)
|
|
}
|
|
|
|
output := string(content)
|
|
if !strings.Contains(output, "LOG_LEVEL=info") {
|
|
t.Error("expected default value for LOG_LEVEL")
|
|
}
|
|
if !strings.Contains(output, "# Log level") {
|
|
t.Error("expected description comment")
|
|
}
|
|
if !strings.Contains(output, "# Database connection") {
|
|
t.Error("expected DATABASE_URL description")
|
|
}
|
|
})
|
|
|
|
t.Run("generate with current values", func(t *testing.T) {
|
|
envFile := filepath.Join(tempDir, "test2.env")
|
|
|
|
err := loader.GenerateEnvFile(envFile, true)
|
|
if err != nil {
|
|
t.Fatalf("GenerateEnvFile failed: %v", err)
|
|
}
|
|
|
|
content, err := os.ReadFile(envFile)
|
|
if err != nil {
|
|
t.Fatalf("failed to read generated file: %v", err)
|
|
}
|
|
|
|
output := string(content)
|
|
if !strings.Contains(output, "LOG_LEVEL=debug") {
|
|
t.Error("expected current value for LOG_LEVEL")
|
|
}
|
|
// DATABASE_URL has no current value, should use default
|
|
if !strings.Contains(output, "DATABASE_URL=postgres://localhost/db") {
|
|
t.Error("expected default value for DATABASE_URL when current is empty")
|
|
}
|
|
})
|
|
|
|
t.Run("preserve untracked variables", func(t *testing.T) {
|
|
envFile := filepath.Join(tempDir, "test3.env")
|
|
|
|
// Create existing file with untracked variable
|
|
existing := `# Existing file
|
|
LOG_LEVEL=warn
|
|
CUSTOM_VAR=custom_value
|
|
ANOTHER_VAR=another_value
|
|
`
|
|
if err := os.WriteFile(envFile, []byte(existing), 0644); err != nil {
|
|
t.Fatalf("failed to create existing file: %v", err)
|
|
}
|
|
|
|
// Generate new file - should preserve untracked variables
|
|
err := loader.GenerateEnvFile(envFile, false)
|
|
if err != nil {
|
|
t.Fatalf("GenerateEnvFile failed: %v", err)
|
|
}
|
|
|
|
content, err := os.ReadFile(envFile)
|
|
if err != nil {
|
|
t.Fatalf("failed to read generated file: %v", err)
|
|
}
|
|
|
|
output := string(content)
|
|
// Should have tracked variables with new format
|
|
if !strings.Contains(output, "LOG_LEVEL") {
|
|
t.Error("expected LOG_LEVEL to be present")
|
|
}
|
|
if !strings.Contains(output, "DATABASE_URL") {
|
|
t.Error("expected DATABASE_URL to be present")
|
|
}
|
|
// Should preserve untracked variables
|
|
if !strings.Contains(output, "CUSTOM_VAR=custom_value") {
|
|
t.Error("expected to preserve CUSTOM_VAR")
|
|
}
|
|
if !strings.Contains(output, "ANOTHER_VAR=another_value") {
|
|
t.Error("expected to preserve ANOTHER_VAR")
|
|
}
|
|
// Should have untracked section header
|
|
if !strings.Contains(output, "Untracked Variables") {
|
|
t.Error("expected untracked variables section header")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestUpdateEnvFile(t *testing.T) {
|
|
loader := New()
|
|
loader.envVars = []EnvVar{
|
|
{
|
|
Name: "LOG_LEVEL",
|
|
Description: "Log level",
|
|
Default: "info",
|
|
},
|
|
{
|
|
Name: "NEW_VAR",
|
|
Description: "New variable",
|
|
Default: "new_default",
|
|
},
|
|
}
|
|
|
|
tempDir := t.TempDir()
|
|
|
|
t.Run("update existing file", func(t *testing.T) {
|
|
envFile := filepath.Join(tempDir, "existing.env")
|
|
|
|
// Create existing file
|
|
existing := `# Existing file
|
|
LOG_LEVEL=debug
|
|
OLD_VAR=old_value
|
|
`
|
|
if err := os.WriteFile(envFile, []byte(existing), 0644); err != nil {
|
|
t.Fatalf("failed to create existing file: %v", err)
|
|
}
|
|
|
|
err := loader.UpdateEnvFile(envFile, false)
|
|
if err != nil {
|
|
t.Fatalf("UpdateEnvFile failed: %v", err)
|
|
}
|
|
|
|
content, err := os.ReadFile(envFile)
|
|
if err != nil {
|
|
t.Fatalf("failed to read updated file: %v", err)
|
|
}
|
|
|
|
output := string(content)
|
|
// Should preserve existing value
|
|
if !strings.Contains(output, "LOG_LEVEL=debug") {
|
|
t.Error("expected to preserve existing LOG_LEVEL value")
|
|
}
|
|
// Should keep old variable
|
|
if !strings.Contains(output, "OLD_VAR=old_value") {
|
|
t.Error("expected to preserve OLD_VAR")
|
|
}
|
|
// Should add new variable
|
|
if !strings.Contains(output, "NEW_VAR=new_default") {
|
|
t.Error("expected to add NEW_VAR")
|
|
}
|
|
})
|
|
|
|
t.Run("create if not exist", func(t *testing.T) {
|
|
envFile := filepath.Join(tempDir, "new.env")
|
|
|
|
err := loader.UpdateEnvFile(envFile, true)
|
|
if err != nil {
|
|
t.Fatalf("UpdateEnvFile failed: %v", err)
|
|
}
|
|
|
|
if _, err := os.Stat(envFile); os.IsNotExist(err) {
|
|
t.Error("expected file to be created")
|
|
}
|
|
})
|
|
|
|
t.Run("error if not exist and no create", func(t *testing.T) {
|
|
envFile := filepath.Join(tempDir, "nonexistent.env")
|
|
|
|
err := loader.UpdateEnvFile(envFile, false)
|
|
if err == nil {
|
|
t.Error("expected error for nonexistent file")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestParseEnvFile(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
envFile := filepath.Join(tempDir, "test.env")
|
|
|
|
content := `# Comment line
|
|
VAR1=value1
|
|
VAR2=value2
|
|
|
|
# Another comment
|
|
VAR3=value3
|
|
EMPTY_VAR=
|
|
`
|
|
|
|
if err := os.WriteFile(envFile, []byte(content), 0644); err != nil {
|
|
t.Fatalf("failed to create test file: %v", err)
|
|
}
|
|
|
|
lines, err := parseEnvFile(envFile)
|
|
if err != nil {
|
|
t.Fatalf("parseEnvFile failed: %v", err)
|
|
}
|
|
|
|
varCount := 0
|
|
for _, line := range lines {
|
|
if line.IsVar {
|
|
varCount++
|
|
}
|
|
}
|
|
|
|
if varCount != 4 {
|
|
t.Errorf("expected 4 variables, got %d", varCount)
|
|
}
|
|
|
|
// Check specific variables
|
|
found := false
|
|
for _, line := range lines {
|
|
if line.IsVar && line.Key == "VAR1" && line.Value == "value1" {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Error("expected to find VAR1=value1")
|
|
}
|
|
}
|
|
|
|
func TestParseEnvFile_InvalidFile(t *testing.T) {
|
|
_, err := parseEnvFile("/nonexistent/file.env")
|
|
if err == nil {
|
|
t.Error("expected error for nonexistent file")
|
|
}
|
|
}
|
|
|
|
func TestPrintEnvVars_NoEnvVars(t *testing.T) {
|
|
loader := New()
|
|
|
|
buf := &bytes.Buffer{}
|
|
err := loader.PrintEnvVars(buf, false)
|
|
if err == nil {
|
|
t.Error("expected error when no env vars are loaded")
|
|
}
|
|
if !strings.Contains(err.Error(), "did you call Load()") {
|
|
t.Errorf("expected helpful error message, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestPrintEnvVarsStdout(t *testing.T) {
|
|
loader := New()
|
|
loader.envVars = []EnvVar{
|
|
{
|
|
Name: "TEST_VAR",
|
|
Description: "Test variable",
|
|
Default: "test",
|
|
},
|
|
}
|
|
|
|
// This test just ensures it doesn't panic
|
|
// We can't easily capture stdout in a unit test without redirecting it
|
|
err := loader.PrintEnvVarsStdout(false)
|
|
if err != nil {
|
|
t.Errorf("PrintEnvVarsStdout(false) failed: %v", err)
|
|
}
|
|
|
|
err = loader.PrintEnvVarsStdout(true)
|
|
if err != nil {
|
|
t.Errorf("PrintEnvVarsStdout(true) failed: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestPrintEnvVarsStdout_NoEnvVars(t *testing.T) {
|
|
loader := New()
|
|
|
|
err := loader.PrintEnvVarsStdout(false)
|
|
if err == nil {
|
|
t.Error("expected error when no env vars are loaded")
|
|
}
|
|
}
|
|
|
|
func TestPrintEnvVars_AfterParseEnvVars(t *testing.T) {
|
|
loader := New()
|
|
|
|
// Add some env vars manually to simulate ParseEnvVars
|
|
loader.envVars = []EnvVar{
|
|
{
|
|
Name: "LOG_LEVEL",
|
|
Description: "Log level for the application",
|
|
Required: false,
|
|
Default: "info",
|
|
CurrentValue: "",
|
|
},
|
|
{
|
|
Name: "DATABASE_URL",
|
|
Description: "Database connection string",
|
|
Required: true,
|
|
Default: "",
|
|
CurrentValue: "",
|
|
},
|
|
}
|
|
|
|
// Test that PrintEnvVars works after ParseEnvVars (without Load)
|
|
buf := &bytes.Buffer{}
|
|
err := loader.PrintEnvVars(buf, false)
|
|
if err != nil {
|
|
t.Fatalf("PrintEnvVars failed: %v", err)
|
|
}
|
|
|
|
output := buf.String()
|
|
if !strings.Contains(output, "LOG_LEVEL") {
|
|
t.Error("output should contain LOG_LEVEL")
|
|
}
|
|
if !strings.Contains(output, "DATABASE_URL") {
|
|
t.Error("output should contain DATABASE_URL")
|
|
}
|
|
if !strings.Contains(output, "(required)") {
|
|
t.Error("output should indicate required variables")
|
|
}
|
|
if !strings.Contains(output, "(default: info)") {
|
|
t.Error("output should contain default value")
|
|
}
|
|
}
|