test(backend): split smoke regression into core and pricing publish flows

separate smoke coverage into core backend checks and pricing publish flow checks

make regression runs more focused and easier to maintain
improve troubleshooting when a smoke stage fails
This commit is contained in:
greebo
2026-03-20 13:25:32 +03:00
parent 239b32a246
commit 210981c953
5 changed files with 746 additions and 249 deletions

View File

@@ -0,0 +1,133 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "${TMP_DIR}"' EXIT
# shellcheck source=backend/scripts/smoke_common.sh
source "${SCRIPT_DIR}/smoke_common.sh"
wait_for_health
request "ping" "GET" "${API_URL}/api/v1/ping" "200"
request "db_ping" "GET" "${API_URL}/api/v1/db/ping" "200"
request "manifest" "GET" "${API_URL}/api/v1/manifest" "200"
create_fresh_scheme_from_upload "smoke-core"
request "scheme_detail" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}" "200"
assert_json_eq "${TMP_DIR}/scheme_detail.body" "scheme_id" "${SCHEME_ID}"
assert_json_eq "${TMP_DIR}/scheme_detail.body" "name" "${FRESH_SCHEME_NAME}"
assert_json_eq "${TMP_DIR}/scheme_detail.body" "status" "draft"
request "scheme_versions" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/versions?limit=20&offset=0" "200"
assert_json_len_eq "${TMP_DIR}/scheme_versions.body" "items" "1"
request "scheme_current" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/current" "200"
CURRENT_VERSION_ID="$(json_get "${TMP_DIR}/scheme_current.body" "scheme_version_id")"
CURRENT_STATUS="$(json_get "${TMP_DIR}/scheme_current.body" "status")"
echo "CURRENT_VERSION_ID=${CURRENT_VERSION_ID}"
echo "CURRENT_STATUS=${CURRENT_STATUS}"
assert_json_eq "${TMP_DIR}/scheme_current.body" "status" "draft"
request "editor_context" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/editor/context" "200"
assert_json_eq "${TMP_DIR}/editor_context.body" "current_scheme_version_id" "${CURRENT_VERSION_ID}"
assert_json_eq "${TMP_DIR}/editor_context.body" "current_is_draft" "true"
request "ensure_draft" "POST" "${API_URL}/api/v1/schemes/${SCHEME_ID}/draft/ensure" "200"
DRAFT_VERSION_ID="$(json_get "${TMP_DIR}/ensure_draft.body" "scheme_version_id")"
DRAFT_CREATED="$(json_get "${TMP_DIR}/ensure_draft.body" "created")"
echo "DRAFT_VERSION_ID=${DRAFT_VERSION_ID}"
echo "DRAFT_CREATED=${DRAFT_CREATED}"
assert_json_eq "${TMP_DIR}/ensure_draft.body" "scheme_version_id" "${CURRENT_VERSION_ID}"
assert_json_eq "${TMP_DIR}/ensure_draft.body" "created" "false"
request "draft_summary" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/draft/summary?expected_scheme_version_id=${DRAFT_VERSION_ID}" "200"
request "draft_structure" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/draft/structure?expected_scheme_version_id=${DRAFT_VERSION_ID}" "200"
request "draft_validation" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/draft/validation?expected_scheme_version_id=${DRAFT_VERSION_ID}" "200"
request "draft_compare_preview" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/draft/compare-preview?expected_scheme_version_id=${DRAFT_VERSION_ID}" "200"
assert_json_eq "${TMP_DIR}/draft_summary.body" "scheme_version_id" "${DRAFT_VERSION_ID}"
assert_json_eq "${TMP_DIR}/draft_structure.body" "scheme_version_id" "${DRAFT_VERSION_ID}"
assert_json_eq "${TMP_DIR}/draft_validation.body" "scheme_version_id" "${DRAFT_VERSION_ID}"
assert_json_eq "${TMP_DIR}/draft_compare_preview.body" "draft_scheme_version_id" "${DRAFT_VERSION_ID}"
TOTAL_SEATS="$(json_get "${TMP_DIR}/draft_summary.body" "total_seats")"
echo "TOTAL_SEATS=${TOTAL_SEATS}"
read -r SEAT_RECORD_ID SECTOR_RECORD_ID GROUP_RECORD_ID EXPLAIN_SEAT_ID <<EOF
$(python3 - "${TMP_DIR}/draft_structure.body" <<'PY'
import json
import sys
from pathlib import Path
payload = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
seats = payload.get("seats", [])
sectors = payload.get("sectors", [])
groups = payload.get("groups", [])
seat_with_id = next((seat for seat in seats if seat.get("seat_id")), None)
if seat_with_id is None:
raise SystemExit("No seat with seat_id found in fresh draft structure")
print(
seat_with_id["seat_record_id"],
sectors[0]["sector_record_id"],
groups[0]["group_record_id"],
seat_with_id["seat_id"],
)
PY
)
EOF
echo "SEAT_RECORD_ID=${SEAT_RECORD_ID}"
echo "SECTOR_RECORD_ID=${SECTOR_RECORD_ID}"
echo "GROUP_RECORD_ID=${GROUP_RECORD_ID}"
echo "EXPLAIN_SEAT_ID=${EXPLAIN_SEAT_ID}"
request "stale_draft_conflict" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/draft/summary?expected_scheme_version_id=deadbeefdeadbeefdeadbeefdeadbeef" "409"
assert_json_eq "${TMP_DIR}/stale_draft_conflict.body" "detail.code" "stale_draft_version"
request "draft_seat_record" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/draft/seats/records/${SEAT_RECORD_ID}?expected_scheme_version_id=${DRAFT_VERSION_ID}" "200"
request "draft_sector_record" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/draft/sectors/records/${SECTOR_RECORD_ID}?expected_scheme_version_id=${DRAFT_VERSION_ID}" "200"
request "draft_group_record" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/draft/groups/records/${GROUP_RECORD_ID}?expected_scheme_version_id=${DRAFT_VERSION_ID}" "200"
request "draft_unknown_record" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/draft/seats/records/deadbeefdeadbeefdeadbeefdeadbeef" "404"
request "current_sectors" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/current/sectors" "200"
request "current_groups" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/current/groups" "200"
request "current_seats" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/current/seats" "200"
request "display_meta" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/current/svg/display/meta" "200"
request "pricing_bundle" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/pricing" "200"
assert_json_len_eq "${TMP_DIR}/pricing_bundle.body" "categories" "0"
assert_json_len_eq "${TMP_DIR}/pricing_bundle.body" "rules" "0"
request "pricing_coverage" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/pricing/coverage" "200"
assert_json_int_eq "${TMP_DIR}/pricing_coverage.body" "priced_seats" "0"
assert_json_int_eq "${TMP_DIR}/pricing_coverage.body" "unpriced_seats" "${TOTAL_SEATS}"
request "pricing_unpriced" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/pricing/unpriced-seats" "200"
assert_json_int_eq "${TMP_DIR}/pricing_unpriced.body" "total" "${TOTAL_SEATS}"
request "pricing_explain_empty" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/pricing/explain/${EXPLAIN_SEAT_ID}" "200"
assert_json_eq "${TMP_DIR}/pricing_explain_empty.body" "has_price" "false"
assert_json_eq "${TMP_DIR}/pricing_explain_empty.body" "reason_code" "no_price_rule"
request "pricing_rule_diagnostics" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/pricing/rules/diagnostics" "200"
assert_json_int_eq "${TMP_DIR}/pricing_rule_diagnostics.body" "summary.total_rules" "0"
assert_json_int_eq "${TMP_DIR}/pricing_rule_diagnostics.body" "summary.active_rules_count" "0"
assert_json_int_eq "${TMP_DIR}/pricing_rule_diagnostics.body" "summary.matched_seats_total" "0"
assert_json_len_eq "${TMP_DIR}/pricing_rule_diagnostics.body" "items" "0"
request "audit_trail" "GET" "${API_URL}/api/v1/schemes/${SCHEME_ID}/audit" "200"
assert_json_int_ge "${TMP_DIR}/audit_trail.body" "total" "0"
log "editor mutation regression"
API_URL="${API_URL}" API_KEY="${API_KEY}" SCHEME_ID="${SCHEME_ID}" \
bash "${SCRIPT_DIR}/editor_mutation_regression.sh"
echo
echo "===== done ====="
echo "[OK] smoke core completed successfully"
echo "FRESH_SCHEME_ID=${SCHEME_ID}"