Files
gastown/internal/doctor/beads_check_test.go
Steve Yegge debe47cc62 fix(doctor): add beads database check to detect empty issues.db
Add a new doctor check that detects when issues.db is empty but
issues.jsonl has content. This situation can cause "table issues has
no column named pinned" errors when running bd mail send.

The check:
- Detects empty database file alongside non-empty JSONL
- Can auto-fix by deleting the empty database and triggering rebuild
- Works for both town-level and rig-level beads

Run 'gt doctor --fix' to automatically fix this issue.

Fixes gt-bxi8

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

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

102 lines
2.3 KiB
Go

package doctor
import (
"os"
"path/filepath"
"testing"
)
func TestNewBeadsDatabaseCheck(t *testing.T) {
check := NewBeadsDatabaseCheck()
if check.Name() != "beads-database" {
t.Errorf("expected name 'beads-database', got %q", check.Name())
}
if !check.CanFix() {
t.Error("expected CanFix to return true")
}
}
func TestBeadsDatabaseCheck_NoBeadsDir(t *testing.T) {
tmpDir := t.TempDir()
check := NewBeadsDatabaseCheck()
ctx := &CheckContext{TownRoot: tmpDir}
result := check.Run(ctx)
if result.Status != StatusWarning {
t.Errorf("expected StatusWarning, got %v", result.Status)
}
}
func TestBeadsDatabaseCheck_NoDatabase(t *testing.T) {
tmpDir := t.TempDir()
beadsDir := filepath.Join(tmpDir, ".beads")
if err := os.MkdirAll(beadsDir, 0755); err != nil {
t.Fatal(err)
}
check := NewBeadsDatabaseCheck()
ctx := &CheckContext{TownRoot: tmpDir}
result := check.Run(ctx)
if result.Status != StatusOK {
t.Errorf("expected StatusOK, got %v", result.Status)
}
}
func TestBeadsDatabaseCheck_EmptyDatabase(t *testing.T) {
tmpDir := t.TempDir()
beadsDir := filepath.Join(tmpDir, ".beads")
if err := os.MkdirAll(beadsDir, 0755); err != nil {
t.Fatal(err)
}
// Create empty database
dbPath := filepath.Join(beadsDir, "issues.db")
if err := os.WriteFile(dbPath, []byte{}, 0644); err != nil {
t.Fatal(err)
}
// Create JSONL with content
jsonlPath := filepath.Join(beadsDir, "issues.jsonl")
if err := os.WriteFile(jsonlPath, []byte(`{"id":"test-1","title":"Test"}`), 0644); err != nil {
t.Fatal(err)
}
check := NewBeadsDatabaseCheck()
ctx := &CheckContext{TownRoot: tmpDir}
result := check.Run(ctx)
if result.Status != StatusError {
t.Errorf("expected StatusError for empty db with content in jsonl, got %v", result.Status)
}
}
func TestBeadsDatabaseCheck_PopulatedDatabase(t *testing.T) {
tmpDir := t.TempDir()
beadsDir := filepath.Join(tmpDir, ".beads")
if err := os.MkdirAll(beadsDir, 0755); err != nil {
t.Fatal(err)
}
// Create database with content
dbPath := filepath.Join(beadsDir, "issues.db")
if err := os.WriteFile(dbPath, []byte("SQLite format 3"), 0644); err != nil {
t.Fatal(err)
}
check := NewBeadsDatabaseCheck()
ctx := &CheckContext{TownRoot: tmpDir}
result := check.Run(ctx)
if result.Status != StatusOK {
t.Errorf("expected StatusOK for populated db, got %v", result.Status)
}
}