Files
foodster/scripts/smoke.sh
T
Esa Kataja 4ce189d1e4 Merge the log and history into one page, group dishes by category
Kirjaa and Historia were two views of the same thing: every history row was
already a link back into the logger, and the logger had a day switcher. They
are now one page — the day being logged on top, history underneath, each row
loading its day into the logger above. Two tabs instead of three.

That also closed a gap. On an already-logged day there was no way to swap to
a different dish; "Muokkaa" only reopened the sides for the same one. It now
opens the board, so changing a dish and choosing one for the first time are
the same path.

Dishes are grouped by category on both screens, with Sekalaiset collecting
the ones covering more than one. That group is derived from the stored set
rather than being a fifth category, so a single Tortillat still satisfies
meat, chicken, fish and vegetarian at once when the §8.1 suggester arrives.

The two screens sort differently on purpose. The log board keeps frequency
then name inside each group, so favourites surface without wandering between
categories as counts change. The catalog sorts by name, because there you are
hunting a specific dish to edit rather than picking one to eat. groupDishes
preserves the order it is handed; the caller decides which it wants.

Ruoat is renamed Ruuat throughout, label and route both.
2026-09-05 21:28:14 +03:00

197 lines
6.8 KiB
Bash
Executable File

#!/bin/sh
# End-to-end check of a running Foodster: auth, static assets and the bundle
# import flow. Builds its own binary, uses a scratch database and a spare
# port, and cleans up after itself, so it never touches a real instance.
#
# Run it with `make smoke`.
set -eu
cd "$(dirname "$0")/.."
addr=127.0.0.1:8099
pass=smoke
tmp=$(mktemp -d)
trap 'kill ${srv:-0} 2>/dev/null || true; rm -rf "$tmp"' EXIT
go build -o "$tmp/foodster" ./cmd/foodster
FOODSTER_PASSWORD="$pass" FOODSTER_DB="$tmp/smoke.db" FOODSTER_ADDR="$addr" \
"$tmp/foodster" >"$tmp/server.log" 2>&1 &
srv=$!
i=0
while ! curl -sf "http://$addr/healthz" >/dev/null 2>&1; do
i=$((i + 1))
if [ "$i" -gt 50 ]; then
echo "server did not start:"
cat "$tmp/server.log"
exit 1
fi
sleep 0.1
done
fail=0
# check <name> <haystack> <needle>
check() {
if printf '%s' "$2" | grep -qF -- "$3"; then
echo " ok $1"
else
echo " FAIL $1 (expected to find: $3)"
fail=1
fi
}
echo "smoke: http://$addr"
check "unauthenticated request is refused" \
"$(curl -s -o /dev/null -w '%{http_code}' "http://$addr/")" "401"
check "healthz needs no password" \
"$(curl -s -o /dev/null -w '%{http_code}' "http://$addr/healthz")" "200"
check "datastar client is served" \
"$(curl -s -o /dev/null -w '%{http_code}' -u ":$pass" "http://$addr/static/datastar.js")" "200"
check "favicon is served" \
"$(curl -s -o /dev/null -w '%{http_code}' -u ":$pass" "http://$addr/static/favicon.svg")" "200"
check "theme script is served" \
"$(curl -s -o /dev/null -w '%{http_code}' -u ":$pass" "http://$addr/static/theme.js")" "200"
home=$(curl -s -u ":$pass" "http://$addr/")
check "the header carries the brand" "$home" "Foodster"
check "dark is the default without JavaScript" "$home" '<html lang="fi" data-theme="dark">'
check "the theme toggle is present" "$home" "data-theme-toggle"
check "both theme icons ship so CSS can pick one" "$home" 'class="i-moon"'
check "apple touch icon is served" \
"$(curl -s -o /dev/null -w '%{http_code}' -u ":$pass" "http://$addr/static/apple-touch-icon.png")" "200"
# A manifest served as octet-stream is silently ignored by the browser.
check "manifest has the right content type" \
"$(curl -s -o /dev/null -w '%{content_type}' -u ":$pass" "http://$addr/static/manifest.webmanifest")" \
"application/manifest+json"
check "catalog starts empty" \
"$(curl -s -u ":$pass" "http://$addr/ruuat")" "0 pääruokaa"
out=$(curl -s -u ":$pass" -F "tiedosto=@seeds/testi.json" "http://$addr/ruuat/tuonti")
check "file upload imports the seed bundle" "$out" "Lisätty 22, ohitettu 0"
check "counts update after import" "$out" "16 pääruokaa, 6 lisuketta"
check "re-import refuses duplicates" \
"$(curl -s -u ":$pass" -F "tiedosto=@seeds/testi.json" "http://$addr/ruuat/tuonti")" \
"jo listalla"
check "pasted JSON imports" \
"$(curl -s -u ":$pass" -F 'json={"mains":[],"sides":[{"name":"Perunasalaatti"}]}' \
"http://$addr/ruuat/tuonti")" "Lisätty 1"
check "unknown category is reported" \
"$(curl -s -u ":$pass" -F 'json={"mains":[{"name":"Rikki","categories":["kana"]}],"sides":[]}' \
"http://$addr/ruuat/tuonti")" "tuntematon kategoria"
check "empty submit is explained" \
"$(curl -s -u ":$pass" -F 'json=' "http://$addr/ruuat/tuonti")" "Ei tuotavaa"
check "malformed JSON is explained" \
"$(curl -s -u ":$pass" -F 'json={nope' "http://$addr/ruuat/tuonti")" "JSON ei kelpaa"
# ---- the log flow, against the dishes imported above --------------------
board=$(curl -s -u ":$pass" "http://$addr/")
check "board lists imported dishes" "$board" "Lihapullat"
# Pull a real dish id out of the board rather than assuming one.
ruoka=$(printf '%s' "$board" | grep -o 'ruoka=[0-9]*' | head -n1 | cut -d= -f2)
if [ -z "$ruoka" ]; then
echo " FAIL could not find a dish link on the board"
fail=1
ruoka=1
fi
check "picking a dish opens the sides step" \
"$(curl -s -u ":$pass" "http://$addr/?ruoka=$ruoka")" "Tallenna"
check "saving redirects back to the day" \
"$(curl -s -o /dev/null -w '%{http_code}' -u ":$pass" \
-d "pvm=2026-09-05&ruoka=$ruoka" "http://$addr/kirjaa")" "303"
check "the saved day shows what was eaten" \
"$(curl -s -u ":$pass" "http://$addr/?pvm=2026-09-05")" "kirjattu"
check "history is on the same page as the logger" \
"$(curl -s -u ":$pass" "http://$addr/")" "Aiemmin"
check "deleting redirects back" \
"$(curl -s -o /dev/null -w '%{http_code}' -u ":$pass" \
-d "pvm=2026-09-05" "http://$addr/poista")" "303"
check "the day is empty again" \
"$(curl -s -u ":$pass" "http://$addr/?pvm=2026-09-05")" "Etsi"
check "search filters the board" \
"$(curl -s -u ":$pass" "http://$addr/?haku=keitto")" "keitto"
# ---- adding a dish without leaving Kirjaa --------------------------------
miss=$(curl -s -u ":$pass" "http://$addr/?haku=Poronkariste")
check "a search with no hits offers to add it" "$miss" "Ei osumia. Lisätäänkö?"
check "the add form is prefilled with the search" "$miss" 'value="Poronkariste"'
check "quick add goes straight to the sides step" \
"$(curl -s -o /dev/null -w '%{redirect_url}' -u ":$pass" \
-d 'nimi=Poronkariste&kategoria=meat&lisukkeita=1' "http://$addr/lisaa")" \
"ruoka="
check "quick add rejects a dish with no category" \
"$(curl -s -u ":$pass" -d 'nimi=Kategoriaton' "http://$addr/lisaa")" \
"Valitse vähintään yksi kategoria."
check "the quick-added dish is on the board" \
"$(curl -s -u ":$pass" "http://$addr/")" "Poronkariste"
# ---- catalog CRUD from the UI -------------------------------------------
check "adding a main redirects" \
"$(curl -s -o /dev/null -w '%{http_code}' -u ":$pass" \
-d 'nimi=uunikala&kategoria=fish&lisukkeita=1' "http://$addr/ruuat/paaruoka")" "303"
catalog=$(curl -s -u ":$pass" "http://$addr/ruuat")
check "the new main is listed, sentence-cased" "$catalog" "Uunikala"
check "a duplicate name is refused" \
"$(curl -s -u ":$pass" -d 'nimi=UUNIKALA&kategoria=fish' "http://$addr/ruuat/paaruoka")" \
"Nimi on jo listalla."
check "a main with no category is refused" \
"$(curl -s -u ":$pass" -d 'nimi=Kategoriaton' "http://$addr/ruuat/paaruoka")" \
"Valitse vähintään yksi kategoria."
check "a nameless dish is refused" \
"$(curl -s -u ":$pass" -d 'nimi=+++&kategoria=fish' "http://$addr/ruuat/paaruoka")" \
"Anna nimi."
check "adding a side redirects" \
"$(curl -s -o /dev/null -w '%{http_code}' -u ":$pass" \
-d 'nimi=lohkoperunat' "http://$addr/ruuat/lisuke")" "303"
check "the new side is listed" \
"$(curl -s -u ":$pass" "http://$addr/ruuat")" "Lohkoperunat"
uusi=$(printf '%s' "$catalog" | grep -o 'muokkaa=[0-9]*' | head -n1 | cut -d= -f2)
check "the edit form is prefilled" \
"$(curl -s -u ":$pass" "http://$addr/ruuat?muokkaa=$uusi")" "Muokkaa pääruokaa"
check "deleting a main redirects" \
"$(curl -s -o /dev/null -w '%{http_code}' -u ":$pass" \
-d "id=$uusi&tyyppi=paa" "http://$addr/ruuat/poista")" "303"
if [ "$fail" -ne 0 ]; then
echo "smoke: FAILED"
exit 1
fi
echo "smoke: all passed"