- functional/_mumble_proto.py: stdlib Mumble TLS protocol client (adapted from corpus mumble_connect.py) - 3 parity ports: test_tcp_health, test_protocol_handshake (channel presence+ServerSync), test_web_client - 2 NEW recipe-specific (P3): welcome-text + max-users config round-trips over the protocol - P4: ops.py + test_backup/test_restore seed ci_marker in /data/mumble-server.sqlite (recipe's own backupbot DB), busy_timeout for live-server locks - test_install overlay: voice server listening on 64738 (beyond web-sidecar readiness) - recipe_meta: COMPOSE_FILE=compose.yml:mumbleweb:host-ports; WELCOME_TEXT/USERS markers - PARITY.md mapping table Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
36 lines
1.4 KiB
Python
36 lines
1.4 KiB
Python
"""mumble — web client parity port (Phase 2 P2).
|
|
|
|
SOURCE: recipe-info/mumble/tests/web_client.py — "Verifies the web client is reachable via HTTPS,
|
|
returns HTTP 200, and serves the Mumble Web UI with expected page content." Requires the
|
|
compose.mumbleweb.yml overlay (enabled via recipe_meta.EXTRA_ENV COMPOSE_FILE).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import ssl
|
|
import sys
|
|
import urllib.request
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "..", "runner"))
|
|
from harness import http as harness_http # noqa: E402
|
|
|
|
|
|
def _fetch_body(url: str) -> str:
|
|
ctx = ssl.create_default_context()
|
|
ctx.check_hostname = False
|
|
ctx.verify_mode = ssl.CERT_NONE
|
|
with urllib.request.urlopen(urllib.request.Request(url), timeout=15, context=ctx) as resp:
|
|
return resp.read().decode("utf-8", errors="replace")
|
|
|
|
|
|
def test_web_client_serves_mumble_web_ui(live_app):
|
|
url = f"https://{live_app}/"
|
|
status, _ = harness_http.retry_http_get(url, expect_status=200, max_wait=120, interval=5)
|
|
assert status == 200, f"GET {url} HTTP {status} (expected 200)"
|
|
|
|
body = _fetch_body(url)
|
|
assert "Mumble" in body, "web client page does not contain 'Mumble' content"
|
|
assert "config.js" in body, "web client page does not load config.js"
|
|
assert body.strip().startswith("<!DOCTYPE html>"), "web client response is not valid HTML"
|