test: end-to-end checks for the WordPress basics; content and workflow guides
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
@@ -3,13 +3,9 @@
|
||||
# Runs INSIDE the DDEV web container (wp-cli and curl available there):
|
||||
# cd /home/janniclas/Projekte/WordPress && ddev exec bash wp-content/plugins/WP-LIT-MCP/tests/Integration/mcp-smoke.sh
|
||||
set -euo pipefail
|
||||
|
||||
PLUGIN=wp-content/plugins/WP-LIT-MCP
|
||||
ENDPOINT=http://localhost/wp-json/mcp/mcp-oauth-server
|
||||
cd /var/www/html
|
||||
|
||||
fail() { echo "FAIL: $*"; exit 1; }
|
||||
pass() { echo "ok - $*"; }
|
||||
# shellcheck source=lib.sh
|
||||
source wp-content/plugins/WP-LIT-MCP/tests/Integration/lib.sh
|
||||
|
||||
# --- Cleanup: remove every "lit-mcp-integration-test" application password
|
||||
# this script mints (for every user it mints one for) and the throwaway
|
||||
@@ -17,23 +13,6 @@ pass() { echo "ok - $*"; }
|
||||
# (success, fail(), or an unexpected error under `set -e`).
|
||||
ADMIN_LOGIN=""
|
||||
|
||||
cleanup_app_passwords_for() { # $1 = user_login
|
||||
local login="$1"
|
||||
[ -n "$login" ] || return 0
|
||||
local escaped=${login//\\/\\\\}
|
||||
escaped=${escaped//\'/\\\'}
|
||||
wp eval "
|
||||
\$u = get_user_by('login', '${escaped}');
|
||||
if (\$u) {
|
||||
foreach (WP_Application_Passwords::get_user_application_passwords(\$u->ID) as \$pw) {
|
||||
if ((\$pw['name'] ?? '') === 'lit-mcp-integration-test') {
|
||||
WP_Application_Passwords::delete_application_password(\$u->ID, \$pw['uuid']);
|
||||
}
|
||||
}
|
||||
}
|
||||
" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
cleanup_app_passwords_for "$ADMIN_LOGIN"
|
||||
cleanup_app_passwords_for lit-smoke-sub
|
||||
@@ -41,16 +20,6 @@ cleanup() {
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
mcp() { # $1 token, $2 json body, $3 session id (optional) -> prints headers+body
|
||||
local session_header=()
|
||||
[ -n "${3:-}" ] && session_header=(-H "Mcp-Session-Id: $3")
|
||||
curl -s --max-time 20 -i -X POST "$ENDPOINT" \
|
||||
-H "Authorization: Bearer $1" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: application/json, text/event-stream' \
|
||||
"${session_header[@]}" -d "$2"
|
||||
}
|
||||
|
||||
# 0. Booting REST triggers no _doing_it_wrong(). A regression in the
|
||||
# unhook-before-create ordering (ServerRegistrar::createServer()) would
|
||||
# otherwise surface as a "duplicate server id" _doing_it_wrong() notice when
|
||||
@@ -73,14 +42,12 @@ pass "booting REST triggers no _doing_it_wrong()"
|
||||
#
|
||||
# The HARD checks below instead hit mcp-oauth's own rewrite target directly
|
||||
# (index.php?mcp_oauth_discovery=...) via a request whose Host matches the
|
||||
# site's home URL (WordPress issues a 301 to the canonical host otherwise),
|
||||
# proving the discovery documents themselves are correct. The ENVIRONMENT
|
||||
# check further down separately probes the real `/.well-known/` path and only
|
||||
# warns, never fails, so a misconfigured web server doesn't block this suite
|
||||
# while still surfacing the risk (real MCP clients like claude.ai use the
|
||||
# real path, not the rewrite target).
|
||||
HOST=$(wp option get home | sed -E 's#^[a-zA-Z]+://##')
|
||||
|
||||
# site's home URL (WordPress issues a 301 to the canonical host otherwise;
|
||||
# HOST comes from lib.sh), proving the discovery documents themselves are
|
||||
# correct. The ENVIRONMENT check further down separately probes the real
|
||||
# `/.well-known/` path and only warns, never fails, so a misconfigured web
|
||||
# server doesn't block this suite while still surfacing the risk (real MCP
|
||||
# clients like claude.ai use the real path, not the rewrite target).
|
||||
curl -s --max-time 20 -H "Host: $HOST" -H 'X-Forwarded-Proto: https' \
|
||||
'http://localhost/?mcp_oauth_discovery=protected-resource' \
|
||||
| grep -q '"resource"' \
|
||||
@@ -110,7 +77,7 @@ pass "401 + WWW-Authenticate without token"
|
||||
|
||||
# 3. Administrator: initialize, tools/list, tools/call
|
||||
ADMIN_LOGIN=$(wp user list --role=administrator --field=user_login | head -1)
|
||||
TOKEN=$(wp eval-file "$PLUGIN/tests/Integration/mint-token.php" "$ADMIN_LOGIN")
|
||||
TOKEN=$(mint_token "$ADMIN_LOGIN")
|
||||
INIT=$(mcp "$TOKEN" '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}')
|
||||
SESSION=$(echo "$INIT" | grep -i '^mcp-session-id:' | awk '{print $2}' | tr -d '\r' || true)
|
||||
echo "$INIT" | grep -q 'LIT MCP pflegt' || fail "instructions missing in initialize result"
|
||||
@@ -130,8 +97,8 @@ pass "tools/call lit-site-status works"
|
||||
# 3b. mcp-adapter's default (unprotected) server must not exist: the route
|
||||
# it would register, mcp-adapter-default-server, must 404. Uses a temporary
|
||||
# application password (Basic auth) instead of the MCP bearer token, since
|
||||
# this checks a plain REST route, not the MCP endpoint. Named like the mint-
|
||||
# token.php passwords so the cleanup trap above also removes it.
|
||||
# this checks a plain REST route, not the MCP endpoint. Named like mint_token's
|
||||
# passwords so the cleanup trap above also removes it.
|
||||
APP_PASSWORD=$(wp user application-password create "$ADMIN_LOGIN" lit-mcp-integration-test --porcelain)
|
||||
DEFAULT_SERVER_STATUS=$(curl -s --max-time 20 -o /dev/null -w '%{http_code}' \
|
||||
-H "Host: $HOST" -H 'X-Forwarded-Proto: https' \
|
||||
@@ -150,7 +117,7 @@ pass "MCP token is rejected on /wp/v2/users/me"
|
||||
|
||||
# 5. Role gate: subscriber has a valid token but must not use tools
|
||||
wp user create lit-smoke-sub lit-smoke-sub@example.invalid --role=subscriber >/dev/null
|
||||
SUB_TOKEN=$(wp eval-file "$PLUGIN/tests/Integration/mint-token.php" lit-smoke-sub)
|
||||
SUB_TOKEN=$(mint_token lit-smoke-sub)
|
||||
SUB_INIT=$(mcp "$SUB_TOKEN" '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}')
|
||||
SUB_SESSION=$(echo "$SUB_INIT" | grep -i '^mcp-session-id:' | awk '{print $2}' | tr -d '\r' || true)
|
||||
SUB_CALL=$(mcp "$SUB_TOKEN" '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"lit-site-status","arguments":{}}}' "$SUB_SESSION")
|
||||
|
||||
Reference in New Issue
Block a user