test(discovery): fixtures for the parsers, the bounded sweep and the surfaces
tests/test_installed_apps.py is new and is where the discovery claims are pinned. NO REAL SHIELD WAS AVAILABLE, so the command output is fixture-based in the documented Android shapes — `pm list packages` lines, the verbose `resolve-activity` header followed by `package/activity`, and `pm dump` carrying `application-label` — including a localized label (the default locale wins), a label-less app (a definitive negative, and still a row) and the launcher (a system app that must be present). Covered: both parsers plus their tolerances (noise, duplicates, blank, a bare `package/activity` line, the settings entry point that is not a launcher), the user+launcher merge and its de-duplication, the icon heuristic and that it is always a string, the sweep's commands, its concurrency bound (peak <= APP_SWEEP_CONCURRENCY and > 1, so it is bounded AND genuinely concurrent), cache reuse with zero shells, the TTL, shared sweeps for concurrent callers, and every degradation path (no poller, disconnected, mute transport — empty list, no loop, no raise). The sensor's count/table/reason and the "a failed refresh is a no-op, not an exception" behaviour are pinned too. The config-flow side is in tests/test_config_flow_ux.py: the table lists every discovered app, a discovered app the map never mentions is appended, the user's name wins for the same package, an `mdi:` value never reaches the icon column, rendering issues no shell, the Discover row runs one forced sweep and returns to the menu, a failed sweep still renders, and the merged table round-trips into the saved options. Also: tests/test_config_flow_real_ha.py learns the new row, the standalone stub accepts `description_placeholders` (which the apps form now passes), and the state=6 wording in media_session.py/media_player.py is the t57 UNIT 0c reword.
This commit is contained in:
1 parent
a56ec38170
commit
5eefd0c6d0
6 files changed
+669
-16
No files matched your search
@@ -149,12 +149,16 @@ def _install_stubs() -> None:
|
||||
raise DiscoveryDedupAbortError("already_in_progress")
|
||||
|
||||
class OptionsFlow:
|
||||
def async_show_form(self, *, step_id, data_schema=None, errors=None):
|
||||
def async_show_form(
|
||||
self, *, step_id, data_schema=None, errors=None,
|
||||
description_placeholders=None,
|
||||
):
|
||||
return {
|
||||
"type": "form",
|
||||
"step_id": step_id,
|
||||
"errors": dict(errors or {}),
|
||||
"data_schema": data_schema,
|
||||
"description_placeholders": dict(description_placeholders or {}),
|
||||
}
|
||||
|
||||
def async_show_menu(self, *, step_id, menu_options, sort=False,
|
||||
@@ -1306,7 +1310,7 @@ class TestAppsMapOptionsEditor:
|
||||
assert result["type"] == "form"
|
||||
fields = getattr(result["data_schema"], "schema", result["data_schema"])
|
||||
suggested = fields.get("__suggested__", {})
|
||||
assert suggested["app_name_map"] == "ar.tvplayer.tv=TiviMate"
|
||||
assert suggested["app_name_map"] == "ar.tvplayer.tv=TiviMate" # t57
|
||||
# the editor carried the existing map through the defaults path
|
||||
assert flow._options["app_name_map"] == {"ar.tvplayer.tv": "TiviMate"}
|
||||
|
||||
|
||||
Reference in new issue
Block a user