Files
cc-ci/tests/wordpress/custom/test_post_roundtrip.py
autonomic-bot d9a446cd36
Some checks failed
continuous-integration/drone/push Build is failing
enroll(wordpress): test suite + bridge POLL_REPOS entry
Enrolls wordpress as a maintained recipe (operator request 2026-08-03):
- tests/wordpress/: recipe_meta (install-wizard-aware health 200/302, 900s deploy
  timeout for mariadb+core-copy first boot, WARM_CANONICAL), custom suite:
  health check, install-wizard completion + REST API round-trip (?rest_route= vs
  /wp-json/ splits DB vs .htaccess failure layers), and the sec4.3 post round-trip
  (XML-RPC write -> REST read -> permalink HTML, unique marker). PARITY.md documents
  the baseline (no recipe-maintainer parity corpus for wordpress).
- nix/modules/bridge.nix: POLL_REPOS += recipe-maintainers/wordpress (!testme bridge
  enrollment; deploy to the cc-ci host follows separately after the in-flight
  /upgrade-all run - test-before-switch policy).

Mirror recipe-maintainers/wordpress created + main synced to coopcloud upstream
(adcd0e9f) with published tags. used-recipes.md gains 'wordpress weekly' in the
orchestrator repo.
2026-08-03 21:05:33 +00:00

66 lines
2.6 KiB
Python

"""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/<id>`) — a different
subsystem than the one that wrote it — asserting id + rendered title match.
4. Fetch the public permalink `/?p=<id>` 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}"