1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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")
}
}
|