#!/bin/bash # Test suite for post.sh, run against tests/mock_wp_server.py so no real # WordPress install is needed. Requires curl, jq, python3, python3-markdown2. set -u cd "$(dirname "$0")/.." for bin in curl jq python3; do command -v "$bin" >/dev/null || { echo "missing dependency: $bin"; exit 1; } done python3 -c "import markdown2" 2>/dev/null || { echo "missing dependency: python3-markdown2"; exit 1; } PORT=8899 WORKDIR=$(mktemp -d) trap 'kill $SERVER_PID 2>/dev/null; rm -rf "$WORKDIR"' EXIT export MOCK_WP_PORT=$PORT export MOCK_WP_CONTROL_FILE="$WORKDIR/control.json" export MOCK_WP_REQUEST_FILE="$WORKDIR/request.json" python3 -u tests/mock_wp_server.py & SERVER_PID=$! for i in $(seq 1 20); do curl -s -o /dev/null "http://127.0.0.1:$PORT/" && break sleep 0.2 done export HOME="$WORKDIR/home" mkdir -p "$HOME/.config/wordpress-rest-curl" cat > "$HOME/.config/wordpress-rest-curl/config.sh" < "$HOME/.config/wordpress-rest-curl/othersite.sh" < "$POST_FILE" <<'EOF2' # My Test Title Some **markdown** content here. EOF2 run_post_sh() { printf "" | "$PWD/post.sh" "$@" } FAIL=0 assert_eq() { local desc="$1" expected="$2" actual="$3" if [[ "$expected" != "$actual" ]]; then echo "FAIL: $desc (expected [$expected], got [$actual])" FAIL=1 else echo "PASS: $desc" fi } # --- create + publish --- rm -f "$MOCK_WP_REQUEST_FILE" "$MOCK_WP_CONTROL_FILE" run_post_sh --file "$POST_FILE" --publish >/dev/null assert_eq "create: exit code" "0" "$?" REQ=$(cat "$MOCK_WP_REQUEST_FILE") assert_eq "create: path" "/wp-json/wp/v2/posts/" "$(jq -r '.path' <<<"$REQ")" assert_eq "create: title extracted from heading" "My Test Title" "$(jq -r '.payload.title' <<<"$REQ")" assert_eq "create: status" "publish" "$(jq -r '.payload.status' <<<"$REQ")" assert_eq "create: categories sent as array" "[3,7]" "$(jq -c '.payload.categories' <<<"$REQ")" assert_eq "create: tags sent as array" "[10]" "$(jq -c '.payload.tags' <<<"$REQ")" assert_eq "create: content rendered as markdown" "true" "$(jq -r '.payload.content | test("markdown")' <<<"$REQ")" assert_eq "create: sends a non-default user agent" "true" "$(jq -r '.user_agent != "" and (.user_agent | test("^curl/") | not)' <<<"$REQ")" # --- USER_AGENT is configurable, e.g. to dodge a host's DDoS protection --- rm -f "$MOCK_WP_REQUEST_FILE" "$MOCK_WP_CONTROL_FILE" cat >> "$HOME/.config/wordpress-rest-curl/config.sh" <<'EOF3' USER_AGENT="Mozilla/5.0 (test override)" EOF3 run_post_sh --file "$POST_FILE" >/dev/null assert_eq "user agent: exit code" "0" "$?" REQ=$(cat "$MOCK_WP_REQUEST_FILE") assert_eq "user agent: override from config is sent" "Mozilla/5.0 (test override)" "$(jq -r '.user_agent' <<<"$REQ")" # --- trailing slash on SERVER doesn't produce a double slash in the URL --- rm -f "$MOCK_WP_REQUEST_FILE" "$MOCK_WP_CONTROL_FILE" cat >> "$HOME/.config/wordpress-rest-curl/config.sh" </dev/null assert_eq "trailing slash: exit code" "0" "$?" REQ=$(cat "$MOCK_WP_REQUEST_FILE") assert_eq "trailing slash: path has no double slash" "/wp-json/wp/v2/posts/" "$(jq -r '.path' <<<"$REQ")" # --- edit an existing post --- rm -f "$MOCK_WP_REQUEST_FILE" "$MOCK_WP_CONTROL_FILE" run_post_sh --file "$POST_FILE" --edit 99 >/dev/null assert_eq "edit: exit code" "0" "$?" REQ=$(cat "$MOCK_WP_REQUEST_FILE") assert_eq "edit: path includes post ID" "/wp-json/wp/v2/posts/99" "$(jq -r '.path' <<<"$REQ")" assert_eq "edit: status defaults to draft" "draft" "$(jq -r '.payload.status' <<<"$REQ")" # --- --site layers on top of config.sh: overrides what it sets, inherits the rest --- rm -f "$MOCK_WP_REQUEST_FILE" "$MOCK_WP_CONTROL_FILE" run_post_sh --site othersite --file "$POST_FILE" >/dev/null assert_eq "site: exit code" "0" "$?" REQ=$(cat "$MOCK_WP_REQUEST_FILE") assert_eq "site: categories overridden by site config" "[1]" "$(jq -c '.payload.categories' <<<"$REQ")" assert_eq "site: tags inherited from default config" "[10]" "$(jq -c '.payload.tags' <<<"$REQ")" assert_eq "site: title transform inherited from default config" "My Test Title" "$(jq -r '.payload.title' <<<"$REQ")" rm -f "$MOCK_WP_REQUEST_FILE" "$MOCK_WP_CONTROL_FILE" OUT=$(run_post_sh --site does-not-exist --file "$POST_FILE" 2>&1) assert_eq "site: unknown site exits non-zero" "1" "$?" assert_eq "site: unknown site error message" "true" "$(grep -q "Config file not found" <<<"$OUT" && echo true || echo false)" # --- no --site and no default config.sh: clean error, not a crash --- mv "$HOME/.config/wordpress-rest-curl/config.sh" "$WORKDIR/config.sh.bak" OUT=$(run_post_sh --file "$POST_FILE" 2>&1) assert_eq "no config: exits non-zero" "1" "$?" assert_eq "no config: error message" "true" "$(grep -q "No site specified and no default config found" <<<"$OUT" && echo true || echo false)" mv "$WORKDIR/config.sh.bak" "$HOME/.config/wordpress-rest-curl/config.sh" # --- non-2xx response is surfaced and script exits non-zero --- rm -f "$MOCK_WP_REQUEST_FILE" echo '{"status": 401, "body": {"code": "rest_forbidden", "message": "Sorry, you are not allowed to do that."}}' > "$MOCK_WP_CONTROL_FILE" OUT=$(run_post_sh --file "$POST_FILE" 2>&1) assert_eq "error: exit code" "1" "$?" assert_eq "error: HTTP status surfaced" "true" "$(grep -q "HTTP 401" <<<"$OUT" && echo true || echo false)" rm -f "$MOCK_WP_CONTROL_FILE" echo if [[ $FAIL -eq 0 ]]; then echo "All tests passed." else echo "Some tests FAILED." fi exit $FAIL