-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun_cli_e2e.sh
More file actions
208 lines (184 loc) · 6.37 KB
/
run_cli_e2e.sh
File metadata and controls
208 lines (184 loc) · 6.37 KB
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage: ./run_cli_e2e.sh -u USERNAME -p PASSWORD [-s SERVER] [--delete]
-u USERNAME KitchenOwl username/email
-p PASSWORD KitchenOwl password
-s SERVER KitchenOwl server base URL
--delete Delete the household after the test so you can inspect the run before cleanup
Example:
./run_cli_e2e.sh -u test_user -p password --delete
EOF
exit 1
}
#SERVER="https://testing-server.exmple"
DELETE_HOUSEHOLD=false
while [[ $# -gt 0 ]]; do
case $1 in
-u|--user)
USERNAME="$2"
shift 2
;;
-p|--password)
PASSWORD="$2"
shift 2
;;
-s|--server)
SERVER="$2"
shift 2
;;
--delete)
DELETE_HOUSEHOLD=true
shift
;;
*)
usage
;;
esac
done
if [[ -z "${USERNAME:-}" || -z "${PASSWORD:-}" ]]; then
usage
fi
CLI="./.venv/bin/python -m kitchenowl_cli.main"
SERVER="${SERVER%/}"
CURL_TIMEOUT=10
# Ensure CLI uses local source tree, not any globally installed package.
export PYTHONPATH="$(pwd):${PYTHONPATH:-}"
echo "Logging in to $SERVER"
$CLI auth login --server "$SERVER" --username "$USERNAME" --password "$PASSWORD"
TOKEN_DATA=$(python3 - <<'PY'
import json
from pathlib import Path
cfg = Path.home() / ".config" / "kitchenowl" / "config.json"
data = json.loads(cfg.read_text())
print(data["access_token"])
print(data["user"]["id"])
PY
)
ACCESS_TOKEN=$(printf "%s\n" "$TOKEN_DATA" | sed -n '1p')
USER_ID=$(printf "%s\n" "$TOKEN_DATA" | sed -n '2p')
HH_NAME="CLI Test Run $(date +%Y%m%d-%H%M%S)"
HH_JSON=$($CLI household create --name "$HH_NAME" --description "CLI e2e household" --use --json)
HH_ID=$(python3 -c 'import json,sys; print(json.loads(sys.argv[1])["id"])' "$HH_JSON")
echo "Created household $HH_ID ($HH_NAME)"
ADMIN_JSON=$($CLI user search --query admin --json 2>/tmp/cli_user_search.json || true)
ADMIN_ID=$(python3 - <<'PY'
import json,sys
data=sys.stdin.read().strip()
if not data:
sys.exit(1)
try:
users=json.loads(data)
except Exception:
sys.exit(1)
else:
if isinstance(users, list) and users:
print(users[0]["id"])
else:
sys.exit(1)
PY
<<<"$ADMIN_JSON" || true)
if [[ -z "${ADMIN_ID:-}" ]]; then
echo "ERROR: Could not resolve an admin user id. Ensure an admin account exists and user search is allowed." >&2
exit 1
fi
echo "Granting admin user $ADMIN_ID admin rights on household $HH_ID"
curl -sS --max-time "$CURL_TIMEOUT" -X PUT "$SERVER/api/household/$HH_ID/member/$ADMIN_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"admin":true}' >/tmp/cli_admin_member.json
echo "Admin assignment response: $(cat /tmp/cli_admin_member.json)"
LIST_JSON=$($CLI shoppinglist create "CLI Grocery List" --household-id "$HH_ID" --json)
LIST_ID=$(python3 -c 'import json,sys; print(json.loads(sys.argv[1])["id"])' "$LIST_JSON")
echo "Created shopping list $LIST_ID"
for ITEM in Milk Bread Eggs; do
$CLI shoppinglist add-item-by-name "$LIST_ID" "$ITEM" --description "Test item" >/tmp/cli_item.log
done
RECIPE1_JSON=$($CLI recipe add --household-id "$HH_ID" \
--name "CLI Flag Recipe" \
--description "Scripted via run_cli_e2e" \
--time 30 \
--yields 4 \
--tag cli \
--item "Prepare dressing|Whisk oil + vinegar|false" \
--ingredient "Lettuce|1 head|false" \
--ingredient "Olive oil|2 tbsp|false" \
--ingredient "Croutons|1 cup|true" \
--json)
RECIPE1_ID=$(python3 -c 'import json,sys; print(json.loads(sys.argv[1])["id"])' "$RECIPE1_JSON")
RECIPE1_GET_JSON=$($CLI recipe get "$RECIPE1_ID" --json)
python3 - <<'PY' "$RECIPE1_GET_JSON"
import json,sys
r=json.loads(sys.argv[1])
ing=r.get("items", r.get("ingredients", []))
assert any(i.get("name") == "Lettuce" and i.get("optional") is False for i in ing), "Missing required ingredient"
assert any(i.get("name") == "Croutons" and i.get("optional") is True for i in ing), "Missing optional ingredient"
print("Verified flag-based recipe ingredients via recipe get (required + optional)")
PY
echo "Created recipe #$RECIPE1_ID"
cat <<'EOF' >/tmp/run_cli_recipe.yml
name: CLI File Recipe
description: Created from YAML
time: 45
cook_time: 35
prep_time: 10
yields: 6
visibility: 0
items:
- name: Chop vegetables
description: Fine dice
optional: false
ingredients:
- name: Tomato
description: 3
optional: false
- name: Chili flakes
description: pinch
optional: true
tags:
- file
- cli
EOF
RECIPE2_JSON=$($CLI recipe add --household-id "$HH_ID" --from-file /tmp/run_cli_recipe.yml --json)
RECIPE2_ID=$(python3 -c 'import json,sys; print(json.loads(sys.argv[1])["id"])' "$RECIPE2_JSON")
RECIPE2_GET_JSON=$($CLI recipe get "$RECIPE2_ID" --json)
python3 - <<'PY' "$RECIPE2_GET_JSON"
import json,sys
r=json.loads(sys.argv[1])
ing=r.get("items", r.get("ingredients", []))
assert any(i.get("name") == "Tomato" and i.get("optional") is False for i in ing), "Missing required file ingredient"
assert any(i.get("name") == "Chili flakes" and i.get("optional") is True for i in ing), "Missing optional file ingredient"
print("Verified file-based recipe ingredients via recipe get (required + optional)")
PY
echo "Created recipe #$RECIPE2_ID from file"
TOKEN_DATA=$(python3 - <<'PY'
import json
from pathlib import Path
cfg = Path.home() / ".config" / "kitchenowl" / "config.json"
data = json.loads(cfg.read_text())
print(data["access_token"])
print(data["user"]["id"])
PY
)
ACCESS_TOKEN=$(printf "%s\n" "$TOKEN_DATA" | sed -n '1p')
USER_ID=$(printf "%s\n" "$TOKEN_DATA" | sed -n '2p')
CURL_OPTS=(-sS --max-time "$CURL_TIMEOUT" -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json")
DATE_MS=$(( $(date +%s) * 1000 ))
curl "${CURL_OPTS[@]}" -X POST "$SERVER/api/household/$HH_ID/planner/recipe" \
-d "{\"recipe_id\":$RECIPE1_ID,\"cooking_date\":$DATE_MS}" >/tmp/plan.json
echo "Planned recipe $RECIPE1_ID for household $HH_ID"
curl "${CURL_OPTS[@]}" -X POST "$SERVER/api/household/$HH_ID/expense" \
-d "{\"name\":\"CLI Test Expense\",\"amount\":12.50,\"paid_by\":{\"id\":$USER_ID},\"paid_for\":[{\"id\":$USER_ID}],\"date\":$DATE_MS}" >/tmp/expense.json
echo "Logged expense for household $HH_ID"
echo
echo "Summary"
echo " Household ID: $HH_ID"
echo " Shopping list ID: $LIST_ID"
echo " Recipes: $RECIPE1_ID, $RECIPE2_ID"
echo " Planner entry: $(cat /tmp/plan.json)"
echo " Expense entry: $(cat /tmp/expense.json)"
if $DELETE_HOUSEHOLD; then
echo "Deleting household $HH_ID"
$CLI household delete "$HH_ID" -y
fi