Files
beads/cmd/bd/reset_test.go
Steve Yegge 91bce49d47 feat: add bd reset command for complete beads removal (GH#505)
Adds a new `bd reset` command that completely removes beads from a
repository, automating the manual uninstall process.

The command:
1. Stops any running daemon
2. Removes git hooks installed by beads
3. Removes the merge driver configuration
4. Removes beads entry from .gitattributes
5. Deletes the .beads directory (ALL ISSUE DATA)
6. Removes the sync worktree (if exists)

Safety features:
- Requires --confirm <remote> to prevent accidental data loss
- Supports --dry-run to preview what would be removed
- Provides clear warnings about permanent data deletion

Closes GH#505

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 01:09:23 -08:00

100 lines
2.8 KiB
Go

package main
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestRemoveBeadsFromGitattributes(t *testing.T) {
t.Run("removes beads entry", func(t *testing.T) {
tmpDir := t.TempDir()
gitattributes := filepath.Join(tmpDir, ".gitattributes")
content := `*.png binary
# Use bd merge for beads JSONL files
.beads/issues.jsonl merge=beads
*.jpg binary
`
if err := os.WriteFile(gitattributes, []byte(content), 0644); err != nil {
t.Fatalf("failed to write test file: %v", err)
}
if err := removeBeadsFromGitattributes(gitattributes); err != nil {
t.Fatalf("removeBeadsFromGitattributes failed: %v", err)
}
result, err := os.ReadFile(gitattributes)
if err != nil {
t.Fatalf("failed to read result: %v", err)
}
if strings.Contains(string(result), "merge=beads") {
t.Error("beads merge entry should have been removed")
}
if strings.Contains(string(result), "Use bd merge") {
t.Error("beads comment should have been removed")
}
if !strings.Contains(string(result), "*.png binary") {
t.Error("other entries should be preserved")
}
if !strings.Contains(string(result), "*.jpg binary") {
t.Error("other entries should be preserved")
}
})
t.Run("removes file if only beads entry", func(t *testing.T) {
tmpDir := t.TempDir()
gitattributes := filepath.Join(tmpDir, ".gitattributes")
content := `# Use bd merge for beads JSONL files
.beads/issues.jsonl merge=beads
`
if err := os.WriteFile(gitattributes, []byte(content), 0644); err != nil {
t.Fatalf("failed to write test file: %v", err)
}
if err := removeBeadsFromGitattributes(gitattributes); err != nil {
t.Fatalf("removeBeadsFromGitattributes failed: %v", err)
}
if _, err := os.Stat(gitattributes); !os.IsNotExist(err) {
t.Error("file should have been deleted when only beads entries present")
}
})
t.Run("handles non-existent file", func(t *testing.T) {
tmpDir := t.TempDir()
gitattributes := filepath.Join(tmpDir, ".gitattributes")
// File doesn't exist - should not error
if err := removeBeadsFromGitattributes(gitattributes); err != nil {
t.Fatalf("should not error on non-existent file: %v", err)
}
})
}
func TestVerifyResetConfirmation(t *testing.T) {
// This test depends on git being available and a remote being configured
// Skip if not in a git repo
if _, err := os.Stat(".git"); os.IsNotExist(err) {
t.Skip("not in a git repository")
}
t.Run("accepts origin", func(t *testing.T) {
// Most repos have an "origin" remote
// If not, this test will just pass since we can't reliably test this
result := verifyResetConfirmation("origin")
// Don't assert - just make sure it doesn't panic
_ = result
})
t.Run("rejects invalid remote", func(t *testing.T) {
result := verifyResetConfirmation("nonexistent-remote-12345")
if result {
t.Error("should reject non-existent remote")
}
})
}