summaryrefslogtreecommitdiff
path: root/internal/store/shopping_test.go
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-07-15 09:43:01 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-07-16 02:50:42 +0000
commitb27b7e681952df44f05c60eea7218798b31d1fb4 (patch)
treeb71195de03f65ab57341ae1628b07009a6c7d22e /internal/store/shopping_test.go
parent7d59a3020c9a98bb8af7240f584ac4c7813a46f6 (diff)
refactor(store): extract shopping methods from sqlite.go into shopping.go
Pure move: UserShoppingItem type, its CRUD methods, and SetShoppingItemChecked/GetShoppingItemChecks, plus their tests and setupTestStoreWithShopping helper, out of sqlite.go. No behavior change. Mirrors the existing internal/handlers/shopping.go naming. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
Diffstat (limited to 'internal/store/shopping_test.go')
-rw-r--r--internal/store/shopping_test.go151
1 files changed, 151 insertions, 0 deletions
diff --git a/internal/store/shopping_test.go b/internal/store/shopping_test.go
new file mode 100644
index 0000000..01f106c
--- /dev/null
+++ b/internal/store/shopping_test.go
@@ -0,0 +1,151 @@
+package store
+
+import (
+ "database/sql"
+ "path/filepath"
+ "testing"
+
+ _ "github.com/mattn/go-sqlite3"
+)
+
+func setupTestStoreWithShopping(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 user_shopping_items (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ name TEXT NOT NULL,
+ store TEXT NOT NULL,
+ checked INTEGER DEFAULT 0,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
+ );
+ CREATE TABLE IF NOT EXISTS shopping_item_checks (
+ source TEXT NOT NULL,
+ item_id TEXT NOT NULL,
+ checked INTEGER DEFAULT 0,
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (source, item_id)
+ );
+ `
+ if _, err := db.Exec(schema); err != nil {
+ t.Fatalf("Failed to create schema: %v", err)
+ }
+
+ return store
+}
+
+func TestUserShoppingItems_CRUD(t *testing.T) {
+ store := setupTestStoreWithShopping(t)
+ defer func() { _ = store.Close() }()
+
+ // Save items
+ if err := store.SaveUserShoppingItem("Milk", "Costco"); err != nil {
+ t.Fatalf("Failed to save item: %v", err)
+ }
+ if err := store.SaveUserShoppingItem("Bread", "Safeway"); err != nil {
+ t.Fatalf("Failed to save second item: %v", err)
+ }
+
+ // Get items
+ items, err := store.GetUserShoppingItems()
+ if err != nil {
+ t.Fatalf("Failed to get items: %v", err)
+ }
+ if len(items) != 2 {
+ t.Errorf("Expected 2 items, got %d", len(items))
+ }
+
+ // Verify item data
+ var milkItem UserShoppingItem
+ for _, item := range items {
+ if item.Name == "Milk" {
+ milkItem = item
+ break
+ }
+ }
+ if milkItem.Name != "Milk" {
+ t.Error("Could not find Milk item")
+ }
+ if milkItem.Store != "Costco" {
+ t.Errorf("Expected store 'Costco', got '%s'", milkItem.Store)
+ }
+ if milkItem.Checked {
+ t.Error("New item should not be checked")
+ }
+
+ // Toggle item
+ if err := store.ToggleUserShoppingItem(milkItem.ID, true); err != nil {
+ t.Fatalf("Failed to toggle item: %v", err)
+ }
+
+ items, _ = store.GetUserShoppingItems()
+ for _, item := range items {
+ if item.ID == milkItem.ID && !item.Checked {
+ t.Error("Item should be checked after toggle")
+ }
+ }
+
+ // Delete item
+ if err := store.DeleteUserShoppingItem(milkItem.ID); err != nil {
+ t.Fatalf("Failed to delete item: %v", err)
+ }
+
+ items, _ = store.GetUserShoppingItems()
+ if len(items) != 1 {
+ t.Errorf("Expected 1 item after delete, got %d", len(items))
+ }
+}
+
+func TestShoppingItemChecks_ExternalSources(t *testing.T) {
+ store := setupTestStoreWithShopping(t)
+ defer func() { _ = store.Close() }()
+
+ // Set checked for trello item
+ if err := store.SetShoppingItemChecked("trello", "card-123", true); err != nil {
+ t.Fatalf("Failed to set trello checked: %v", err)
+ }
+
+ // Set checked for plantoeat item
+ if err := store.SetShoppingItemChecked("plantoeat", "pte-456", true); err != nil {
+ t.Fatalf("Failed to set plantoeat checked: %v", err)
+ }
+
+ // Get trello checks
+ trelloChecks, err := store.GetShoppingItemChecks("trello")
+ if err != nil {
+ t.Fatalf("Failed to get trello checks: %v", err)
+ }
+ if !trelloChecks["card-123"] {
+ t.Error("Expected trello card to be checked")
+ }
+
+ // Get plantoeat checks
+ pteChecks, err := store.GetShoppingItemChecks("plantoeat")
+ if err != nil {
+ t.Fatalf("Failed to get plantoeat checks: %v", err)
+ }
+ if !pteChecks["pte-456"] {
+ t.Error("Expected plantoeat item to be checked")
+ }
+
+ // Uncheck trello item
+ if err := store.SetShoppingItemChecked("trello", "card-123", false); err != nil {
+ t.Fatalf("Failed to uncheck trello item: %v", err)
+ }
+
+ trelloChecks, _ = store.GetShoppingItemChecks("trello")
+ if trelloChecks["card-123"] {
+ t.Error("Trello item should be unchecked after update")
+ }
+}