391 lines
9.1 KiB
Go
391 lines
9.1 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"flag"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gorm.io/gorm"
|
|
"goyco/cmd/goyco/commands"
|
|
"goyco/internal/config"
|
|
"goyco/internal/testutils"
|
|
)
|
|
|
|
func TestLoadDotEnv(t *testing.T) {
|
|
t.Run("no .env file", func(t *testing.T) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
t.Errorf("loadDotEnv panicked: %v", r)
|
|
}
|
|
}()
|
|
loadDotEnv()
|
|
})
|
|
}
|
|
|
|
func TestNewFlagSet(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
flagName string
|
|
usage func()
|
|
}{
|
|
{
|
|
name: "with usage function",
|
|
flagName: "test",
|
|
usage: func() { _, _ = os.Stderr.WriteString("test usage") },
|
|
},
|
|
{
|
|
name: "without usage function",
|
|
flagName: "test2",
|
|
usage: nil,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
fs := newFlagSet(tt.flagName, tt.usage)
|
|
|
|
if fs.Name() != tt.flagName {
|
|
t.Errorf("expected flag set name %q, got %q", tt.flagName, fs.Name())
|
|
}
|
|
|
|
if tt.usage != nil && fs.Usage == nil {
|
|
t.Error("expected usage function to be set")
|
|
}
|
|
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseCommand(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
context string
|
|
expectError bool
|
|
expectHelp bool
|
|
}{
|
|
{
|
|
name: "valid arguments",
|
|
args: []string{"--help"},
|
|
context: "test",
|
|
expectError: true,
|
|
expectHelp: true,
|
|
},
|
|
{
|
|
name: "invalid flag",
|
|
args: []string{"--invalid-flag"},
|
|
context: "test",
|
|
expectError: true,
|
|
expectHelp: false,
|
|
},
|
|
{
|
|
name: "empty arguments",
|
|
args: []string{},
|
|
context: "test",
|
|
expectError: false,
|
|
expectHelp: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
fs := flag.NewFlagSet("test", flag.ContinueOnError)
|
|
fs.SetOutput(os.Stderr)
|
|
|
|
err := parseCommand(fs, tt.args, tt.context)
|
|
|
|
if tt.expectError && err == nil {
|
|
t.Error("expected error but got none")
|
|
}
|
|
|
|
if !tt.expectError && err != nil {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
|
|
if tt.expectHelp && !errors.Is(err, commands.ErrHelpRequested) {
|
|
t.Error("expected help requested error")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPrintRootUsage(t *testing.T) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
t.Errorf("printRootUsage panicked: %v", r)
|
|
}
|
|
}()
|
|
|
|
printRootUsage()
|
|
}
|
|
|
|
func TestPrintRunUsage(t *testing.T) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
t.Errorf("printRunUsage panicked: %v", r)
|
|
}
|
|
}()
|
|
|
|
printRunUsage()
|
|
}
|
|
|
|
func TestDispatchCommand(t *testing.T) {
|
|
|
|
t.Run("unknown command", func(t *testing.T) {
|
|
cfg := testutils.NewTestConfig()
|
|
err := dispatchCommand(cfg, "unknown", []string{})
|
|
|
|
if err == nil {
|
|
t.Error("expected error for unknown command")
|
|
}
|
|
|
|
expectedErr := "unknown command: unknown"
|
|
if err.Error() != expectedErr {
|
|
t.Errorf("expected error %q, got %q", expectedErr, err.Error())
|
|
}
|
|
})
|
|
|
|
t.Run("help command", func(t *testing.T) {
|
|
cfg := testutils.NewTestConfig()
|
|
err := dispatchCommand(cfg, "help", []string{})
|
|
|
|
if err != nil {
|
|
t.Errorf("unexpected error for help command: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("h command", func(t *testing.T) {
|
|
cfg := testutils.NewTestConfig()
|
|
err := dispatchCommand(cfg, "-h", []string{})
|
|
|
|
if err != nil {
|
|
t.Errorf("unexpected error for -h command: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("--help command", func(t *testing.T) {
|
|
cfg := testutils.NewTestConfig()
|
|
err := dispatchCommand(cfg, "--help", []string{})
|
|
|
|
if err != nil {
|
|
t.Errorf("unexpected error for --help command: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("post list with injected database", func(t *testing.T) {
|
|
cfg := testutils.NewTestConfig()
|
|
|
|
useInMemoryCommandsConnector(t)
|
|
|
|
err := dispatchCommand(cfg, "post", []string{"list"})
|
|
|
|
if err != nil {
|
|
t.Errorf("unexpected error for post list: %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestHandleRunCommand(t *testing.T) {
|
|
|
|
t.Run("help requested", func(t *testing.T) {
|
|
cfg := testutils.NewTestConfig()
|
|
err := handleRunCommand(cfg, []string{"--help"})
|
|
|
|
if err != nil {
|
|
t.Errorf("unexpected error for help: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("unexpected arguments", func(t *testing.T) {
|
|
cfg := testutils.NewTestConfig()
|
|
err := handleRunCommand(cfg, []string{"extra", "args"})
|
|
|
|
if err == nil {
|
|
t.Error("expected error for unexpected arguments")
|
|
}
|
|
|
|
expectedErr := "unexpected arguments for run command"
|
|
if err.Error() != expectedErr {
|
|
t.Errorf("expected error %q, got %q", expectedErr, err.Error())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestRun(t *testing.T) {
|
|
|
|
t.Run("no arguments", func(t *testing.T) {
|
|
err := run([]string{})
|
|
|
|
if err != nil {
|
|
t.Logf("Expected error in test environment: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("help flag", func(t *testing.T) {
|
|
err := run([]string{"--help"})
|
|
|
|
if err == nil {
|
|
t.Error("expected config loading error in test environment")
|
|
}
|
|
})
|
|
|
|
t.Run("invalid flag", func(t *testing.T) {
|
|
err := run([]string{"--invalid-flag"})
|
|
|
|
if err == nil {
|
|
t.Error("expected error for invalid flag")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestRunE2E_CommandParsing(t *testing.T) {
|
|
setupTestEnv(t)
|
|
|
|
t.Run("help command succeeds", func(t *testing.T) {
|
|
err := run([]string{"help"})
|
|
if err != nil {
|
|
t.Errorf("Expected help command to succeed, got error: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("unknown command fails with error", func(t *testing.T) {
|
|
err := run([]string{"unknown-command"})
|
|
if err == nil {
|
|
t.Error("Expected error for unknown command")
|
|
}
|
|
if err != nil && !strings.Contains(err.Error(), "unknown command") {
|
|
t.Errorf("Expected error about unknown command, got: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("migrate command parses correctly", func(t *testing.T) {
|
|
err := run([]string{"migrate", "up"})
|
|
if err != nil && strings.Contains(err.Error(), "unknown command") {
|
|
t.Errorf("Expected migrate command to be recognized, got parsing error: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("post command parses correctly", func(t *testing.T) {
|
|
useInMemoryCommandsConnector(t)
|
|
err := run([]string{"post", "list"})
|
|
if err != nil && strings.Contains(err.Error(), "unknown command") {
|
|
t.Errorf("Expected post command to be recognized, got parsing error: %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestRunE2E_ConfigurationLoading(t *testing.T) {
|
|
t.Run("missing required env vars fails gracefully", func(t *testing.T) {
|
|
originalDBPwd := os.Getenv("DB_PASSWORD")
|
|
originalSMTPHost := os.Getenv("SMTP_HOST")
|
|
originalSMTPFrom := os.Getenv("SMTP_FROM")
|
|
originalAdminEmail := os.Getenv("ADMIN_EMAIL")
|
|
originalJWTSecret := os.Getenv("JWT_SECRET")
|
|
|
|
defer func() {
|
|
if originalDBPwd != "" {
|
|
_ = os.Setenv("DB_PASSWORD", originalDBPwd)
|
|
}
|
|
if originalSMTPHost != "" {
|
|
_ = os.Setenv("SMTP_HOST", originalSMTPHost)
|
|
}
|
|
if originalSMTPFrom != "" {
|
|
_ = os.Setenv("SMTP_FROM", originalSMTPFrom)
|
|
}
|
|
if originalAdminEmail != "" {
|
|
_ = os.Setenv("ADMIN_EMAIL", originalAdminEmail)
|
|
}
|
|
if originalJWTSecret != "" {
|
|
_ = os.Setenv("JWT_SECRET", originalJWTSecret)
|
|
}
|
|
}()
|
|
|
|
_ = os.Unsetenv("DB_PASSWORD")
|
|
_ = os.Unsetenv("SMTP_HOST")
|
|
_ = os.Unsetenv("SMTP_FROM")
|
|
_ = os.Unsetenv("ADMIN_EMAIL")
|
|
_ = os.Unsetenv("JWT_SECRET")
|
|
|
|
err := run([]string{"help"})
|
|
if err == nil {
|
|
t.Error("Expected error when required env vars are missing")
|
|
}
|
|
if err != nil && !strings.Contains(err.Error(), "configuration") && !strings.Contains(err.Error(), "config") {
|
|
t.Logf("Got error (may be expected): %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("valid configuration loads successfully", func(t *testing.T) {
|
|
setupTestEnv(t)
|
|
err := run([]string{"help"})
|
|
if err != nil {
|
|
t.Errorf("Expected help command to succeed with valid config, got: %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestRunE2E_ArgumentParsing(t *testing.T) {
|
|
setupTestEnv(t)
|
|
|
|
t.Run("root help flag", func(t *testing.T) {
|
|
err := run([]string{"--help"})
|
|
if err != nil && !strings.Contains(err.Error(), "flag") {
|
|
t.Logf("Got error (may be expected in test env): %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("command with help flag", func(t *testing.T) {
|
|
err := run([]string{"migrate", "--help"})
|
|
if err != nil && strings.Contains(err.Error(), "unknown command") {
|
|
t.Errorf("Expected migrate command to be recognized, got: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("command with invalid arguments", func(t *testing.T) {
|
|
err := run([]string{"run", "extra", "args"})
|
|
if err == nil {
|
|
t.Error("Expected error for unexpected arguments")
|
|
}
|
|
if err != nil && !strings.Contains(err.Error(), "unexpected arguments") {
|
|
t.Errorf("Expected error about unexpected arguments, got: %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func setupTestEnv(t *testing.T) {
|
|
t.Helper()
|
|
t.Setenv("DB_PASSWORD", "test-password")
|
|
t.Setenv("SMTP_HOST", "smtp.example.com")
|
|
t.Setenv("SMTP_FROM", "test@example.com")
|
|
t.Setenv("ADMIN_EMAIL", "admin@example.com")
|
|
t.Setenv("JWT_SECRET", "test-jwt-secret-key-that-is-long-enough-for-validation-purposes")
|
|
tmpDir := os.TempDir()
|
|
t.Setenv("LOG_DIR", tmpDir)
|
|
t.Setenv("PID_DIR", tmpDir)
|
|
}
|
|
|
|
func useInMemoryCommandsConnector(t *testing.T) {
|
|
t.Helper()
|
|
|
|
commands.SetDBConnector(func(_ *config.Config) (*gorm.DB, func() error, error) {
|
|
db := testutils.NewTestDB(t)
|
|
|
|
sqlDB, err := db.DB()
|
|
if err != nil {
|
|
t.Fatalf("failed to access underlying sql.DB: %v", err)
|
|
}
|
|
|
|
cleanup := func() error {
|
|
return sqlDB.Close()
|
|
}
|
|
|
|
return db, cleanup, nil
|
|
})
|
|
|
|
t.Cleanup(func() {
|
|
commands.SetDBConnector(nil)
|
|
})
|
|
}
|