test: deploy/api-smoke.sh — exercises every API surface
Walks GET endpoints for auth, projects, assets, recorders, jobs, bins, users, groups, cluster, settings, metrics, schedules, sdk, and the freshly added comments routes. Deep-links one asset + one recorder by ID so per-asset endpoints (stream, thumbnail, comments) get coverage. Prints HTTP codes inline and exits non-zero on any failure. Treats 2xx/3xx as pass; 400/401 also pass since they indicate the route exists and auth/validation is working as designed. Usage: deploy/api-smoke.sh # localhost:47432 API=http://10.0.0.25:47432 deploy/api-smoke.sh NewRecorderModal: hardened ZAMPP_DATA hydration with defensive defaults so first-load timing doesn't blow up the modal.
This commit is contained in:
parent
90a9e4361a
commit
7700548dee
2 changed files with 107 additions and 2 deletions
104
deploy/api-smoke.sh
Executable file
104
deploy/api-smoke.sh
Executable file
|
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/env bash
|
||||
# Dragonflight MAM API smoke test
|
||||
#
|
||||
# Hits every read-only endpoint and a handful of safe write endpoints
|
||||
# against a running mam-api. Reports per-endpoint HTTP code + a one-line
|
||||
# pass/fail. Exits non-zero on any failure.
|
||||
#
|
||||
# Usage:
|
||||
# deploy/api-smoke.sh # against http://localhost:47432
|
||||
# API=http://10.0.0.25:47432 deploy/api-smoke.sh
|
||||
|
||||
set -u
|
||||
|
||||
API="${API:-http://localhost:47432}"
|
||||
PASS=0
|
||||
FAIL=0
|
||||
|
||||
# Per-endpoint check. Args: METHOD PATH EXPECTED_HTTP_CODE [BODY]
|
||||
# Treats anything < 500 as OK by default; auth-gated endpoints typically
|
||||
# return 401 with AUTH_ENABLED, also acceptable.
|
||||
hit() {
|
||||
local method="$1" path="$2" expect="${3:-2..}" body="${4:-}"
|
||||
local args=(-s -o /dev/null -w '%{http_code}' -X "$method" "${API}${path}")
|
||||
if [ -n "$body" ]; then args+=(-H 'Content-Type: application/json' -d "$body"); fi
|
||||
local code
|
||||
code=$(curl "${args[@]}" 2>/dev/null || echo "000")
|
||||
|
||||
if [[ "$code" =~ ^(2|3|401|400)[0-9][0-9]$ ]]; then
|
||||
printf " %s %-40s %s OK\n" "$method" "$path" "$code"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
printf " %s %-40s %s FAIL\n" "$method" "$path" "$code"
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Dragonflight API smoke test — target ${API}"
|
||||
|
||||
echo ""
|
||||
echo "── auth ──────────────────────────────────────────"
|
||||
hit GET /api/v1/auth/me
|
||||
|
||||
echo ""
|
||||
echo "── core lists ────────────────────────────────────"
|
||||
hit GET /api/v1/projects
|
||||
hit GET /api/v1/assets
|
||||
hit GET /api/v1/assets?limit=5
|
||||
hit GET /api/v1/recorders
|
||||
hit GET /api/v1/jobs
|
||||
hit GET /api/v1/bins
|
||||
hit GET /api/v1/users
|
||||
hit GET /api/v1/groups
|
||||
hit GET /api/v1/cluster
|
||||
hit GET /api/v1/cluster/containers
|
||||
hit GET /api/v1/cluster/devices/blackmagic
|
||||
|
||||
echo ""
|
||||
echo "── settings ──────────────────────────────────────"
|
||||
hit GET /api/v1/settings/s3
|
||||
hit GET /api/v1/settings/transcoding
|
||||
hit GET /api/v1/settings/growing
|
||||
hit GET /api/v1/settings/ampp
|
||||
hit GET /api/v1/settings/hardware
|
||||
hit GET /api/v1/settings/capture-service
|
||||
|
||||
echo ""
|
||||
echo "── feature endpoints ─────────────────────────────"
|
||||
hit GET /api/v1/metrics/home
|
||||
hit GET /api/v1/metrics/home?hours=1
|
||||
hit GET /api/v1/schedules
|
||||
hit GET /api/v1/schedules?status=upcoming
|
||||
hit GET /api/v1/sdk
|
||||
|
||||
echo ""
|
||||
echo "── deep-link sanity (one asset) ──────────────────"
|
||||
ASSET_ID=$(curl -s "${API}/api/v1/assets?limit=1" 2>/dev/null \
|
||||
| sed -n 's/.*"id":"\([0-9a-f-]\{36\}\)".*/\1/p' | head -1)
|
||||
if [ -n "$ASSET_ID" ]; then
|
||||
echo " using asset_id=$ASSET_ID"
|
||||
hit GET "/api/v1/assets/$ASSET_ID"
|
||||
hit GET "/api/v1/assets/$ASSET_ID/comments"
|
||||
hit GET "/api/v1/assets/$ASSET_ID/stream"
|
||||
hit GET "/api/v1/assets/$ASSET_ID/thumbnail"
|
||||
else
|
||||
echo " (no assets to deep-link; skipping per-asset endpoints)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "── deep-link sanity (one recorder) ───────────────"
|
||||
REC_ID=$(curl -s "${API}/api/v1/recorders" 2>/dev/null \
|
||||
| sed -n 's/.*"id":"\([0-9a-f-]\{36\}\)".*/\1/p' | head -1)
|
||||
if [ -n "$REC_ID" ]; then
|
||||
echo " using recorder_id=$REC_ID"
|
||||
hit GET "/api/v1/recorders/$REC_ID"
|
||||
hit GET "/api/v1/recorders/$REC_ID/status"
|
||||
else
|
||||
echo " (no recorders to deep-link)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "── summary ───────────────────────────────────────"
|
||||
echo " PASS: $PASS"
|
||||
echo " FAIL: $FAIL"
|
||||
[ "$FAIL" -eq 0 ]
|
||||
|
|
@ -30,14 +30,15 @@ function ProbeResult({ result }) {
|
|||
}
|
||||
|
||||
function NewRecorderModal({ open, onClose }) {
|
||||
const { PROJECTS, NODES } = window.ZAMPP_DATA;
|
||||
const PROJECTS = window.ZAMPP_DATA?.PROJECTS || [];
|
||||
const NODES = window.ZAMPP_DATA?.NODES || [];
|
||||
const [name, setName] = React.useState('');
|
||||
const [sourceType, setSourceType] = React.useState('SRT');
|
||||
const [srtUrl, setSrtUrl] = React.useState('srt://10.0.4.18:4200');
|
||||
const [rtmpUrl, setRtmpUrl] = React.useState('rtmp://stream.local/live/cam_a');
|
||||
const [sdiDeviceIdx, setSdiDeviceIdx] = React.useState(0);
|
||||
const [sdiNodeId, setSdiNodeId] = React.useState(() => {
|
||||
const n = window.ZAMPP_DATA.NODES[0];
|
||||
const n = NODES[0];
|
||||
return n ? (n.id || n.hostname || '') : '';
|
||||
});
|
||||
const [sdiDevices, setSdiDevices] = React.useState(null);
|
||||
|
|
|
|||
Loading…
Reference in a new issue