diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-03-21 21:24:02 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-03-21 21:24:02 +0000 |
| commit | 764d4d2d07449aec72c87afe941b7c63ea05e08c (patch) | |
| tree | 042b157cfff2ab358b5bb9b891f26944133b7065 /internal/store/sqlite_test.go | |
| parent | 5f4f59fc6302a4e44773d4a939ae7b3304d61f1f (diff) | |
feat: Phase 1 — remove bug feature and dead code
- Delete Bug struct, BugToAtom, SourceBug, TypeBug, TypeNote
- Remove bug store methods (SaveBug, GetBugs, ResolveBug, etc.)
- Remove HandleGetBugs, HandleReportBug, bug branches in handlers
- Remove bug routes, bugs.html template, bug UI from index.html
- Remove AddMealToPlanner stub + interface method
- Migration 018: DROP TABLE IF EXISTS bugs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/store/sqlite_test.go')
| -rw-r--r-- | internal/store/sqlite_test.go | 188 |
1 files changed, 68 insertions, 120 deletions
diff --git a/internal/store/sqlite_test.go b/internal/store/sqlite_test.go index c6c428a..0514eeb 100644 --- a/internal/store/sqlite_test.go +++ b/internal/store/sqlite_test.go @@ -2,6 +2,7 @@ package store import ( "database/sql" + "os" "path/filepath" "testing" "time" @@ -10,6 +11,73 @@ import ( "task-dashboard/internal/models" ) +func TestRunMigrations_LegacyDB_SeedsTrackingTable(t *testing.T) { + tempDir := t.TempDir() + dbPath := filepath.Join(tempDir, "test.db") + migDir := filepath.Join(tempDir, "migrations") + if err := os.MkdirAll(migDir, 0755); err != nil { + t.Fatal(err) + } + + // Simulate a legacy DB: tables exist but no schema_migrations + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + t.Fatal(err) + } + if _, err := db.Exec("CREATE TABLE legacy_items (id INTEGER PRIMARY KEY); ALTER TABLE legacy_items ADD COLUMN created_at DATETIME;"); err != nil { + t.Fatal(err) + } + db.Close() + + migration := []byte("CREATE TABLE legacy_items (id INTEGER PRIMARY KEY);\nALTER TABLE legacy_items ADD COLUMN created_at DATETIME;\n") + if err := os.WriteFile(filepath.Join(migDir, "001_test.sql"), migration, 0644); err != nil { + t.Fatal(err) + } + + // Should not fail even though migration SQL would fail if re-run + store, err := New(dbPath, migDir) + if err != nil { + t.Fatalf("New() on legacy DB failed: %v", err) + } + defer store.Close() + + // Confirm migration was recorded as applied + var count int + store.db.QueryRow("SELECT COUNT(*) FROM schema_migrations WHERE filename = '001_test.sql'").Scan(&count) + if count != 1 { + t.Errorf("expected migration to be seeded in schema_migrations, got count=%d", count) + } +} + +func TestRunMigrations_IdempotentOnRestart(t *testing.T) { + tempDir := t.TempDir() + dbPath := filepath.Join(tempDir, "test.db") + migDir := filepath.Join(tempDir, "migrations") + if err := os.MkdirAll(migDir, 0755); err != nil { + t.Fatal(err) + } + + // Write a migration with a non-idempotent ALTER TABLE + migration := []byte("CREATE TABLE foo (id INTEGER PRIMARY KEY);\nALTER TABLE foo ADD COLUMN bar TEXT;\n") + if err := os.WriteFile(filepath.Join(migDir, "001_test.sql"), migration, 0644); err != nil { + t.Fatal(err) + } + + // First run — should succeed + store1, err := New(dbPath, migDir) + if err != nil { + t.Fatalf("first New() failed: %v", err) + } + store1.Close() + + // Second run (simulating service restart) — should also succeed + store2, err := New(dbPath, migDir) + if err != nil { + t.Fatalf("second New() failed (migration re-run not skipped): %v", err) + } + store2.Close() +} + // setupTestStoreWithTasks creates a test store with tasks table func setupTestStoreWithTasks(t *testing.T) *Store { t.Helper() @@ -631,126 +699,6 @@ func TestGetCardsByDateRange(t *testing.T) { } } -// setupTestStoreWithBugs creates a test store with bugs table -func setupTestStoreWithBugs(t *testing.T) *Store { - t.Helper() - - tempDir := t.TempDir() - dbPath := filepath.Join(tempDir, "test.db") - - db, err := sql.Open("sqlite3", dbPath) - if err != nil { - t.Fatalf("Failed to open test database: %v", err) - } - - db.SetMaxOpenConns(1) - - store := &Store{db: db} - - schema := ` - CREATE TABLE IF NOT EXISTS bugs ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - description TEXT NOT NULL, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - resolved_at DATETIME DEFAULT NULL - ); - ` - if _, err := db.Exec(schema); err != nil { - t.Fatalf("Failed to create schema: %v", err) - } - - return store -} - -func TestBugResolution(t *testing.T) { - store := setupTestStoreWithBugs(t) - defer func() { _ = store.Close() }() - - // Save some bugs - if err := store.SaveBug("Bug 1"); err != nil { - t.Fatalf("Failed to save bug 1: %v", err) - } - if err := store.SaveBug("Bug 2"); err != nil { - t.Fatalf("Failed to save bug 2: %v", err) - } - if err := store.SaveBug("Bug 3"); err != nil { - t.Fatalf("Failed to save bug 3: %v", err) - } - - // Verify all 3 bugs are unresolved - unresolved, err := store.GetUnresolvedBugs() - if err != nil { - t.Fatalf("GetUnresolvedBugs failed: %v", err) - } - if len(unresolved) != 3 { - t.Errorf("Expected 3 unresolved bugs, got %d", len(unresolved)) - } - - // Resolve bug 2 - if err := store.ResolveBug(2); err != nil { - t.Fatalf("ResolveBug failed: %v", err) - } - - // Verify only 2 unresolved bugs remain - unresolved, err = store.GetUnresolvedBugs() - if err != nil { - t.Fatalf("GetUnresolvedBugs after resolve failed: %v", err) - } - if len(unresolved) != 2 { - t.Errorf("Expected 2 unresolved bugs, got %d", len(unresolved)) - } - - // Verify bug 2 is not in the unresolved list - for _, bug := range unresolved { - if bug.ID == 2 { - t.Error("Bug 2 should have been resolved but is still in unresolved list") - } - } - - // Verify all bugs still exist in GetBugs (including resolved) - allBugs, err := store.GetBugs() - if err != nil { - t.Fatalf("GetBugs failed: %v", err) - } - if len(allBugs) != 3 { - t.Errorf("Expected 3 total bugs, got %d", len(allBugs)) - } - - // Verify bug 2 has resolved_at set - for _, bug := range allBugs { - if bug.ID == 2 { - if bug.ResolvedAt == nil { - t.Error("Bug 2 should have resolved_at set") - } - } - } - - // Unresolve bug 2 - if err := store.UnresolveBug(2); err != nil { - t.Fatalf("UnresolveBug failed: %v", err) - } - - // Verify all 3 bugs are unresolved again - unresolved, err = store.GetUnresolvedBugs() - if err != nil { - t.Fatalf("GetUnresolvedBugs after unresolve failed: %v", err) - } - if len(unresolved) != 3 { - t.Errorf("Expected 3 unresolved bugs after unresolve, got %d", len(unresolved)) - } -} - -func TestResolveBug_NonExistent(t *testing.T) { - store := setupTestStoreWithBugs(t) - defer func() { _ = store.Close() }() - - // Resolving a non-existent bug should not error (no rows affected is fine) - err := store.ResolveBug(999) - if err != nil { - t.Errorf("ResolveBug on non-existent bug should not error, got: %v", err) - } -} - // ============================================================================= // User Shopping Items Tests // ============================================================================= |
