Add tests for setup package (28.4% → 53.8% coverage)
Adds comprehensive tests for: - factory.go: updateBeadsSection, removeBeadsSection, createNewAgentsFile, InstallFactory, RemoveFactory - cursor.go: InstallCursor, RemoveCursor, CheckCursor - aider.go: InstallAider, RemoveAider, CheckAider, templates Coverage improved from 21.6% (measured) to 53.8%, exceeding 50% target. (bd-sh4c) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
309
cmd/bd/setup/cursor_test.go
Normal file
309
cmd/bd/setup/cursor_test.go
Normal file
@@ -0,0 +1,309 @@
|
||||
package setup
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCursorRulesTemplate(t *testing.T) {
|
||||
// Verify template contains required content
|
||||
requiredContent := []string{
|
||||
"bd prime",
|
||||
"bd ready",
|
||||
"bd create",
|
||||
"bd update",
|
||||
"bd close",
|
||||
"bd sync",
|
||||
"BEADS INTEGRATION",
|
||||
}
|
||||
|
||||
for _, req := range requiredContent {
|
||||
if !strings.Contains(cursorRulesTemplate, req) {
|
||||
t.Errorf("cursorRulesTemplate missing required content: %q", req)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstallCursor(t *testing.T) {
|
||||
origDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get working directory: %v", err)
|
||||
}
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
if err := os.Chdir(tmpDir); err != nil {
|
||||
t.Fatalf("failed to change to temp directory: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Chdir(origDir); err != nil {
|
||||
t.Fatalf("failed to restore working directory: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
InstallCursor()
|
||||
|
||||
// Verify file was created
|
||||
rulesPath := ".cursor/rules/beads.mdc"
|
||||
if !FileExists(rulesPath) {
|
||||
t.Fatal("Cursor rules file was not created")
|
||||
}
|
||||
|
||||
// Verify content
|
||||
data, err := os.ReadFile(rulesPath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read rules file: %v", err)
|
||||
}
|
||||
|
||||
if string(data) != cursorRulesTemplate {
|
||||
t.Error("Rules file content doesn't match template")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstallCursor_ExistingDirectory(t *testing.T) {
|
||||
origDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get working directory: %v", err)
|
||||
}
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
if err := os.Chdir(tmpDir); err != nil {
|
||||
t.Fatalf("failed to change to temp directory: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Chdir(origDir); err != nil {
|
||||
t.Fatalf("failed to restore working directory: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Pre-create the directory
|
||||
if err := os.MkdirAll(".cursor/rules", 0755); err != nil {
|
||||
t.Fatalf("failed to create directory: %v", err)
|
||||
}
|
||||
|
||||
// Should not fail
|
||||
InstallCursor()
|
||||
|
||||
// Verify file was created
|
||||
if !FileExists(".cursor/rules/beads.mdc") {
|
||||
t.Fatal("Cursor rules file was not created")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstallCursor_OverwriteExisting(t *testing.T) {
|
||||
origDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get working directory: %v", err)
|
||||
}
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
if err := os.Chdir(tmpDir); err != nil {
|
||||
t.Fatalf("failed to change to temp directory: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Chdir(origDir); err != nil {
|
||||
t.Fatalf("failed to restore working directory: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Create existing file with different content
|
||||
rulesPath := ".cursor/rules/beads.mdc"
|
||||
if err := os.MkdirAll(filepath.Dir(rulesPath), 0755); err != nil {
|
||||
t.Fatalf("failed to create directory: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(rulesPath, []byte("old content"), 0644); err != nil {
|
||||
t.Fatalf("failed to create old file: %v", err)
|
||||
}
|
||||
|
||||
InstallCursor()
|
||||
|
||||
// Verify content was overwritten
|
||||
data, err := os.ReadFile(rulesPath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read rules file: %v", err)
|
||||
}
|
||||
|
||||
if string(data) == "old content" {
|
||||
t.Error("Old content was not overwritten")
|
||||
}
|
||||
if string(data) != cursorRulesTemplate {
|
||||
t.Error("Content doesn't match template")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstallCursorIdempotent(t *testing.T) {
|
||||
origDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get working directory: %v", err)
|
||||
}
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
if err := os.Chdir(tmpDir); err != nil {
|
||||
t.Fatalf("failed to change to temp directory: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Chdir(origDir); err != nil {
|
||||
t.Fatalf("failed to restore working directory: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Run twice
|
||||
InstallCursor()
|
||||
firstData, _ := os.ReadFile(".cursor/rules/beads.mdc")
|
||||
|
||||
InstallCursor()
|
||||
secondData, _ := os.ReadFile(".cursor/rules/beads.mdc")
|
||||
|
||||
if string(firstData) != string(secondData) {
|
||||
t.Error("InstallCursor should be idempotent")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveCursor(t *testing.T) {
|
||||
origDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get working directory: %v", err)
|
||||
}
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
if err := os.Chdir(tmpDir); err != nil {
|
||||
t.Fatalf("failed to change to temp directory: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Chdir(origDir); err != nil {
|
||||
t.Fatalf("failed to restore working directory: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Install first
|
||||
InstallCursor()
|
||||
|
||||
// Verify file exists
|
||||
rulesPath := ".cursor/rules/beads.mdc"
|
||||
if !FileExists(rulesPath) {
|
||||
t.Fatal("File should exist before removal")
|
||||
}
|
||||
|
||||
// Remove
|
||||
RemoveCursor()
|
||||
|
||||
// Verify file is gone
|
||||
if FileExists(rulesPath) {
|
||||
t.Error("File should have been removed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveCursor_NoFile(t *testing.T) {
|
||||
origDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get working directory: %v", err)
|
||||
}
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
if err := os.Chdir(tmpDir); err != nil {
|
||||
t.Fatalf("failed to change to temp directory: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Chdir(origDir); err != nil {
|
||||
t.Fatalf("failed to restore working directory: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Should not panic when file doesn't exist
|
||||
RemoveCursor()
|
||||
}
|
||||
|
||||
func TestCheckCursor_NotInstalled(t *testing.T) {
|
||||
origDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get working directory: %v", err)
|
||||
}
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
if err := os.Chdir(tmpDir); err != nil {
|
||||
t.Fatalf("failed to change to temp directory: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Chdir(origDir); err != nil {
|
||||
t.Fatalf("failed to restore working directory: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// CheckCursor calls os.Exit(1) when not installed
|
||||
// We can't easily test that, but we document expected behavior
|
||||
}
|
||||
|
||||
func TestCheckCursor_Installed(t *testing.T) {
|
||||
origDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get working directory: %v", err)
|
||||
}
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
if err := os.Chdir(tmpDir); err != nil {
|
||||
t.Fatalf("failed to change to temp directory: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Chdir(origDir); err != nil {
|
||||
t.Fatalf("failed to restore working directory: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Install first
|
||||
InstallCursor()
|
||||
|
||||
// Should not panic or exit
|
||||
CheckCursor()
|
||||
}
|
||||
|
||||
func TestCursorRulesPath(t *testing.T) {
|
||||
// Verify the path is correct for Cursor IDE
|
||||
expectedPath := ".cursor/rules/beads.mdc"
|
||||
|
||||
// These are the paths used in the implementation
|
||||
origDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get working directory: %v", err)
|
||||
}
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
if err := os.Chdir(tmpDir); err != nil {
|
||||
t.Fatalf("failed to change to temp directory: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Chdir(origDir); err != nil {
|
||||
t.Fatalf("failed to restore working directory: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
InstallCursor()
|
||||
|
||||
// Verify the file was created at the expected path
|
||||
if !FileExists(expectedPath) {
|
||||
t.Errorf("Expected file at %s", expectedPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCursorTemplateFormatting(t *testing.T) {
|
||||
// Verify template is well-formed
|
||||
template := cursorRulesTemplate
|
||||
|
||||
// Should have both markers
|
||||
if !strings.Contains(template, "BEGIN BEADS INTEGRATION") {
|
||||
t.Error("Missing BEGIN marker")
|
||||
}
|
||||
if !strings.Contains(template, "END BEADS INTEGRATION") {
|
||||
t.Error("Missing END marker")
|
||||
}
|
||||
|
||||
// Should have workflow section
|
||||
if !strings.Contains(template, "## Workflow") {
|
||||
t.Error("Missing Workflow section")
|
||||
}
|
||||
|
||||
// Should have context loading section
|
||||
if !strings.Contains(template, "## Context Loading") {
|
||||
t.Error("Missing Context Loading section")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user