docs(readme): replacement guide + a verified seed example (t41)

The README now answers the question a migrator actually has: what do I delete,
and what covers it afterwards.

* a new "Replacing androidtv / androidtv_remote + the glue" section: the
  back-up → remove-the-platform-YAML → remove-mediasession2mqtt → delete the old
  integrations → add this one → update automations checklist, plus a table
  mapping every retired piece to what serves it now. It notes that Wholphin
  publishes no MediaSession of its own and gets its now-playing from the ADB
  media session, so no bridge is needed for it either;
* the setup steps describe the real flow (name + one address, both transports on
  by default, ADB pairing then PIN pairing, each with a skip);
* the YAML seed section carries a complete, copy-pasteable block. It documents
  ONLY the keys `_yaml_seed_blocks` honours (name, host, adb_port, adb_enabled,
  and the still-accepted protocol_host/adb_host) and says explicitly that the
  rest lives on the Configure page — an example that lists ignored keys is worse
  than no example;
* the state-ladder section, the discovery bullet and the options list follow the
  two-transport, one-address reality.

`tests/test_readme.py` pins the doc/code contract: the example's keys are a
subset of what the seed reads, the example uses the current `host` key, and the
guide keeps naming the retired integrations and glues.

Verified: 326 passed / 2 skipped, ruff clean.
This commit is contained in:
James Mackay committed 2026-10-11 06:21:40 +01:00
1 parent fb481c3c14
commit 151c49a0da
2 files changed
+145 -24

No files matched your search

+63
View File
@@ -0,0 +1,63 @@
"""tests/test_readme.py — the README's user-facing contracts (t41).
Documentation drifts silently: the seed example is read by people who then
report "the key did nothing". These pins are deliberately textual — no YAML
parser dependency — but they check the two things that actually hurt:
* every key in the `nvidia_shield:` example is a key ``_yaml_seed_blocks``
honours (nothing documented that the integration ignores);
* the replacement guide names the integrations and the glue it retires, so the
t41 ruling stays visible to users, not only in the changelog.
"""
import re
from pathlib import Path
import pytest
README = Path(__file__).resolve().parent.parent / "README.md"
# helpers.seed_host / helpers.seed_adb_enabled read these; nothing else in a
# seed block reaches the entry (the rest is the interactive flow's or the
# options page's to set).
SEEDED_KEYS = {
"name",
"host",
"adb_port",
"adb_enabled",
"protocol_host", # legacy, still accepted
"adb_host", # legacy, still accepted
}
@pytest.fixture(scope="module")
def readme_text() -> str:
return README.read_text(encoding="utf-8")
def _seed_example(text: str) -> str:
match = re.search(r"```yaml\n(nvidia_shield:\n(?:.*\n)*?)```", text)
assert match, "the README has no `nvidia_shield:` example block"
return match.group(1)
def test_the_example_block_only_uses_seeded_keys(readme_text):
keys = set(re.findall(r"^\s+([a-z_]+):", _seed_example(readme_text), re.M))
assert keys, "the example block declares no keys"
assert keys <= SEEDED_KEYS, f"documented but ignored: {sorted(keys - SEEDED_KEYS)}"
def test_the_example_block_documents_the_one_address_field(readme_text):
example = _seed_example(readme_text)
assert "host:" in example
# the legacy spellings are still explained, as back-compat
assert "protocol_host" in readme_text and "adb_host" in readme_text
def test_the_replacement_guide_retires_the_old_stack(readme_text):
for needle in ("androidtv_remote", "mediasession2mqtt", "universal", "Wholphin"):
assert needle in readme_text, needle
# and it says the UI is the primary path
assert "primary path" in readme_text