← back to Wallco Ai
drunk-animals: end-to-end smoke test, 19/19 passing
0ec07a8e324e5e9ad6acbbe04980ccad677024b5 · 2026-05-13 07:18:06 -0700 · SteveStudio2
Validates every artifact built tonight:
- pm2 daemon online
- server health + PG count + snapshot consistency + feed consistency
- all 3 endpoints (feed / stats / best) + schema fields
- /drunk-animals → /designs?cat= redirect
- /drunk-animals/live page has title + status pill + feed wire
- /designs hero block renders for drunk-animals filter
- newest design page + image both 200 with Cache-Control
- /admin/reload-designs accepts localhost auth
- 100% motif tagging coverage
- id_seq ≥ max(id) (prevents the desync bug recurring)
- every PG row has its PNG on disk (no orphans)
- homepage carries wallco branding
Workaround landed: zsh $path is the array form of $PATH — using it as
a loop var (for path in ...) silently corrupts PATH mid-script. Fixed
with 'design_path' rename + while-read instead of for-in.
Files touched
A scripts/test_drunk_animals.sh
Diff
commit 0ec07a8e324e5e9ad6acbbe04980ccad677024b5
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Wed May 13 07:18:06 2026 -0700
drunk-animals: end-to-end smoke test, 19/19 passing
Validates every artifact built tonight:
- pm2 daemon online
- server health + PG count + snapshot consistency + feed consistency
- all 3 endpoints (feed / stats / best) + schema fields
- /drunk-animals → /designs?cat= redirect
- /drunk-animals/live page has title + status pill + feed wire
- /designs hero block renders for drunk-animals filter
- newest design page + image both 200 with Cache-Control
- /admin/reload-designs accepts localhost auth
- 100% motif tagging coverage
- id_seq ≥ max(id) (prevents the desync bug recurring)
- every PG row has its PNG on disk (no orphans)
- homepage carries wallco branding
Workaround landed: zsh $path is the array form of $PATH — using it as
a loop var (for path in ...) silently corrupts PATH mid-script. Fixed
with 'design_path' rename + while-read instead of for-in.
---
scripts/test_drunk_animals.sh | 119 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 119 insertions(+)
diff --git a/scripts/test_drunk_animals.sh b/scripts/test_drunk_animals.sh
new file mode 100755
index 0000000..9267cad
--- /dev/null
+++ b/scripts/test_drunk_animals.sh
@@ -0,0 +1,119 @@
+#!/bin/zsh
+# End-to-end smoke test for the drunk-animals overnight pipeline.
+# Validates every endpoint + page + DB state I touched tonight.
+
+BASE=http://127.0.0.1:9792
+PSQL=/opt/homebrew/opt/postgresql@14/bin/psql
+PASS=0
+FAIL=0
+
+check() {
+ local name="$1"
+ local result="$2"
+ if [[ "$result" == "PASS" ]]; then
+ printf " \033[32m✓\033[0m %s\n" "$name"
+ PASS=$((PASS+1))
+ else
+ printf " \033[31m✗\033[0m %s — %s\n" "$name" "$result"
+ FAIL=$((FAIL+1))
+ fi
+}
+
+echo ""
+echo "═══ Drunk Animals — End-to-End Test ═══"
+echo ""
+
+# 1. pm2 daemon online
+pm2_state=$(pm2 list 2>&1 | grep wallco-drunk-animals | grep -c online)
+check "pm2 daemon online" $([[ $pm2_state == "1" ]] && echo PASS || echo "daemon not online")
+
+# 2. wallco-ai server responding
+http=$(curl -s -o /dev/null -w "%{http_code}" -m 3 $BASE/health)
+check "wallco-ai :9792 health" $([[ $http == "200" ]] && echo PASS || echo "http $http")
+
+# 3. PG row count
+pg_count=$($PSQL dw_unified -At -c "SELECT count(*) FROM spoon_all_designs WHERE category='drunk-animals';" 2>&1)
+check "PG drunk-animals count > 0" $([[ "$pg_count" -gt 0 ]] && echo PASS || echo "got $pg_count")
+echo " → $pg_count rows"
+
+# 4. Snapshot matches PG
+snap_count=$(python3 -c "import json; print(sum(1 for d in json.load(open('/Users/stevestudio2/Projects/wallco-ai/data/designs.json')) if d.get('category')=='drunk-animals'))")
+check "designs.json snapshot matches PG" $([[ "$snap_count" == "$pg_count" ]] && echo PASS || echo "snapshot=$snap_count pg=$pg_count")
+
+# 5. In-memory feed total matches PG
+feed_total=$(curl -sf -m 3 "$BASE/api/drunk-animals/feed?limit=1" | python3 -c "import sys,json; print(json.load(sys.stdin)['total'])" 2>&1)
+check "feed.total matches PG" $([[ "$feed_total" == "$pg_count" ]] && echo PASS || echo "feed=$feed_total pg=$pg_count")
+
+# 6. /api/drunk-animals/stats endpoint
+stats=$(curl -sf -m 3 $BASE/api/drunk-animals/stats)
+ok=$(echo "$stats" | python3 -c "import sys,json; d=json.load(sys.stdin); print('PASS' if d.get('total') and 'animals' in d and 'avg_saturation' in d and 'status' in d else 'missing fields')")
+check "/api/drunk-animals/stats schema" "$ok"
+# Status field
+sval=$(echo "$stats" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
+check "stats.status ∈ {live,complete}" $([[ "$sval" == "live" || "$sval" == "complete" ]] && echo PASS || echo "got $sval")
+echo " → status=$sval"
+
+# 7. /api/drunk-animals/best returns N
+best_n=$(curl -sf -m 3 "$BASE/api/drunk-animals/best?n=3" | python3 -c "import sys,json; print(len(json.load(sys.stdin)['best']))")
+check "/api/drunk-animals/best?n=3 returns 3" $([[ "$best_n" == "3" ]] && echo PASS || echo "got $best_n")
+
+# 8. /drunk-animals friendly redirect
+loc=$(curl -sI -m 3 $BASE/drunk-animals 2>&1 | tr -d '\r' | awk -F': ' 'tolower($1)=="location"{print $2}')
+check "/drunk-animals redirects to /designs?cat=" $([[ "$loc" == */designs?cat=drunk-animals* ]] && echo PASS || echo "got: '$loc'")
+
+# 9. /drunk-animals/live page renders
+live_html=$(curl -sf -m 3 $BASE/drunk-animals/live)
+has_title=$(echo "$live_html" | grep -c "Drunk Animals Collection")
+has_pulse=$(echo "$live_html" | grep -c "status-pill")
+has_feed=$(echo "$live_html" | grep -c "/api/drunk-animals/feed")
+check "/drunk-animals/live has title + pulse + feed wire" $([[ $has_title -ge 1 && $has_pulse -ge 1 && $has_feed -ge 1 ]] && echo PASS || echo "title=$has_title pulse=$has_pulse feed=$has_feed")
+
+# 10. /designs?cat=drunk-animals has hero block
+hero=$(curl -sf -m 3 "$BASE/designs?cat=drunk-animals" | grep -c "The Drunk Animals Collection")
+check "/designs?cat=drunk-animals shows hero block" $([[ $hero -ge 1 ]] && echo PASS || echo "hero count $hero")
+
+# 11. Sample design page renders (newest)
+newest_id=$($PSQL dw_unified -At -c "SELECT id FROM spoon_all_designs WHERE category='drunk-animals' ORDER BY id DESC LIMIT 1;")
+http=$(curl -s -o /dev/null -w "%{http_code}" -m 3 $BASE/design/$newest_id)
+check "/design/$newest_id renders 200" $([[ $http == "200" ]] && echo PASS || echo "http $http")
+
+# 12. Sample image serves with cache headers
+newest_filename=$($PSQL dw_unified -At -c "SELECT split_part(local_path,'/',-1) FROM spoon_all_designs WHERE category='drunk-animals' ORDER BY id DESC LIMIT 1;")
+img_headers=$(curl -sI -m 3 "$BASE/designs/img/$newest_filename")
+img_http=$(echo "$img_headers" | head -1 | awk '{print $2}')
+img_cache=$(echo "$img_headers" | grep -ic "cache-control")
+check "/designs/img/<newest>.png serves 200" $([[ $img_http == "200" ]] && echo PASS || echo "http $img_http")
+check "image has Cache-Control header" $([[ $img_cache -ge 1 ]] && echo PASS || echo "no cache-control")
+
+# 13. /admin/reload-designs is admin-gated (works from localhost)
+reload=$(curl -sf -m 3 -X POST $BASE/admin/reload-designs)
+ok=$(echo "$reload" | python3 -c "import sys,json; d=json.load(sys.stdin); print('PASS' if d.get('ok') and 'before' in d and 'after' in d else 'malformed')")
+check "/admin/reload-designs (localhost) returns ok" "$ok"
+
+# 14. Motif tagging coverage
+untagged=$($PSQL dw_unified -At -c "SELECT count(*) FROM spoon_all_designs WHERE category='drunk-animals' AND motifs IS NULL;")
+check "all drunk-animals tagged (untagged=0)" $([[ "$untagged" == "0" ]] && echo PASS || echo "$untagged untagged")
+
+# 15. Sequence is sane — next call to nextval() = last_value + 1 must
+# exceed current max(id). So last_value >= max(id) is required.
+seq=$($PSQL dw_unified -At -c "SELECT last_value FROM spoon_all_designs_id_seq;")
+max_id=$($PSQL dw_unified -At -c "SELECT max(id) FROM spoon_all_designs;")
+check "id_seq.last_value ≥ max(id) (no collision on next insert)" $([[ "$seq" -ge "$max_id" ]] && echo PASS || echo "seq=$seq max=$max_id (next nextval would collide)")
+
+# 16. Disk PNGs match rows (no orphans)
+# NB: avoid using $path as a loop var — zsh has $path tied to $PATH (array form).
+disk_count=0
+while IFS= read -r design_path; do
+ [[ -f "$design_path" ]] && disk_count=$((disk_count+1))
+done < <($PSQL dw_unified -At -c "SELECT local_path FROM spoon_all_designs WHERE category='drunk-animals';")
+check "all rows have PNG on disk" $([[ "$disk_count" == "$pg_count" ]] && echo PASS || echo "disk=$disk_count pg=$pg_count")
+
+# 17. Hero anatomy compliance (logo UL + hamburger UR — per Steve's standing rule)
+home_html=$(curl -sf -m 3 $BASE/)
+has_logo=$(echo "$home_html" | grep -ciE "logo|wallco")
+check "homepage has wallco branding" $([[ $has_logo -ge 1 ]] && echo PASS || echo "no logo")
+
+echo ""
+echo "═══ $PASS passed · $FAIL failed ═══"
+echo ""
+exit $FAIL
← e884616 /admin/reload-designs: also bump by-color cache version + cl
·
back to Wallco Ai
·
/admin/health: surface random-ETag hit/miss/rate alongside b f12547c →