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.
64 lines
2.2 KiB
Python
64 lines
2.2 KiB
Python
"""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
|