Files
beads/cmd/bd/orphans_test.go
matt wilkie 99f5e50a32 feat: Add 'bd orphans' command with DRY refactoring of orphan detection
Implements the 'bd orphans' command to identify issues referenced in commits
but still open in the database, and refactors to eliminate code duplication.

- Creates cmd/bd/orphans.go with Cobra command structure
- Identifies orphaned issues (referenced in git commits but still open/in_progress)
- Supports multiple output formats (human, JSON, detailed)
- Auto-close with --fix flag

DRY refactoring:
- Extracted FindOrphanedIssues() to cmd/bd/doctor/git.go as shared core logic
- Moved OrphanIssue type to cmd/bd/doctor/types.go
- Refactored CheckOrphanedIssues() to use FindOrphanedIssues()

Cherry-picked from PR #767

Co-authored-by: Amp <amp@ampcode.com>
2025-12-27 17:23:45 -08:00

83 lines
2.3 KiB
Go

package main
import (
"context"
"os"
"os/exec"
"path/filepath"
"testing"
)
// TestOrphansBasic tests basic orphan detection
func TestOrphansBasic(t *testing.T) {
// Create a temporary directory with a git repo and beads database
tmpDir := t.TempDir()
// Initialize git repo
cmd := exec.Command("git", "init")
cmd.Dir = tmpDir
if err := cmd.Run(); err != nil {
t.Fatalf("Failed to init git repo: %v", err)
}
// Configure git user (needed for commits)
ctx := context.Background()
for _, cmd := range []*exec.Cmd{
exec.CommandContext(ctx, "git", "-C", tmpDir, "config", "user.email", "test@example.com"),
exec.CommandContext(ctx, "git", "-C", tmpDir, "config", "user.name", "Test User"),
} {
if err := cmd.Run(); err != nil {
t.Fatalf("Failed to configure git: %v", err)
}
}
// Create .beads directory
beadsDir := filepath.Join(tmpDir, ".beads")
if err := os.MkdirAll(beadsDir, 0755); err != nil {
t.Fatalf("Failed to create .beads dir: %v", err)
}
// Create a minimal database with beads.db
// For this test, we'll skip creating an actual database
// since the test is primarily about integration
// Test: findOrphanedIssues should handle missing database gracefully
orphans, err := findOrphanedIssues(tmpDir)
if err != nil {
t.Fatalf("findOrphanedIssues failed: %v", err)
}
// Should be empty list since no database
if len(orphans) != 0 {
t.Errorf("Expected empty orphans list, got %d", len(orphans))
}
}
// TestOrphansNotGitRepo tests behavior in non-git directories
func TestOrphansNotGitRepo(t *testing.T) {
tmpDir := t.TempDir()
// Should not error, just return empty list
orphans, err := findOrphanedIssues(tmpDir)
if err != nil {
t.Fatalf("findOrphanedIssues failed: %v", err)
}
if len(orphans) != 0 {
t.Errorf("Expected empty orphans list for non-git repo, got %d", len(orphans))
}
}
// TestCloseIssueCommand tests that close issue command is properly formed
func TestCloseIssueCommand(t *testing.T) {
// This is a basic test to ensure the closeIssue function
// attempts to run the correct command.
// In a real environment, this would fail since bd close requires
// a valid beads database.
// Just test that the function doesn't panic
// (actual close will fail, which is expected)
_ = closeIssue("bd-test-invalid")
// Error is expected since the issue doesn't exist
}