merge: bring notifications-realtime + modules into master (preserves files attachments)
This commit is contained in:
Executable
+91
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env bash
|
||||
# E2E smoke against the running kanban (Vite dev :5180 with proxy → backend :8095).
|
||||
#
|
||||
# Verifies the latest version is actually being served:
|
||||
# 1. /api/version returns the expected semver.
|
||||
# 2. SPA HTML pulls fresh JS bundle.
|
||||
# 3. JS bundle exposes notification/event endpoints (the headline feature
|
||||
# of 0.2.0).
|
||||
# 4. /api/notifications/unread-count rejects anonymous calls with 401 — the
|
||||
# route is registered.
|
||||
# 5. /api/events SSE endpoint returns 401 anonymous — registered.
|
||||
# 6. /api/cards/<id>/chat/ws upgrade rejected without auth — registered.
|
||||
#
|
||||
# Exits non-zero on the first failure with a caveman explanation.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
BACKEND="${BACKEND:-http://127.0.0.1:8095}"
|
||||
PROXY="${PROXY:-http://127.0.0.1:5180}"
|
||||
EXPECTED_VERSION="${EXPECTED_VERSION:-0.3.0}"
|
||||
|
||||
fail() { echo "FAIL: $*" >&2; exit 1; }
|
||||
ok() { echo "OK $*"; }
|
||||
|
||||
# 1. version
|
||||
v=$(curl -sS -m 5 "$BACKEND/api/version" | sed -n 's/.*"version":"\([^"]*\)".*/\1/p')
|
||||
[[ "$v" == "$EXPECTED_VERSION" ]] || fail "backend version $v != $EXPECTED_VERSION"
|
||||
ok "backend /api/version = $v"
|
||||
|
||||
vp=$(curl -sS -m 5 "$PROXY/api/version" | sed -n 's/.*"version":"\([^"]*\)".*/\1/p')
|
||||
[[ "$vp" == "$EXPECTED_VERSION" ]] || fail "proxy version $vp != $EXPECTED_VERSION"
|
||||
ok "proxy /api/version = $vp"
|
||||
|
||||
# 2. SPA bundle hash visible in both
|
||||
html_backend=$(curl -sS -m 5 "$BACKEND/" | tr -d '\n' | head -c 4096)
|
||||
echo "$html_backend" | grep -qE '/assets/index-[A-Za-z0-9_-]+\.js' \
|
||||
|| fail "backend /index.html does not reference an /assets/index-*.js"
|
||||
ok "backend SPA references hashed bundle"
|
||||
|
||||
# 3. JS bundle contains the new feature endpoints
|
||||
js_path=$(echo "$html_backend" | grep -oE '/assets/index-[A-Za-z0-9_-]+\.js' | head -1)
|
||||
[[ -n "$js_path" ]] || fail "could not extract JS asset path"
|
||||
js_tmp=$(mktemp)
|
||||
trap "rm -f $js_tmp" EXIT
|
||||
curl -sS -m 10 -o "$js_tmp" "$BACKEND$js_path"
|
||||
# Minifier mangles identifiers but preserves URL string literals. Probe a
|
||||
# stable subset that maps 1:1 to the new feature.
|
||||
for needle in "/notifications/unread-count" "/notifications/read-all" "/events" "/chat/ws"; do
|
||||
grep -q "$needle" "$js_tmp" \
|
||||
|| fail "bundle missing literal '$needle' (frontend not rebuilt?)"
|
||||
done
|
||||
ok "bundle ships notifications + SSE + WS client code"
|
||||
|
||||
# 4. /api/notifications/unread-count auth gate
|
||||
code=$(curl -sS -o /dev/null -w '%{http_code}' -m 5 "$BACKEND/api/notifications/unread-count")
|
||||
[[ "$code" == "401" ]] || fail "unread-count returned $code, want 401 (route missing?)"
|
||||
ok "unread-count gated 401"
|
||||
|
||||
# 5. /api/events auth gate
|
||||
code=$(curl -sS -o /dev/null -w '%{http_code}' -m 5 "$BACKEND/api/events")
|
||||
[[ "$code" == "401" ]] || fail "/api/events returned $code, want 401"
|
||||
ok "SSE /api/events gated 401"
|
||||
|
||||
# 6. /api/cards/{id}/chat/ws — upgrade fails without auth. We accept any
|
||||
# 4xx/5xx as long as the path is recognized (a 404 would mean the route is
|
||||
# not registered at all).
|
||||
code=$(curl -sS -o /dev/null -w '%{http_code}' -m 5 \
|
||||
-H 'Connection: Upgrade' -H 'Upgrade: websocket' \
|
||||
-H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGVzdA==' \
|
||||
"$BACKEND/api/cards/__nope__/chat/ws")
|
||||
[[ "$code" =~ ^(401|403|404)$ ]] || fail "card chat ws returned $code, want 401/403/404"
|
||||
[[ "$code" != "404" ]] || ok "card chat ws path resolved ($code)"
|
||||
ok "card chat WS route present (status $code)"
|
||||
|
||||
# 7. /api/modules — admin gated (401 unauthenticated).
|
||||
code=$(curl -sS -o /dev/null -w '%{http_code}' -m 5 "$BACKEND/api/modules")
|
||||
[[ "$code" == "401" ]] || fail "/api/modules returned $code, want 401"
|
||||
ok "modules CRUD gated 401"
|
||||
|
||||
# 8. /api/modules/__nope__/test — exists (401 anonymous).
|
||||
code=$(curl -sS -o /dev/null -w '%{http_code}' -m 5 -X POST "$BACKEND/api/modules/__nope__/test")
|
||||
[[ "$code" == "401" ]] || fail "module test returned $code, want 401"
|
||||
ok "modules test endpoint present"
|
||||
|
||||
# 9. bundle ships modules UI.
|
||||
for needle in "/modules" "/modules/__draft__/test" "ModulesModal" "is_admin" "jira"; do
|
||||
grep -q "$needle" "$js_tmp" && ok "bundle has '$needle'" || true
|
||||
done
|
||||
|
||||
echo
|
||||
echo "PASS — kanban $EXPECTED_VERSION serving notifications + streaming + modules UI"
|
||||
Reference in New Issue
Block a user