diff --git a/homeassistant/components/androidtv/manifest.json b/homeassistant/components/androidtv/manifest.json index 47768cbd4dc..39e5bfb2cdf 100644 --- a/homeassistant/components/androidtv/manifest.json +++ b/homeassistant/components/androidtv/manifest.json @@ -3,8 +3,8 @@ "name": "Androidtv", "documentation": "https://www.home-assistant.io/integrations/androidtv", "requirements": [ - "adb-shell==0.0.9", - "androidtv==0.0.35", + "adb-shell==0.1.0", + "androidtv==0.0.36", "pure-python-adb==0.2.2.dev0" ], "dependencies": [], diff --git a/homeassistant/components/androidtv/media_player.py b/homeassistant/components/androidtv/media_player.py index a1fb4cea9cd..15acd594bee 100644 --- a/homeassistant/components/androidtv/media_player.py +++ b/homeassistant/components/androidtv/media_player.py @@ -146,7 +146,8 @@ def setup_platform(hass, config, add_entities, discovery_info=None): adb_log = f"using Python ADB implementation with adbkey='{adbkey}'" aftv = setup( - host, + config[CONF_HOST], + config[CONF_PORT], adbkey, device_class=config[CONF_DEVICE_CLASS], state_detection_rules=config[CONF_STATE_DETECTION_RULES], @@ -159,7 +160,8 @@ def setup_platform(hass, config, add_entities, discovery_info=None): ) aftv = setup( - host, + config[CONF_HOST], + config[CONF_PORT], config[CONF_ADBKEY], device_class=config[CONF_DEVICE_CLASS], state_detection_rules=config[CONF_STATE_DETECTION_RULES], @@ -171,7 +173,8 @@ def setup_platform(hass, config, add_entities, discovery_info=None): adb_log = f"using ADB server at {config[CONF_ADB_SERVER_IP]}:{config[CONF_ADB_SERVER_PORT]}" aftv = setup( - host, + config[CONF_HOST], + config[CONF_PORT], adb_server_ip=config[CONF_ADB_SERVER_IP], adb_server_port=config[CONF_ADB_SERVER_PORT], device_class=config[CONF_DEVICE_CLASS], diff --git a/requirements_all.txt b/requirements_all.txt index 2f6247ec18e..2c4d1c9e5a0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -115,7 +115,7 @@ adafruit-blinka==1.2.1 adafruit-circuitpython-mcp230xx==1.1.2 # homeassistant.components.androidtv -adb-shell==0.0.9 +adb-shell==0.1.0 # homeassistant.components.adguard adguardhome==0.3.0 @@ -215,7 +215,7 @@ ambiclimate==0.2.1 amcrest==1.5.3 # homeassistant.components.androidtv -androidtv==0.0.35 +androidtv==0.0.36 # homeassistant.components.anel_pwrctrl anel_pwrctrl-homeassistant==0.0.1.dev2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 812af1a2b13..472ed8df9a3 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -29,7 +29,7 @@ YesssSMS==0.4.1 abodepy==0.16.7 # homeassistant.components.androidtv -adb-shell==0.0.9 +adb-shell==0.1.0 # homeassistant.components.adguard adguardhome==0.3.0 @@ -84,7 +84,7 @@ airly==0.0.2 ambiclimate==0.2.1 # homeassistant.components.androidtv -androidtv==0.0.35 +androidtv==0.0.36 # homeassistant.components.apns apns2==0.3.0 diff --git a/tests/components/androidtv/patchers.py b/tests/components/androidtv/patchers.py index bd05cab2a74..c49b6ad11e9 100644 --- a/tests/components/androidtv/patchers.py +++ b/tests/components/androidtv/patchers.py @@ -3,11 +3,11 @@ from unittest.mock import mock_open, patch -class AdbDeviceFake: - """A fake of the `adb_shell.adb_device.AdbDevice` class.""" +class AdbDeviceTcpFake: + """A fake of the `adb_shell.adb_device.AdbDeviceTcp` class.""" def __init__(self, *args, **kwargs): - """Initialize a fake `adb_shell.adb_device.AdbDevice` instance.""" + """Initialize a fake `adb_shell.adb_device.AdbDeviceTcp` instance.""" self.available = False def close(self): @@ -74,39 +74,39 @@ class DeviceFake: def patch_connect(success): - """Mock the `adb_shell.adb_device.AdbDevice` and `ppadb.client.Client` classes.""" + """Mock the `adb_shell.adb_device.AdbDeviceTcp` and `ppadb.client.Client` classes.""" def connect_success_python(self, *args, **kwargs): - """Mock the `AdbDeviceFake.connect` method when it succeeds.""" + """Mock the `AdbDeviceTcpFake.connect` method when it succeeds.""" self.available = True def connect_fail_python(self, *args, **kwargs): - """Mock the `AdbDeviceFake.connect` method when it fails.""" + """Mock the `AdbDeviceTcpFake.connect` method when it fails.""" raise OSError if success: return { "python": patch( - f"{__name__}.AdbDeviceFake.connect", connect_success_python + f"{__name__}.AdbDeviceTcpFake.connect", connect_success_python ), "server": patch("androidtv.adb_manager.Client", ClientFakeSuccess), } return { - "python": patch(f"{__name__}.AdbDeviceFake.connect", connect_fail_python), + "python": patch(f"{__name__}.AdbDeviceTcpFake.connect", connect_fail_python), "server": patch("androidtv.adb_manager.Client", ClientFakeFail), } def patch_shell(response=None, error=False): - """Mock the `AdbDeviceFake.shell` and `DeviceFake.shell` methods.""" + """Mock the `AdbDeviceTcpFake.shell` and `DeviceFake.shell` methods.""" def shell_success(self, cmd): - """Mock the `AdbDeviceFake.shell` and `DeviceFake.shell` methods when they are successful.""" + """Mock the `AdbDeviceTcpFake.shell` and `DeviceFake.shell` methods when they are successful.""" self.shell_cmd = cmd return response def shell_fail_python(self, cmd): - """Mock the `AdbDeviceFake.shell` method when it fails.""" + """Mock the `AdbDeviceTcpFake.shell` method when it fails.""" self.shell_cmd = cmd raise AttributeError @@ -117,16 +117,16 @@ def patch_shell(response=None, error=False): if not error: return { - "python": patch(f"{__name__}.AdbDeviceFake.shell", shell_success), + "python": patch(f"{__name__}.AdbDeviceTcpFake.shell", shell_success), "server": patch(f"{__name__}.DeviceFake.shell", shell_success), } return { - "python": patch(f"{__name__}.AdbDeviceFake.shell", shell_fail_python), + "python": patch(f"{__name__}.AdbDeviceTcpFake.shell", shell_fail_python), "server": patch(f"{__name__}.DeviceFake.shell", shell_fail_server), } -PATCH_ADB_DEVICE = patch("androidtv.adb_manager.AdbDevice", AdbDeviceFake) +PATCH_ADB_DEVICE_TCP = patch("androidtv.adb_manager.AdbDeviceTcp", AdbDeviceTcpFake) PATCH_ANDROIDTV_OPEN = patch("androidtv.adb_manager.open", mock_open()) PATCH_KEYGEN = patch("homeassistant.components.androidtv.media_player.keygen") PATCH_SIGNER = patch("androidtv.adb_manager.PythonRSASigner") diff --git a/tests/components/androidtv/test_media_player.py b/tests/components/androidtv/test_media_player.py index 860b8738607..15c4897c136 100644 --- a/tests/components/androidtv/test_media_player.py +++ b/tests/components/androidtv/test_media_player.py @@ -95,7 +95,7 @@ async def _test_reconnect(hass, caplog, config): """ patch_key, entity_id = _setup(hass, config) - with patchers.PATCH_ADB_DEVICE, patchers.patch_connect(True)[ + with patchers.PATCH_ADB_DEVICE_TCP, patchers.patch_connect(True)[ patch_key ], patchers.patch_shell("")[ patch_key @@ -166,7 +166,7 @@ async def _test_adb_shell_returns_none(hass, config): """ patch_key, entity_id = _setup(hass, config) - with patchers.PATCH_ADB_DEVICE, patchers.patch_connect(True)[ + with patchers.PATCH_ADB_DEVICE_TCP, patchers.patch_connect(True)[ patch_key ], patchers.patch_shell("")[ patch_key @@ -274,7 +274,7 @@ async def test_setup_with_adbkey(hass): config[DOMAIN][CONF_ADBKEY] = hass.config.path("user_provided_adbkey") patch_key, entity_id = _setup(hass, config) - with patchers.PATCH_ADB_DEVICE, patchers.patch_connect(True)[ + with patchers.PATCH_ADB_DEVICE_TCP, patchers.patch_connect(True)[ patch_key ], patchers.patch_shell("")[ patch_key @@ -292,7 +292,7 @@ async def _test_sources(hass, config0): config[DOMAIN][CONF_APPS] = {"com.app.test1": "TEST 1"} patch_key, entity_id = _setup(hass, config) - with patchers.PATCH_ADB_DEVICE, patchers.patch_connect(True)[ + with patchers.PATCH_ADB_DEVICE_TCP, patchers.patch_connect(True)[ patch_key ], patchers.patch_shell("")[patch_key]: assert await async_setup_component(hass, DOMAIN, config) @@ -364,7 +364,7 @@ async def _test_select_source(hass, config0, source, expected_arg, method_patch) config[DOMAIN][CONF_APPS] = {"com.app.test1": "TEST 1"} patch_key, entity_id = _setup(hass, config) - with patchers.PATCH_ADB_DEVICE, patchers.patch_connect(True)[ + with patchers.PATCH_ADB_DEVICE_TCP, patchers.patch_connect(True)[ patch_key ], patchers.patch_shell("")[patch_key]: assert await async_setup_component(hass, DOMAIN, config) @@ -515,3 +515,68 @@ async def test_firetv_select_source_stop_app_id_no_name(hass): "com.app.test2", patchers.PATCH_STOP_APP, ) + + +async def _test_setup_fail(hass, config): + """Test that the entity is not created when the ADB connection is not established.""" + patch_key, entity_id = _setup(hass, config) + + with patchers.PATCH_ADB_DEVICE_TCP, patchers.patch_connect(False)[ + patch_key + ], patchers.patch_shell("")[ + patch_key + ], patchers.PATCH_KEYGEN, patchers.PATCH_ANDROIDTV_OPEN, patchers.PATCH_SIGNER: + assert await async_setup_component(hass, DOMAIN, config) + await hass.helpers.entity_component.async_update_entity(entity_id) + state = hass.states.get(entity_id) + assert state is None + + return True + + +async def test_setup_fail_androidtv(hass): + """Test that the Android TV entity is not created when the ADB connection is not established.""" + assert await _test_setup_fail(hass, CONFIG_ANDROIDTV_PYTHON_ADB) + + +async def test_setup_fail_firetv(hass): + """Test that the Fire TV entity is not created when the ADB connection is not established.""" + assert await _test_setup_fail(hass, CONFIG_FIRETV_PYTHON_ADB) + + +async def test_setup_two_devices(hass): + """Test that two devices can be set up.""" + config = { + DOMAIN: [ + CONFIG_ANDROIDTV_ADB_SERVER[DOMAIN], + CONFIG_FIRETV_ADB_SERVER[DOMAIN].copy(), + ] + } + config[DOMAIN][1][CONF_HOST] = "127.0.0.2" + + patch_key = "server" + with patchers.PATCH_ADB_DEVICE_TCP, patchers.patch_connect(True)[ + patch_key + ], patchers.patch_shell("")[patch_key]: + assert await async_setup_component(hass, DOMAIN, config) + + for entity_id in ["media_player.android_tv", "media_player.fire_tv"]: + await hass.helpers.entity_component.async_update_entity(entity_id) + state = hass.states.get(entity_id) + assert state is not None + assert state.state == STATE_OFF + + +async def test_setup_same_device_twice(hass): + """Test that setup succeeds with a duplicated config entry.""" + patch_key = "server" + + with patchers.PATCH_ADB_DEVICE_TCP, patchers.patch_connect(True)[ + patch_key + ], patchers.patch_shell("")[patch_key]: + assert await async_setup_component(hass, DOMAIN, CONFIG_ANDROIDTV_ADB_SERVER) + + with patchers.PATCH_ADB_DEVICE_TCP, patchers.patch_connect(True)[ + patch_key + ], patchers.patch_shell("")[patch_key]: + assert await async_setup_component(hass, DOMAIN, CONFIG_ANDROIDTV_ADB_SERVER)