"""wordpress — §4.3 create-an-object + read-it-back: publish a post, read it back twice. Flow: 1. `ensure_installed` (idempotent — run-scoped admin credentials from _wp.py). 2. Create a post with a unique marker title via **XML-RPC** `wp.newPost` (stdlib xmlrpc.client; XML-RPC ships enabled in WP and authenticates with the admin user/password directly — no cookie/nonce dance). 3. Read it back via the **public REST API** (`?rest_route=/wp/v2/posts/`) — a different subsystem than the one that wrote it — asserting id + rendered title match. 4. Fetch the public permalink `/?p=` and assert the marker is in the served HTML. Non-vacuous: the marker round-trips app → mariadb → app across three distinct read paths; a post that didn't persist, a broken DB, or a wedged PHP-FPM fails at the layer that broke. """ from __future__ import annotations import os import ssl import sys import uuid import xmlrpc.client sys.path.insert(0, os.path.dirname(__file__)) sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "..", "runner")) from _wp import ADMIN_PW, ADMIN_USER, ensure_installed, fetch_text # noqa: E402 from harness import http as harness_http # noqa: E402 _CTX = ssl.create_default_context() _CTX.check_hostname = False _CTX.verify_mode = ssl.CERT_NONE def test_create_post_and_read_back(live_app): ensure_installed(live_app) marker = f"ccci-post-{uuid.uuid4().hex[:8]}" proxy = xmlrpc.client.ServerProxy(f"https://{live_app}/xmlrpc.php", context=_CTX) post_id = proxy.wp.newPost( 0, ADMIN_USER, ADMIN_PW, { "post_title": marker, "post_content": f"cc-ci round-trip body for {marker}", "post_status": "publish", }, ) assert post_id and str(post_id).isdigit(), f"wp.newPost returned no post id: {post_id!r}" # Read back via the public REST API (different subsystem than XML-RPC) status, body = harness_http.http_get( f"https://{live_app}/?rest_route=/wp/v2/posts/{post_id}", timeout=60 ) assert status == 200, f"GET rest_route /wp/v2/posts/{post_id} HTTP {status}: {body!r}" assert isinstance(body, dict) and str(body.get("id")) == str(post_id), ( f"read-back id mismatch: {body!r}" ) rendered = (body.get("title") or {}).get("rendered", "") assert marker in rendered, f"read-back title {rendered!r} missing marker {marker!r}" # And the public permalink serves the marker in HTML status, raw = fetch_text(f"https://{live_app}/?p={post_id}") assert status == 200, f"GET /?p={post_id} HTTP {status}" assert marker in raw, f"permalink page does not contain the marker {marker!r}"