test(frontend): add provider admin acceptance coverage
Add a dedicated acceptance script for providers.html, cover it in the local real-host script regression suite, and document the current frontend review baseline, closure audit, providers action matrix, and remediation task board. This keeps the frontend acceptance boundary explicit: providers.html now has a repeatable verification entry point for its page-level actions, while non-UI provider operations remain documented as backend-only capabilities.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
- 例如:
|
||||
- `real_host_acceptance.sh`
|
||||
- `import_remote43_provider.sh`
|
||||
- `verify_provider_admin_actions.sh`
|
||||
- `check_deepseek_completion_split.sh`
|
||||
- `scripts/test/`
|
||||
- 脚本自身的回归与资产检查
|
||||
@@ -42,6 +43,7 @@ bash ./scripts/test/test_tksea_portal_assets.sh
|
||||
bash ./scripts/test/verify_quality_gates.sh
|
||||
scripts/deploy/build_local_image.sh
|
||||
bash ./scripts/acceptance/real_host_acceptance.sh
|
||||
bash ./scripts/acceptance/verify_provider_admin_actions.sh
|
||||
```
|
||||
|
||||
## 统一质量门禁
|
||||
|
||||
378
scripts/acceptance/verify_provider_admin_actions.sh
Executable file
378
scripts/acceptance/verify_provider_admin_actions.sh
Executable file
@@ -0,0 +1,378 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
# shellcheck disable=SC1091
|
||||
source "$ROOT_DIR/scripts/acceptance/route_acceptance_lib.sh"
|
||||
|
||||
PROVIDER_ADMIN_ROOT="${PROVIDER_ADMIN_ROOT:-$ROOT_DIR/artifacts/provider-admin-matrix}"
|
||||
PROVIDER_ADMIN_PAGE_URL="${PROVIDER_ADMIN_PAGE_URL:-https://sub.tksea.top/portal/admin/providers.html}"
|
||||
TS="${TS:-$(timestamp_token)}"
|
||||
ARTIFACT_DIR="${ARTIFACT_DIR:-$PROVIDER_ADMIN_ROOT/${TS}_provider_admin_actions}"
|
||||
|
||||
PACK_ID="${PACK_ID:-}"
|
||||
HOST_ID="${HOST_ID:-}"
|
||||
PACK_PATH="${PACK_PATH:-}"
|
||||
PROVIDER_ID="${PROVIDER_ID:-}"
|
||||
MODE="${MODE:-partial}"
|
||||
ACCESS_MODE="${ACCESS_MODE:-self_service}"
|
||||
ACCESS_API_KEY="${ACCESS_API_KEY:-}"
|
||||
PROVIDER_KEYS="${PROVIDER_KEYS:-}"
|
||||
SUBSCRIPTION_USERS="${SUBSCRIPTION_USERS:-}"
|
||||
SUBSCRIPTION_DAYS="${SUBSCRIPTION_DAYS:-30}"
|
||||
VERIFY_PUBLISH="${VERIFY_PUBLISH:-0}"
|
||||
|
||||
crud_provider_id="${CRUD_PROVIDER_ID:-provider-admin-draft-$TS}"
|
||||
crud_display_name="${CRUD_DISPLAY_NAME:-Provider Admin Draft $TS}"
|
||||
crud_platform="${CRUD_PLATFORM:-openai}"
|
||||
crud_base_url="${CRUD_BASE_URL:-https://draft-$TS.example.com/v1}"
|
||||
crud_smoke_model="${CRUD_SMOKE_MODEL:-provider-admin-draft-$TS}"
|
||||
crud_supported_models="${CRUD_SUPPORTED_MODELS:-provider-admin-draft-$TS,provider-admin-draft-mini-$TS}"
|
||||
crud_notes="${CRUD_NOTES:-provider-admin draft acceptance $TS}"
|
||||
crud_updated_display_name="${CRUD_UPDATED_DISPLAY_NAME:-Provider Admin Draft Updated $TS}"
|
||||
crud_updated_base_url="${CRUD_UPDATED_BASE_URL:-https://draft-updated-$TS.example.com/v1}"
|
||||
crud_updated_smoke_model="${CRUD_UPDATED_SMOKE_MODEL:-provider-admin-draft-updated-$TS}"
|
||||
crud_updated_supported_models="${CRUD_UPDATED_SUPPORTED_MODELS:-provider-admin-draft-updated-$TS}"
|
||||
crud_updated_notes="${CRUD_UPDATED_NOTES:-provider-admin draft acceptance updated $TS}"
|
||||
|
||||
publish_provider_id="${PUBLISH_PROVIDER_ID:-provider-admin-publish-$TS}"
|
||||
publish_display_name="${PUBLISH_DISPLAY_NAME:-Provider Admin Publish $TS}"
|
||||
publish_platform="${PUBLISH_PLATFORM:-openai}"
|
||||
publish_base_url="${PUBLISH_BASE_URL:-https://publish-$TS.example.com/v1}"
|
||||
publish_smoke_model="${PUBLISH_SMOKE_MODEL:-provider-admin-publish-$TS}"
|
||||
publish_supported_models="${PUBLISH_SUPPORTED_MODELS:-provider-admin-publish-$TS}"
|
||||
publish_notes="${PUBLISH_NOTES:-provider-admin publish acceptance $TS}"
|
||||
publish_commit_message="${PUBLISH_COMMIT_MESSAGE:-feat(pack): publish provider admin draft $publish_provider_id}"
|
||||
|
||||
require_var CRM_BASE
|
||||
require_var ACCESS_API_KEY
|
||||
require_var PROVIDER_KEYS
|
||||
|
||||
crm_auth_init
|
||||
ensure_artifact_dir
|
||||
curl_status_to_file "$PROVIDER_ADMIN_PAGE_URL" "$ARTIFACT_DIR/00-provider-admin.html"
|
||||
|
||||
json_field_from_file() {
|
||||
local file="$1"
|
||||
local path="$2"
|
||||
python3 - "$file" "$path" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
file_path, path = sys.argv[1:3]
|
||||
value = json.load(open(file_path, "r", encoding="utf-8"))
|
||||
for part in path.split("."):
|
||||
if isinstance(value, dict):
|
||||
value = value.get(part)
|
||||
else:
|
||||
value = None
|
||||
break
|
||||
if value is None:
|
||||
raise SystemExit(2)
|
||||
if isinstance(value, (dict, list)):
|
||||
print(json.dumps(value, ensure_ascii=False))
|
||||
else:
|
||||
print(value)
|
||||
PY
|
||||
}
|
||||
|
||||
first_collection_field_from_file() {
|
||||
local file="$1"
|
||||
local collection="$2"
|
||||
local field="$3"
|
||||
python3 - "$file" "$collection" "$field" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
file_path, collection, field = sys.argv[1:4]
|
||||
payload = json.load(open(file_path, "r", encoding="utf-8"))
|
||||
items = payload.get(collection) or []
|
||||
if not items:
|
||||
raise SystemExit(2)
|
||||
value = items[0].get(field)
|
||||
if value in ("", None):
|
||||
raise SystemExit(2)
|
||||
print(value)
|
||||
PY
|
||||
}
|
||||
|
||||
normalize_csv_json() {
|
||||
local raw="$1"
|
||||
python3 - "$raw" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
raw = sys.argv[1]
|
||||
values = []
|
||||
for line in raw.replace("\r", "\n").split("\n"):
|
||||
for item in line.split(","):
|
||||
item = item.strip()
|
||||
if item:
|
||||
values.append(item)
|
||||
print(json.dumps(values, ensure_ascii=False))
|
||||
PY
|
||||
}
|
||||
|
||||
build_preview_payload() {
|
||||
local host_id="$1"
|
||||
local pack_path="$2"
|
||||
local provider_id="$3"
|
||||
local mode="$4"
|
||||
local keys_json="$5"
|
||||
python3 - "$host_id" "$pack_path" "$provider_id" "$mode" "$keys_json" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
host_id, pack_path, provider_id, mode, keys_json = sys.argv[1:6]
|
||||
print(json.dumps({
|
||||
"host_id": host_id,
|
||||
"pack_path": pack_path,
|
||||
"provider_id": provider_id,
|
||||
"keys": json.loads(keys_json),
|
||||
"mode": mode,
|
||||
}, ensure_ascii=False))
|
||||
PY
|
||||
}
|
||||
|
||||
build_import_payload() {
|
||||
local host_id="$1"
|
||||
local pack_path="$2"
|
||||
local provider_id="$3"
|
||||
local mode="$4"
|
||||
local access_mode="$5"
|
||||
local access_api_key="$6"
|
||||
local keys_json="$7"
|
||||
local subscription_users_json="$8"
|
||||
local subscription_days="$9"
|
||||
python3 - "$host_id" "$pack_path" "$provider_id" "$mode" "$access_mode" "$access_api_key" "$keys_json" "$subscription_users_json" "$subscription_days" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
host_id, pack_path, provider_id, mode, access_mode, access_api_key, keys_json, subscription_users_json, subscription_days = sys.argv[1:10]
|
||||
payload = {
|
||||
"host_id": host_id,
|
||||
"pack_path": pack_path,
|
||||
"provider_id": provider_id,
|
||||
"keys": json.loads(keys_json),
|
||||
"mode": mode,
|
||||
"access_mode": access_mode,
|
||||
"access_api_key": access_api_key,
|
||||
}
|
||||
if access_mode == "subscription":
|
||||
payload["subscription_users"] = json.loads(subscription_users_json)
|
||||
payload["subscription_days"] = int(subscription_days)
|
||||
print(json.dumps(payload, ensure_ascii=False))
|
||||
PY
|
||||
}
|
||||
|
||||
build_draft_payload() {
|
||||
local pack_id="$1"
|
||||
local provider_id="$2"
|
||||
local display_name="$3"
|
||||
local platform="$4"
|
||||
local base_url="$5"
|
||||
local smoke_model="$6"
|
||||
local supported_models_json="$7"
|
||||
local source_host_id="$8"
|
||||
local notes="$9"
|
||||
python3 - "$pack_id" "$provider_id" "$display_name" "$platform" "$base_url" "$smoke_model" "$supported_models_json" "$source_host_id" "$notes" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
pack_id, provider_id, display_name, platform, base_url, smoke_model, supported_models_json, source_host_id, notes = sys.argv[1:10]
|
||||
supported_models = json.loads(supported_models_json)
|
||||
manifest = {
|
||||
"provider_id": provider_id,
|
||||
"display_name": display_name,
|
||||
"platform": platform,
|
||||
"base_url": base_url,
|
||||
"smoke_test_model": smoke_model,
|
||||
"supported_models": supported_models,
|
||||
}
|
||||
print(json.dumps({
|
||||
"pack_id": pack_id,
|
||||
"provider_id": provider_id,
|
||||
"display_name": display_name,
|
||||
"platform": platform,
|
||||
"base_url": base_url,
|
||||
"smoke_test_model": smoke_model,
|
||||
"supported_models": supported_models,
|
||||
"source_host_id": source_host_id,
|
||||
"notes": notes,
|
||||
"manifest": manifest,
|
||||
}, ensure_ascii=False))
|
||||
PY
|
||||
}
|
||||
|
||||
crm_curl_status() {
|
||||
local method="$1"
|
||||
local path="$2"
|
||||
local payload="${3:-}"
|
||||
local -a curl_args
|
||||
curl_args=(-fsS -o /dev/null -w '%{http_code}' -X "$method")
|
||||
if [[ -n "${crm_token:-}" ]]; then
|
||||
curl_args+=(-H "Authorization: Bearer $crm_token")
|
||||
elif [[ -n "${crm_cookie_jar:-}" ]]; then
|
||||
curl_args+=(-b "$crm_cookie_jar" -c "$crm_cookie_jar")
|
||||
else
|
||||
echo "missing CRM auth: set CRM_ADMIN_TOKEN or CRM_ADMIN_USERNAME/CRM_ADMIN_PASSWORD" >&2
|
||||
exit 2
|
||||
fi
|
||||
if [[ -n "$payload" ]]; then
|
||||
curl_args+=(-H 'Content-Type: application/json' "${CRM_BASE%/}${path}" -d "$payload")
|
||||
else
|
||||
curl_args+=("${CRM_BASE%/}${path}")
|
||||
fi
|
||||
curl "${curl_args[@]}"
|
||||
}
|
||||
|
||||
provider_keys_json="$(normalize_csv_json "$PROVIDER_KEYS")"
|
||||
subscription_users_json="$(normalize_csv_json "$SUBSCRIPTION_USERS")"
|
||||
crud_supported_models_json="$(normalize_csv_json "$crud_supported_models")"
|
||||
crud_updated_supported_models_json="$(normalize_csv_json "$crud_updated_supported_models")"
|
||||
publish_supported_models_json="$(normalize_csv_json "$publish_supported_models")"
|
||||
|
||||
save_json 01-packs "$(crm_curl_json GET "/api/packs")"
|
||||
if [[ -z "$PACK_ID" ]]; then
|
||||
PACK_ID="$(first_collection_field_from_file "$ARTIFACT_DIR/01-packs.json" packs pack_id)"
|
||||
fi
|
||||
|
||||
save_json 02-hosts "$(crm_curl_json GET "/api/hosts")"
|
||||
if [[ -z "$HOST_ID" ]]; then
|
||||
HOST_ID="$(first_collection_field_from_file "$ARTIFACT_DIR/02-hosts.json" hosts host_id)"
|
||||
fi
|
||||
|
||||
if [[ -z "$PACK_PATH" ]]; then
|
||||
PACK_PATH="/app/packs/$PACK_ID"
|
||||
fi
|
||||
|
||||
save_json 03-pack-providers "$(crm_curl_json GET "/api/packs/$PACK_ID/providers")"
|
||||
if [[ -z "$PROVIDER_ID" ]]; then
|
||||
PROVIDER_ID="$(first_collection_field_from_file "$ARTIFACT_DIR/03-pack-providers.json" providers provider_id)"
|
||||
fi
|
||||
|
||||
preview_payload="$(build_preview_payload "$HOST_ID" "$PACK_PATH" "$PROVIDER_ID" "$MODE" "$provider_keys_json")"
|
||||
save_json 04-preview-import "$(crm_curl_json POST "/api/providers/$PROVIDER_ID/preview-import" "$preview_payload")"
|
||||
|
||||
import_payload="$(build_import_payload "$HOST_ID" "$PACK_PATH" "$PROVIDER_ID" "$MODE" "$ACCESS_MODE" "$ACCESS_API_KEY" "$provider_keys_json" "$subscription_users_json" "$SUBSCRIPTION_DAYS")"
|
||||
save_json 05-import "$(crm_curl_json POST "/api/providers/$PROVIDER_ID/import" "$import_payload")"
|
||||
|
||||
crud_create_payload="$(build_draft_payload "$PACK_ID" "$crud_provider_id" "$crud_display_name" "$crud_platform" "$crud_base_url" "$crud_smoke_model" "$crud_supported_models_json" "$HOST_ID" "$crud_notes")"
|
||||
save_json 06-create-draft "$(crm_curl_json POST "/api/provider-drafts" "$crud_create_payload")"
|
||||
crud_draft_id="$(json_field_from_file "$ARTIFACT_DIR/06-create-draft.json" draft.draft_id)"
|
||||
|
||||
save_json 07-list-drafts-before-delete "$(crm_curl_json GET "/api/provider-drafts?pack_id=$PACK_ID")"
|
||||
save_json 08-get-draft "$(crm_curl_json GET "/api/provider-drafts/$crud_draft_id")"
|
||||
|
||||
crud_update_payload="$(build_draft_payload "$PACK_ID" "$crud_provider_id" "$crud_updated_display_name" "$crud_platform" "$crud_updated_base_url" "$crud_updated_smoke_model" "$crud_updated_supported_models_json" "$HOST_ID" "$crud_updated_notes")"
|
||||
save_json 09-update-draft "$(crm_curl_json PUT "/api/provider-drafts/$crud_draft_id" "$crud_update_payload")"
|
||||
|
||||
delete_status="$(crm_curl_status DELETE "/api/provider-drafts/$crud_draft_id")"
|
||||
save_text 10-delete-draft.status "$delete_status"
|
||||
save_json 11-list-drafts-after-delete "$(crm_curl_json GET "/api/provider-drafts?pack_id=$PACK_ID")"
|
||||
|
||||
publish_verified="false"
|
||||
if [[ "$VERIFY_PUBLISH" == "1" ]]; then
|
||||
publish_create_payload="$(build_draft_payload "$PACK_ID" "$publish_provider_id" "$publish_display_name" "$publish_platform" "$publish_base_url" "$publish_smoke_model" "$publish_supported_models_json" "$HOST_ID" "$publish_notes")"
|
||||
save_json 12-create-publish-draft "$(crm_curl_json POST "/api/provider-drafts" "$publish_create_payload")"
|
||||
publish_draft_id="$(json_field_from_file "$ARTIFACT_DIR/12-create-publish-draft.json" draft.draft_id)"
|
||||
publish_payload="$(python3 - "$publish_commit_message" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
print(json.dumps({"commit_message": sys.argv[1]}, ensure_ascii=False))
|
||||
PY
|
||||
)"
|
||||
save_json 13-publish-draft "$(crm_curl_json POST "/api/provider-drafts/$publish_draft_id/publish" "$publish_payload")"
|
||||
publish_verified="true"
|
||||
fi
|
||||
|
||||
python3 - \
|
||||
"$ARTIFACT_DIR" \
|
||||
"$PACK_ID" \
|
||||
"$HOST_ID" \
|
||||
"$PACK_PATH" \
|
||||
"$PROVIDER_ID" \
|
||||
"$crud_draft_id" \
|
||||
"$crud_updated_display_name" \
|
||||
"$publish_verified" \
|
||||
"$publish_provider_id" \
|
||||
>"$ARTIFACT_DIR/99-summary.json" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
(
|
||||
artifact_dir,
|
||||
pack_id,
|
||||
host_id,
|
||||
pack_path,
|
||||
provider_id,
|
||||
crud_draft_id,
|
||||
crud_updated_display_name,
|
||||
publish_verified,
|
||||
publish_provider_id,
|
||||
) = sys.argv[1:10]
|
||||
|
||||
art = Path(artifact_dir)
|
||||
page = (art / "00-provider-admin.html").read_text(encoding="utf-8")
|
||||
packs = json.loads((art / "01-packs.json").read_text(encoding="utf-8"))
|
||||
hosts = json.loads((art / "02-hosts.json").read_text(encoding="utf-8"))
|
||||
providers = json.loads((art / "03-pack-providers.json").read_text(encoding="utf-8"))
|
||||
preview = json.loads((art / "04-preview-import.json").read_text(encoding="utf-8"))
|
||||
import_result = json.loads((art / "05-import.json").read_text(encoding="utf-8"))
|
||||
create_draft = json.loads((art / "06-create-draft.json").read_text(encoding="utf-8"))["draft"]
|
||||
list_before = json.loads((art / "07-list-drafts-before-delete.json").read_text(encoding="utf-8"))["provider_drafts"]
|
||||
get_draft = json.loads((art / "08-get-draft.json").read_text(encoding="utf-8"))["draft"]
|
||||
update_draft = json.loads((art / "09-update-draft.json").read_text(encoding="utf-8"))["draft"]
|
||||
delete_status = (art / "10-delete-draft.status").read_text(encoding="utf-8").strip()
|
||||
list_after = json.loads((art / "11-list-drafts-after-delete.json").read_text(encoding="utf-8"))["provider_drafts"]
|
||||
|
||||
assert "Provider Admin" in page
|
||||
assert packs["packs"]
|
||||
assert hosts["hosts"]
|
||||
assert providers["providers"]
|
||||
assert pack_id
|
||||
assert host_id
|
||||
assert pack_path
|
||||
assert provider_id
|
||||
assert int(preview["accepted_keys_count"]) >= 1
|
||||
assert int(import_result["batch_id"]) > 0
|
||||
assert import_result["batch_status"]
|
||||
assert create_draft["draft_id"] == crud_draft_id
|
||||
assert any(item["draft_id"] == crud_draft_id for item in list_before)
|
||||
assert get_draft["draft_id"] == crud_draft_id
|
||||
assert update_draft["display_name"] == crud_updated_display_name
|
||||
assert delete_status == "204"
|
||||
assert not any(item["draft_id"] == crud_draft_id for item in list_after)
|
||||
|
||||
summary = {
|
||||
"page_title_seen": "Provider Admin" in page,
|
||||
"pack_id": pack_id,
|
||||
"host_id": host_id,
|
||||
"pack_path": pack_path,
|
||||
"provider_id": provider_id,
|
||||
"preview_accepted_keys_count": int(preview["accepted_keys_count"]),
|
||||
"import_batch_id": int(import_result["batch_id"]),
|
||||
"import_batch_status": import_result["batch_status"],
|
||||
"crud_draft_id": crud_draft_id,
|
||||
"crud_updated_display_name": update_draft["display_name"],
|
||||
"crud_delete_status": delete_status,
|
||||
"publish_verified": publish_verified == "true",
|
||||
}
|
||||
|
||||
if publish_verified == "true":
|
||||
create_publish = json.loads((art / "12-create-publish-draft.json").read_text(encoding="utf-8"))["draft"]
|
||||
publish_result = json.loads((art / "13-publish-draft.json").read_text(encoding="utf-8"))["publish"]
|
||||
assert create_publish["provider_id"] == publish_provider_id
|
||||
assert publish_result["provider_id"] == publish_provider_id
|
||||
assert publish_result["commit_sha"]
|
||||
summary["publish_draft_id"] = create_publish["draft_id"]
|
||||
summary["publish_provider_id"] = publish_result["provider_id"]
|
||||
summary["publish_commit_sha"] = publish_result["commit_sha"]
|
||||
else:
|
||||
summary["publish_skipped_reason"] = "VERIFY_PUBLISH=0"
|
||||
|
||||
print(json.dumps(summary, ensure_ascii=False, indent=2))
|
||||
PY
|
||||
|
||||
cat "$ARTIFACT_DIR/99-summary.json"
|
||||
@@ -830,6 +830,131 @@ EOF
|
||||
assert_contains "$payloads" '"subscription_user_id": "36"'
|
||||
}
|
||||
|
||||
run_test_verify_provider_admin_actions_script() {
|
||||
local tmpdir fakebin artifact_dir state_dir stdout_file
|
||||
tmpdir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmpdir"' RETURN
|
||||
fakebin="$tmpdir/bin"
|
||||
artifact_dir="$tmpdir/artifacts"
|
||||
state_dir="$tmpdir/state"
|
||||
stdout_file="$tmpdir/verify_provider_admin_actions.stdout.txt"
|
||||
mkdir -p "$fakebin" "$artifact_dir" "$state_dir"
|
||||
|
||||
cat > "$fakebin/curl" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
method="GET"
|
||||
url=""
|
||||
payload=""
|
||||
output_file=""
|
||||
write_out=""
|
||||
prev=""
|
||||
for arg in "$@"; do
|
||||
case "$prev" in
|
||||
-X) method="$arg"; prev=""; continue ;;
|
||||
-d|--data) payload="$arg"; prev=""; continue ;;
|
||||
-o) output_file="$arg"; prev=""; continue ;;
|
||||
-w) write_out="$arg"; prev=""; continue ;;
|
||||
esac
|
||||
case "$arg" in
|
||||
-X|-d|--data|-o|-w) prev="$arg"; continue ;;
|
||||
http://*|https://*) url="$arg" ;;
|
||||
esac
|
||||
done
|
||||
state_dir="${FAKE_STATE_DIR:?missing FAKE_STATE_DIR}"
|
||||
write_body() {
|
||||
local body="$1"
|
||||
if [[ -n "$output_file" ]]; then
|
||||
printf '%s\n' "$body" > "$output_file"
|
||||
else
|
||||
printf '%s\n' "$body"
|
||||
fi
|
||||
}
|
||||
write_status() {
|
||||
local status="$1"
|
||||
if [[ -n "$write_out" ]]; then
|
||||
printf '%s' "$status"
|
||||
fi
|
||||
}
|
||||
case "$method $url" in
|
||||
"GET http://portal.example.com/providers.html")
|
||||
write_body '<html><title>Provider Admin</title><body>Provider Admin</body></html>'
|
||||
;;
|
||||
"GET http://crm.example.com/api/packs")
|
||||
write_body '{"packs":[{"pack_id":"openai-cn-pack","version":"1.1.9"}]}'
|
||||
;;
|
||||
"GET http://crm.example.com/api/hosts")
|
||||
write_body '{"hosts":[{"host_id":"remote43-current-host","base_url":"http://host.example.com","host_version":"0.1.129"}]}'
|
||||
;;
|
||||
"GET http://crm.example.com/api/packs/openai-cn-pack/providers")
|
||||
write_body '{"providers":[{"provider_id":"deepseek","display_name":"DeepSeek","platform":"openai","host_overlays":1}]}'
|
||||
;;
|
||||
"POST http://crm.example.com/api/providers/deepseek/preview-import")
|
||||
write_body '{"accepted_keys_count":1,"host_overlays":1,"names":["DeepSeek"],"decisions":[{"action":"accept"}]}'
|
||||
;;
|
||||
"POST http://crm.example.com/api/providers/deepseek/import")
|
||||
write_body '{"batch_id":321,"batch_status":"succeeded","provider_status":"ready","access_status":"self_service_ready","accepted_keys_count":1,"accounts_count":1,"host_overlays":1,"group":{"id":"g1"},"channel":{"id":"c1"},"plan":{"id":"p1"},"gateway":{"id":"gw1"}}'
|
||||
;;
|
||||
"POST http://crm.example.com/api/provider-drafts")
|
||||
if [[ "$payload" == *'provider-admin-publish-1700000003'* ]]; then
|
||||
printf '%s\n' present > "$state_dir/publish-draft.present"
|
||||
write_body '{"draft":{"draft_id":"draft_publish_001","pack_id":"openai-cn-pack","provider_id":"provider-admin-publish-1700000003","display_name":"Provider Admin Publish 1700000003","platform":"openai","base_url":"https://publish-1700000003.example.com/v1","smoke_test_model":"provider-admin-publish-1700000003","supported_models":["provider-admin-publish-1700000003"]}}'
|
||||
else
|
||||
printf '%s\n' present > "$state_dir/crud-draft.present"
|
||||
write_body '{"draft":{"draft_id":"draft_crud_001","pack_id":"openai-cn-pack","provider_id":"provider-admin-draft-1700000003","display_name":"Provider Admin Draft 1700000003","platform":"openai","base_url":"https://draft-1700000003.example.com/v1","smoke_test_model":"provider-admin-draft-1700000003","supported_models":["provider-admin-draft-1700000003","provider-admin-draft-mini-1700000003"]}}'
|
||||
fi
|
||||
;;
|
||||
"GET http://crm.example.com/api/provider-drafts?pack_id=openai-cn-pack")
|
||||
if [[ -f "$state_dir/crud-draft.present" ]]; then
|
||||
write_body '{"provider_drafts":[{"draft_id":"draft_crud_001","pack_id":"openai-cn-pack","provider_id":"provider-admin-draft-1700000003","display_name":"Provider Admin Draft 1700000003","platform":"openai"}]}'
|
||||
else
|
||||
write_body '{"provider_drafts":[]}'
|
||||
fi
|
||||
;;
|
||||
"GET http://crm.example.com/api/provider-drafts/draft_crud_001")
|
||||
write_body '{"draft":{"draft_id":"draft_crud_001","pack_id":"openai-cn-pack","provider_id":"provider-admin-draft-1700000003","display_name":"Provider Admin Draft 1700000003","platform":"openai","base_url":"https://draft-1700000003.example.com/v1","smoke_test_model":"provider-admin-draft-1700000003","supported_models":["provider-admin-draft-1700000003","provider-admin-draft-mini-1700000003"]}}'
|
||||
;;
|
||||
"PUT http://crm.example.com/api/provider-drafts/draft_crud_001")
|
||||
write_body '{"draft":{"draft_id":"draft_crud_001","pack_id":"openai-cn-pack","provider_id":"provider-admin-draft-1700000003","display_name":"Provider Admin Draft Updated 1700000003","platform":"openai","base_url":"https://draft-updated-1700000003.example.com/v1","smoke_test_model":"provider-admin-draft-updated-1700000003","supported_models":["provider-admin-draft-updated-1700000003"]}}'
|
||||
;;
|
||||
"DELETE http://crm.example.com/api/provider-drafts/draft_crud_001")
|
||||
rm -f "$state_dir/crud-draft.present"
|
||||
write_status "204"
|
||||
;;
|
||||
"POST http://crm.example.com/api/provider-drafts/draft_publish_001/publish")
|
||||
write_body '{"publish":{"draft_id":"draft_publish_001","pack_id":"openai-cn-pack","provider_id":"provider-admin-publish-1700000003","provider_path":"packs/openai-cn-pack/providers/provider-admin-publish-1700000003.json","pack_version_before":"1.1.9","pack_version_after":"1.1.10","publish_mode":"created","commit_message":"feat(pack): publish provider admin draft provider-admin-publish-1700000003","commit_sha":"abc1234","repo_root":"/srv/sub2api-cn-relay-manager"}}'
|
||||
;;
|
||||
*)
|
||||
echo "unexpected curl request: $method $url payload=$payload" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
EOF
|
||||
chmod +x "$fakebin/curl"
|
||||
|
||||
PATH="$fakebin:$PATH" \
|
||||
FAKE_STATE_DIR="$state_dir" \
|
||||
CRM_BASE="http://crm.example.com" \
|
||||
CRM_ADMIN_TOKEN="token" \
|
||||
PROVIDER_ADMIN_PAGE_URL="http://portal.example.com/providers.html" \
|
||||
TS="1700000003" \
|
||||
ACCESS_API_KEY="sk-access" \
|
||||
PROVIDER_KEYS="sk-provider-1" \
|
||||
VERIFY_PUBLISH="1" \
|
||||
ARTIFACT_DIR="$artifact_dir" \
|
||||
bash "$ROOT_DIR/scripts/acceptance/verify_provider_admin_actions.sh" >"$stdout_file"
|
||||
|
||||
local summary
|
||||
summary="$(cat "$artifact_dir/99-summary.json")"
|
||||
assert_contains "$summary" '"page_title_seen": true'
|
||||
assert_contains "$summary" '"provider_id": "deepseek"'
|
||||
assert_contains "$summary" '"preview_accepted_keys_count": 1'
|
||||
assert_contains "$summary" '"import_batch_id": 321'
|
||||
assert_contains "$summary" '"crud_delete_status": "204"'
|
||||
assert_contains "$summary" '"publish_verified": true'
|
||||
assert_contains "$summary" '"publish_commit_sha": "abc1234"'
|
||||
}
|
||||
|
||||
run_test_verify_route_health_ui_script() {
|
||||
local tmpdir fakebin artifact_dir stdout_file
|
||||
tmpdir="$(mktemp -d)"
|
||||
@@ -1056,6 +1181,7 @@ run_test_import_remote43_provider_subscription_prep
|
||||
run_test_migrate_historical_artifacts
|
||||
run_test_verify_route_control_plane_script
|
||||
run_test_verify_route_data_plane_script
|
||||
run_test_verify_provider_admin_actions_script
|
||||
run_test_verify_route_health_ui_script
|
||||
run_test_remote43_patched_stack_renderers
|
||||
run_test_setup_remote43_patched_stack_dry_run
|
||||
|
||||
Reference in New Issue
Block a user