121 lines
4.8 KiB
Bash
Executable File
121 lines
4.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
APP_URL="${APP_URL:-http://localhost:52080}"
|
|
BACKEND_URL="${BACKEND_URL:-http://localhost:52000}"
|
|
ADMIN_BACKEND_URL="${ADMIN_BACKEND_URL:-http://localhost:52800}"
|
|
ADMIN_AUTH="${ADMIN_AUTH:-admin:admin}"
|
|
SMOKE_AUDIO="${SMOKE_AUDIO:-0}"
|
|
|
|
COOKIE_JAR="$(mktemp "${TMPDIR:-/tmp}/dreamweaver-cookie.XXXXXX")"
|
|
cleanup() {
|
|
rm -f "$COOKIE_JAR"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
need_cmd() {
|
|
if ! command -v "$1" >/dev/null 2>&1; then
|
|
echo "Missing required command: $1" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
need_cmd curl
|
|
need_cmd jq
|
|
|
|
say() {
|
|
printf '\n[%s] %s\n' "$(date '+%H:%M:%S')" "$*"
|
|
}
|
|
|
|
post_json() {
|
|
local url="$1"
|
|
local payload="$2"
|
|
curl -fsS -b "$COOKIE_JAR" -H 'Content-Type: application/json' -d "$payload" "$url"
|
|
}
|
|
|
|
get_json() {
|
|
local url="$1"
|
|
curl -fsS -b "$COOKIE_JAR" "$url"
|
|
}
|
|
|
|
assert_jq() {
|
|
local json="$1"
|
|
local filter="$2"
|
|
local message="$3"
|
|
if ! jq -e "$filter" >/dev/null <<<"$json"; then
|
|
echo "Assertion failed: $message" >&2
|
|
echo "$json" | jq '.' >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
say "Checking backend health"
|
|
curl -fsS "$BACKEND_URL/health" | jq -e '.status == "ok"' >/dev/null
|
|
curl -fsS "$ADMIN_BACKEND_URL/health" | jq -e '.status == "ok"' >/dev/null
|
|
|
|
say "Logging in with dev auth"
|
|
curl -fsS -c "$COOKIE_JAR" -o /dev/null -L "$APP_URL/auth/dev/signin"
|
|
session_json="$(get_json "$APP_URL/auth/session")"
|
|
assert_jq "$session_json" '.user.id == "github:dev_user_001"' "dev session should be active"
|
|
|
|
say "Checking provider capability policy"
|
|
capabilities_json="$(curl -fsS -u "$ADMIN_AUTH" "$ADMIN_BACKEND_URL/admin/providers/capabilities")"
|
|
assert_jq "$capabilities_json" 'map(.capability) | sort == ["image","storybook","text","tts"]' "capabilities should include text/image/tts/storybook"
|
|
|
|
say "Generating text story without assets"
|
|
story_json="$(post_json "$APP_URL/api/generations" '{
|
|
"output_mode": "story",
|
|
"type": "keywords",
|
|
"data": "金色书签, 小鹿, 学会复盘",
|
|
"education_theme": "复盘与成长",
|
|
"generate_images": false
|
|
}')"
|
|
story_id="$(jq -r '.id' <<<"$story_json")"
|
|
assert_jq "$story_json" '.mode == "generated" and .generation_status == "narrative_ready"' "story should be readable before assets"
|
|
echo "$story_json" | jq '{id,title,mode,generation_status,image_status,audio_status}'
|
|
|
|
say "Retrying story cover image"
|
|
story_image_json="$(post_json "$APP_URL/api/generations/$story_id/retry-assets" '{"assets":["image"]}')"
|
|
assert_jq "$story_image_json" '.image_status == "ready" and (.image_url != null)' "story cover should be ready after retry"
|
|
echo "$story_image_json" | jq '{id,title,generation_status,image_status,audio_status}'
|
|
|
|
if [[ "$SMOKE_AUDIO" == "1" ]]; then
|
|
say "Retrying story audio"
|
|
story_audio_json="$(post_json "$APP_URL/api/generations/$story_id/retry-assets" '{"assets":["audio"]}')"
|
|
assert_jq "$story_audio_json" '.audio_status == "ready"' "story audio should be ready after retry"
|
|
audio_probe="$(curl -fsS -b "$COOKIE_JAR" -o /tmp/dreamweaver-smoke-audio.mp3 -w '%{http_code} %{content_type} %{size_download}' "$APP_URL/api/audio/$story_id")"
|
|
if [[ "$audio_probe" != 200\ audio/mpeg* ]]; then
|
|
echo "Unexpected audio response: $audio_probe" >&2
|
|
exit 1
|
|
fi
|
|
echo "$story_audio_json" | jq '{id,title,generation_status,image_status,audio_status}'
|
|
else
|
|
say "Skipping audio smoke; set SMOKE_AUDIO=1 to include TTS"
|
|
fi
|
|
|
|
say "Generating storybook without images"
|
|
storybook_json="$(post_json "$APP_URL/api/generations" '{
|
|
"output_mode": "storybook",
|
|
"type": "keywords",
|
|
"data": "彩虹邮局, 小刺猬, 练习说谢谢",
|
|
"education_theme": "感恩表达",
|
|
"generate_images": false,
|
|
"page_count": 6
|
|
}')"
|
|
storybook_id="$(jq -r '.id' <<<"$storybook_json")"
|
|
assert_jq "$storybook_json" '.mode == "storybook" and .image_status == "not_requested" and (.pages | length) >= 4' "storybook should be readable before images"
|
|
echo "$storybook_json" | jq '{id,title,mode,generation_status,image_status,audio_status,pages:(.pages | length)}'
|
|
|
|
say "Retrying storybook images"
|
|
storybook_image_json="$(post_json "$APP_URL/api/generations/$storybook_id/retry-assets" '{"assets":["image"]}')"
|
|
assert_jq "$storybook_image_json" '.image_status == "ready" and (.pages | length) >= 4 and ([.pages[] | select(.image_url != null)] | length) == (.pages | length)' "storybook images should be ready after retry"
|
|
echo "$storybook_image_json" | jq '{id,title,generation_status,image_status,audio_status,pages:(.pages | length), ready_pages:([.pages[] | select(.image_url != null)] | length)}'
|
|
|
|
say "Checking story list"
|
|
list_json="$(get_json "$APP_URL/api/stories?limit=5")"
|
|
assert_jq "$list_json" "map(.id) | index($story_id) != null" "story list should include generated story"
|
|
assert_jq "$list_json" "map(.id) | index($storybook_id) != null" "story list should include generated storybook"
|
|
echo "$list_json" | jq '.[] | {id,title,mode,generation_status,image_status,audio_status}'
|
|
|
|
say "DreamWeaver demo smoke passed"
|