Files
content-factory/tests/smoke/plan-flow.sh
T

123 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
COMPOSE_FILE="${ROOT_DIR}/docker-compose.yml"
BACKEND_URL="${BACKEND_URL:-http://localhost:8000}"
WAIT_SECONDS="${WAIT_SECONDS:-60}"
PYTHON_BIN="${PYTHON_BIN:-python3}"
EDITOR_EMAIL="${EDITOR_EMAIL:-editor@example.com}"
cleanup() {
docker compose -f "${COMPOSE_FILE}" down --remove-orphans >/dev/null 2>&1 || true
}
request() {
local method="$1"
local path="$2"
local body="${3:-}"
if [[ -n "${body}" ]]; then
curl -fsS -X "${method}" -H "Content-Type: application/json" \
-H "X-Demo-User-Email: ${EDITOR_EMAIL}" --data "${body}" "${BACKEND_URL}${path}"
return
fi
curl -fsS -X "${method}" -H "X-Demo-User-Email: ${EDITOR_EMAIL}" "${BACKEND_URL}${path}"
}
wait_backend() {
local deadline=$((SECONDS + WAIT_SECONDS))
while (( SECONDS < deadline )); do
if curl -fsS "${BACKEND_URL}/health" >/dev/null 2>&1; then
return 0
fi
sleep 1
done
echo "Timed out waiting for backend at ${BACKEND_URL}" >&2
return 1
}
json_eval() {
local expression="$1"
"${PYTHON_BIN}" -c "import json,sys; print(${expression})"
}
cd "${ROOT_DIR}"
trap cleanup EXIT
docker compose -f "${COMPOSE_FILE}" up --build -d
wait_backend
sites_json="$(request GET /api/sites)"
site_id="$(printf '%s' "${sites_json}" | json_eval "json.load(sys.stdin)[0]['site']['id']")"
article_body="$(
SITE_ID="${site_id}" "${PYTHON_BIN}" - <<'PY'
import json
import os
import uuid
print(json.dumps({
"target_site_id": os.environ["SITE_ID"],
"brief_description": f"Plan smoke flow {uuid.uuid4()}",
"working_title": "Plan Smoke Flow",
"content_type": "longform_guide",
"primary_keyword": "plan smoke flow",
}))
PY
)"
article_json="$(request POST /api/articles "${article_body}")"
article_id="$(printf '%s' "${article_json}" | json_eval "json.load(sys.stdin)['article']['id']")"
questions_json="$(request POST "/api/articles/${article_id}/boundary-questions/generate")"
question_patch_commands="$(
QUESTIONS_JSON="${questions_json}" "${PYTHON_BIN}" - <<'PY'
import json
import os
payload = json.loads(os.environ["QUESTIONS_JSON"])
for question in payload["questions"]:
if question["is_required"]:
print(f"{question['id']}\tAccepted answer for {question['category']}.")
PY
)"
while IFS=$'\t' read -r question_id answer; do
[[ -z "${question_id}" ]] && continue
patch_body="$(ANSWER="${answer}" "${PYTHON_BIN}" - <<'PY'
import json
import os
print(json.dumps({"answer": os.environ["ANSWER"]}))
PY
)"
request PATCH "/api/articles/${article_id}/boundary-questions/${question_id}" "${patch_body}" >/dev/null
done <<< "${question_patch_commands}"
request POST "/api/articles/${article_id}/boundary-questions/submit" >/dev/null
plan_json="$(request POST "/api/articles/${article_id}/plan/generate")"
plan_id="$(printf '%s' "${plan_json}" | json_eval "json.load(sys.stdin)['plan']['id']")"
edit_body="$("${PYTHON_BIN}" - <<'PY'
import json
print(json.dumps({
"recommended_title": "Edited smoke plan",
"tone": "Direct",
"audience": "Editors",
"seo_notes": ["Smoke keyword"],
}))
PY
)"
edited_json="$(request PATCH "/api/articles/${article_id}/plans/${plan_id}" "${edit_body}")"
edited_plan_id="$(printf '%s' "${edited_json}" | json_eval "json.load(sys.stdin)['plan']['id']")"
request POST "/api/articles/${article_id}/plans/${edited_plan_id}/request-revision" '{"notes":"Smoke revision"}' >/dev/null
request POST "/api/articles/${article_id}/plans/${edited_plan_id}/approve" >/dev/null
research_json="$(request POST "/api/articles/${article_id}/research/start")"
job_type="$(printf '%s' "${research_json}" | json_eval "json.load(sys.stdin)['job']['job_type']")"
if [[ "${job_type}" != "RESEARCH" ]]; then
echo "Expected RESEARCH job, got ${job_type}" >&2
exit 1
fi
echo "plan flow smoke ok"