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
|
package api
import (
"strings"
"testing"
)
func TestParseShoppingListHTML(t *testing.T) {
// Sample HTML structure matching PlanToEat's shopping list
html := `
<div id="shopping_items" data-total-items="3">
<div id="store-0" class="store" data-store-id="0">
<div class="store_heading">
<h4 class="store_name">Costco (3)</h4>
</div>
<table>
<tr>
<td class="column">
<div class="category-box" id="cat01_350">
<p class="category-title"><span>Baking</span></p>
<ul class="ingredients">
<li class="sli noselect i493745871" data-store-id="0">
<label class="checkbox-label">
<input type="checkbox" name="items[493745871]" value="493745871">
<strong>Olive oil</strong> <span class="quan">2 tablespoons</span>
</label>
</li>
<li class="sli noselect i493745872 checked" data-store-id="0">
<label class="checkbox-label">
<input type="checkbox" name="items[493745872]" value="493745872" checked>
<strong>Flour</strong> <span class="quan">1 cup</span>
</label>
</li>
</ul>
</div>
<div class="category-box" id="cat01_347">
<p class="category-title"><span>Meat</span></p>
<ul class="ingredients">
<li class="sli noselect i493745889" data-store-id="0">
<label class="checkbox-label">
<input type="checkbox" name="items[493745889]" value="493745889">
<strong>Ground beef</strong> <span class="quan">1 pound</span>
</label>
</li>
</ul>
</div>
</td>
</tr>
</table>
</div>
</div>`
items, err := parseShoppingListHTML(strings.NewReader(html))
if err != nil {
t.Fatalf("parseShoppingListHTML failed: %v", err)
}
if len(items) != 3 {
t.Errorf("Expected 3 items, got %d", len(items))
}
// Check first item
if items[0].Name != "Olive oil" {
t.Errorf("Expected first item name 'Olive oil', got '%s'", items[0].Name)
}
if items[0].Quantity != "2 tablespoons" {
t.Errorf("Expected quantity '2 tablespoons', got '%s'", items[0].Quantity)
}
if items[0].Category != "Baking" {
t.Errorf("Expected category 'Baking', got '%s'", items[0].Category)
}
if items[0].Store != "Costco" {
t.Errorf("Expected store 'Costco', got '%s'", items[0].Store)
}
if items[0].ID != "493745871" {
t.Errorf("Expected ID '493745871', got '%s'", items[0].ID)
}
if items[0].Checked {
t.Error("Expected first item to not be checked")
}
// Check checked item
if !items[1].Checked {
t.Error("Expected second item to be checked")
}
// Check item from different category
if items[2].Name != "Ground beef" {
t.Errorf("Expected 'Ground beef', got '%s'", items[2].Name)
}
if items[2].Category != "Meat" {
t.Errorf("Expected category 'Meat', got '%s'", items[2].Category)
}
}
func TestParseShoppingListHTML_EmptyList(t *testing.T) {
html := `<div id="shopping_items" data-total-items="0"></div>`
items, err := parseShoppingListHTML(strings.NewReader(html))
if err != nil {
t.Fatalf("parseShoppingListHTML failed: %v", err)
}
if len(items) != 0 {
t.Errorf("Expected 0 items for empty list, got %d", len(items))
}
}
func TestCleanQuantity(t *testing.T) {
tests := []struct {
input string
expected string
}{
{"1 cup", "1 cup"},
{"2 tablespoons", "2 tablespoons"},
{"1\u00a0pound", "1 pound"},
{" 3 oz ", "3 oz"},
}
for _, tt := range tests {
result := cleanQuantity(tt.input)
if result != tt.expected {
t.Errorf("cleanQuantity(%q) = %q, want %q", tt.input, result, tt.expected)
}
}
}
|