#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" ENV_FILE="${ROOT_DIR}/credentials/.env" if [[ -f "${ENV_FILE}" ]]; then # shellcheck disable=SC1090 source "${ENV_FILE}" fi BASE_URL="${BASE_URL:-${WP_URL:-}}" AUTH_USER="${CAL_TEST_USER:-adrians@chezstephens.org.uk}" AUTH_PASS="${CAL_TEST_PASSWORD:-brillig1}" EXPECTED_TABLE_PREFIX="${CAL_TABLE_PREFIX_EXPECTED:-wp_cs_calendar}" ENABLE_PREFIX_CHECK="${CAL_ENABLE_PREFIX_CHECK:-1}" REMOTE_WP_PATH="${REMOTE_WP_PATH:-}" if [[ -z "${REMOTE_WP_PATH}" ]] && [[ -n "${REMOTE_APP_DIR:-}" ]]; then REMOTE_WP_PATH="$(dirname "$(dirname "${REMOTE_APP_DIR}")")" fi if [[ -z "${REMOTE_WP_PATH}" ]]; then REMOTE_WP_PATH="/var/www/wordpress" fi FAILURES=0 CREATED_EVENT_ID="" CREATED_REC_EVENT_ID="" usage() { cat <<'TXT' Remote API+E2E smoke runner for calendar plugin. Usage: tests/run_remote_tests.sh [--base-url URL] [--user EMAIL] [--password PASS] Env overrides: BASE_URL CAL_TEST_USER CAL_TEST_PASSWORD CAL_TABLE_PREFIX_EXPECTED CAL_ENABLE_PREFIX_CHECK Defaults: BASE_URL -> credentials/.env:WP_URL user/password -> seeded smoke account TXT } while [[ $# -gt 0 ]]; do case "$1" in --base-url) BASE_URL="${2:-}" shift 2 ;; --user) AUTH_USER="${2:-}" shift 2 ;; --password) AUTH_PASS="${2:-}" shift 2 ;; --help|-h) usage exit 0 ;; *) echo "[remote-tests] unknown argument: $1" >&2 usage exit 2 ;; esac done if [[ -z "${BASE_URL}" ]]; then echo "[remote-tests] BASE_URL is required (set WP_URL in credentials/.env or pass --base-url)" >&2 exit 2 fi BASE_URL="${BASE_URL%/}" step() { printf '\n[remote-tests] %s\n' "$1" } record_fail() { FAILURES=$((FAILURES + 1)) echo "[remote-tests] FAIL: $1" >&2 } json_assert() { local file="$1" local expr="$2" python3 - "$file" "$expr" <<'PY' import json, sys path, expr = sys.argv[1], sys.argv[2] data = json.load(open(path)) safe = {"bool": bool, "isinstance": isinstance, "list": list, "dict": dict, "str": str, "int": int} ok = eval(expr, {"__builtins__": safe}, {"data": data}) if not ok: raise SystemExit(1) PY } cleanup() { if [[ -n "${CREATED_EVENT_ID}" ]]; then curl -sS -u "${AUTH_USER}:${AUTH_PASS}" -X DELETE \ "${BASE_URL}/wp-json/calendar/v1/events/${CREATED_EVENT_ID}" >/dev/null || true fi if [[ -n "${CREATED_REC_EVENT_ID}" ]]; then curl -sS -u "${AUTH_USER}:${AUTH_PASS}" -X DELETE \ "${BASE_URL}/wp-json/calendar/v1/events/${CREATED_REC_EVENT_ID}" >/dev/null || true fi } trap cleanup EXIT step "health" if curl -fsS "${BASE_URL}/wp-json/calendar/v1/health" >/tmp/remote_test_health.json; then if ! json_assert /tmp/remote_test_health.json "data.get('status') == 'ok'"; then record_fail "health payload invalid" fi else record_fail "health endpoint unreachable" fi if [[ "${ENABLE_PREFIX_CHECK}" == "1" ]] && [[ -n "${REMOTE_HOST:-}" ]] && [[ -n "${REMOTE_USER:-}" ]] && [[ -n "${REMOTE_SSH_KEY_PATH:-}" ]] && [[ -n "${REMOTE_PORT:-}" ]] && [[ -n "${REMOTE_WP_CLI:-}" ]]; then step "table prefix configuration" SSH_KEY_PATH="${REMOTE_SSH_KEY_PATH}" if [[ "${SSH_KEY_PATH}" != /* ]]; then SSH_KEY_PATH="${ROOT_DIR}/${SSH_KEY_PATH}" fi SSH_PREFIX=(ssh -F /dev/null -i "${SSH_KEY_PATH}" -p "${REMOTE_PORT}" -o StrictHostKeyChecking=accept-new "${REMOTE_USER}@${REMOTE_HOST}") if ! "${SSH_PREFIX[@]}" "echo ok" >/dev/null 2>&1; then echo "[remote-tests] WARN: SSH unavailable, skipping table prefix check" else STEM="$("${SSH_PREFIX[@]}" "cd ${REMOTE_WP_PATH} && ${REMOTE_WP_CLI} option get calendar_plugin_table_stem --allow-root 2>/dev/null || true" | tr -d '\r' | tail -n1)" if [[ -n "${STEM}" ]] && [[ "${STEM}" != "cs_calendar" ]] && [[ "${STEM}" != "calendar" ]]; then record_fail "table stem option expected cs_calendar/calendar got '${STEM}'" fi TABLE_LIST="$("${SSH_PREFIX[@]}" "cd ${REMOTE_WP_PATH} && ${REMOTE_WP_CLI} db query \"SHOW TABLES;\" --allow-root --silent --skip-column-names 2>/dev/null || true" | tr -d '\r')" TABLE_EXISTS="$(printf '%s\n' "${TABLE_LIST}" | grep -Fx "${EXPECTED_TABLE_PREFIX}_events" | head -n1 || true)" LEGACY_EXISTS="$(printf '%s\n' "${TABLE_LIST}" | grep -Fx "wp_calendar_events" | head -n1 || true)" if [[ "${TABLE_EXISTS}" != "${EXPECTED_TABLE_PREFIX}_events" ]] && [[ "${LEGACY_EXISTS}" != "wp_calendar_events" ]]; then record_fail "expected table prefix '${EXPECTED_TABLE_PREFIX}' (or legacy wp_calendar) not found" fi fi fi step "public read month" if curl -fsS "${BASE_URL}/wp-json/calendar/v1/public/events?view=month&date=2026-04-01" >/tmp/remote_test_public.json; then if ! json_assert /tmp/remote_test_public.json "isinstance(data.get('data'), list)"; then record_fail "public events payload invalid" fi else record_fail "public events endpoint failed" fi step "authenticated /users/me" if curl -fsS -u "${AUTH_USER}:${AUTH_PASS}" "${BASE_URL}/wp-json/calendar/v1/users/me" >/tmp/remote_test_me.json; then if ! json_assert /tmp/remote_test_me.json "bool(data.get('data', {}).get('email'))"; then record_fail "auth user context invalid" fi else record_fail "auth /users/me failed" fi step "event CRUD" EVENT_UID="remote-api-e2e-$(date +%s)@calendar-plugin" CREATE_JSON=$(cat <