package worker import ( "context" "testing" "time" "github.com/orchard9/rdev/internal/domain" ) func TestSDLCTaskExecutor_ParseSpec(t *testing.T) { exec := NewSDLCTaskExecutor(SDLCTaskExecutorConfig{ Namespace: "rdev", }) t.Run("valid spec", func(t *testing.T) { spec, err := exec.parseSpec(map[string]any{ "command": "feature-create", "args": []any{"auth-flow", "--title", "Authentication Flow"}, "git_clone_url": "https://git.example.com/owner/repo.git", "auto_commit": true, "auto_push": true, }) if err != nil { t.Fatalf("parseSpec() error = %v", err) } if spec.Command != "feature-create" { t.Errorf("got command %q, want %q", spec.Command, "feature-create") } if len(spec.Args) != 3 { t.Errorf("got %d args, want 3", len(spec.Args)) } if spec.GitCloneURL != "https://git.example.com/owner/repo.git" { t.Errorf("got git_clone_url %q", spec.GitCloneURL) } if !spec.AutoCommit { t.Error("expected auto_commit = true") } if !spec.AutoPush { t.Error("expected auto_push = true") } }) t.Run("missing command", func(t *testing.T) { _, err := exec.parseSpec(map[string]any{ "git_clone_url": "https://git.example.com/owner/repo.git", }) if err == nil { t.Error("expected error for missing command") } }) t.Run("missing git_clone_url", func(t *testing.T) { _, err := exec.parseSpec(map[string]any{ "command": "feature-create", }) if err == nil { t.Error("expected error for missing git_clone_url") } }) t.Run("args as string slice", func(t *testing.T) { spec, err := exec.parseSpec(map[string]any{ "command": "feature-create", "args": []string{"arg1", "arg2"}, "git_clone_url": "https://git.example.com/owner/repo.git", }) if err != nil { t.Fatalf("parseSpec() error = %v", err) } if len(spec.Args) != 2 { t.Errorf("got %d args, want 2", len(spec.Args)) } }) t.Run("empty args", func(t *testing.T) { spec, err := exec.parseSpec(map[string]any{ "command": "state", "git_clone_url": "https://git.example.com/owner/repo.git", }) if err != nil { t.Fatalf("parseSpec() error = %v", err) } if len(spec.Args) != 0 { t.Errorf("got %d args, want 0", len(spec.Args)) } }) } func TestSDLCTaskExecutor_Execute_NoPodGitOps(t *testing.T) { exec := NewSDLCTaskExecutor(SDLCTaskExecutorConfig{ Namespace: "rdev", PodGitOps: nil, // No git operations configured }) task := &domain.WorkTask{ ID: "task-1", ProjectID: "project-1", Type: domain.WorkTaskTypeSDLC, Spec: map[string]any{ "command": "feature-create", "args": []any{"auth-flow"}, "git_clone_url": "https://git.example.com/owner/repo.git", }, CreatedAt: time.Now(), } result := exec.Execute(context.Background(), task) if result.Success { t.Error("expected failure when pod git operations not configured") } if result.Error == "" { t.Error("expected error message") } } func TestSDLCTaskExecutor_Execute_InvalidSpec(t *testing.T) { exec := NewSDLCTaskExecutor(SDLCTaskExecutorConfig{ Namespace: "rdev", }) task := &domain.WorkTask{ ID: "task-1", ProjectID: "project-1", Type: domain.WorkTaskTypeSDLC, Spec: map[string]any{ // Missing required fields }, CreatedAt: time.Now(), } result := exec.Execute(context.Background(), task) if result.Success { t.Error("expected failure for invalid spec") } if result.Error == "" { t.Error("expected error message for invalid spec") } } func TestSDLCTaskSpec_Valid(t *testing.T) { // Verify the domain type is valid spec := domain.SDLCTaskSpec{ Command: "feature-create", Args: []string{"auth-flow", "--title", "Auth Flow"}, GitCloneURL: "https://git.example.com/owner/repo.git", AutoCommit: true, AutoPush: true, } if spec.Command == "" { t.Error("command should not be empty") } if len(spec.Args) != 3 { t.Errorf("got %d args, want 3", len(spec.Args)) } } func TestShellQuote(t *testing.T) { tests := []struct { name string input string want string }{ {"simple", "auth-flow", "auth-flow"}, {"with space", "Authentication System", "'Authentication System'"}, {"with single quote", "it's working", "'it'\"'\"'s working'"}, {"flag", "--title", "--title"}, {"empty", "", ""}, {"with dollar", "$HOME", "'$HOME'"}, {"with backtick", "`cmd`", "'`cmd`'"}, {"with semicolon", "a;b", "'a;b'"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := shellQuote(tt.input) if got != tt.want { t.Errorf("shellQuote(%q) = %q, want %q", tt.input, got, tt.want) } }) } }