async def test_setting_up_core_update_when_addon_fails(hass, caplog): """Test setting up core update when single addon fails.""" with patch.dict(os.environ, MOCK_ENVIRON), patch( "homeassistant.components.hassio.HassIO.get_addon_stats", side_effect=HassioAPIError("add-on is not running"), ), patch( "homeassistant.components.hassio.HassIO.get_addon_changelog", side_effect=HassioAPIError("add-on is not running"), ), patch( "homeassistant.components.hassio.HassIO.get_addon_info", side_effect=HassioAPIError("add-on is not running"), ): result = await async_setup_component( hass, "hassio", {"http": {"server_port": 9999, "server_host": "127.0.0.1"}, "hassio": {}}, ) assert result await hass.async_block_till_done() # Verify that the core update entity does exist state = hass.states.get("update.home_assistant_core_update") assert state assert state.state == "on" assert "Could not fetch stats for test: add-on is not running" in caplog.text
async def download_snapshot(self, slug, output_path): """Download and save a snapshot from Hass.io.""" command = COMMAND_SNAPSHOT_DOWNLOAD.format(slug=slug) try: with async_timeout.timeout(self._backup_timeout): request = await self.web_session.request( "get", f"http://{self._ip}{command}", headers={X_HASSIO: os.environ.get("HASSIO_TOKEN", "")}, timeout=None, ) if request.status not in (200, 400): _LOGGER.error("%s return code %d.", command, request.status) raise HassioAPIError() with open(output_path, "wb") as file: file.write(await request.read()) _LOGGER.info("Downloaded snapshot '%s' to '%s'", slug, output_path) return except asyncio.TimeoutError: _LOGGER.error("Timeout on %s request", command) except aiohttp.ClientError as err: _LOGGER.error("Client error on %s request %s", command, err) except IOError: _LOGGER.error("Failed to download snapshot '%s' to '%s'", slug, output_path) raise HassioAPIError( "Snapshot download failed. Check the logs for more information." )
async def send_command(self, command, method="post", payload=None, timeout=10): """Send API command to Hass.io. This method is a coroutine. """ try: with async_timeout.timeout(timeout): request = await self.web_session.request( method, f"http://{self._ip}{command}", json=payload, headers={X_HASSIO: os.environ.get("HASSIO_TOKEN", "")}, timeout=None, ) if request.status not in (200, 400): _LOGGER.error("%s return code %d.", command, request.status) raise HassioAPIError() answer = await request.json() return answer except asyncio.TimeoutError: raise HassioAPIError("Timeout on %s request" % command) except aiohttp.ClientError as err: raise HassioAPIError("Client error on %s request %s" % (command, err)) raise HassioAPIError("Failed to call %s" % command)
async def test_install_addon_failure(hass, supervisor, addon_installed, install_addon): """Test add-on install failure.""" addon_installed.return_value["version"] = None install_addon.side_effect = HassioAPIError() await setup.async_setup_component(hass, "persistent_notification", {}) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER}) assert result["type"] == "form" assert result["step_id"] == "on_supervisor" result = await hass.config_entries.flow.async_configure( result["flow_id"], {"use_addon": True}) assert result["type"] == "progress" # Make sure the flow continues when the progress task is done. await hass.async_block_till_done() result = await hass.config_entries.flow.async_configure(result["flow_id"]) assert result["type"] == "abort" assert result["reason"] == "addon_install_failed"
async def test_hassio_discovery_startup_done(hass, aioclient_mock, hassio_client): """Test startup and discovery with hass discovery.""" aioclient_mock.get( "http://127.0.0.1/discovery", json={ "result": "ok", "data": { "discovery": [{ "service": "mqtt", "uuid": "test", "addon": "mosquitto", "config": { "broker": "mock-broker", "port": 1883, "username": "******", "password": "******", "protocol": "3.1.1", }, }] }, }, ) aioclient_mock.get( "http://127.0.0.1/addons/mosquitto/info", json={ "result": "ok", "data": { "name": "Mosquitto Test" } }, ) with patch( "homeassistant.components.hassio.HassIO.update_hass_api", Mock(return_value=mock_coro({"result": "ok"})), ), patch( "homeassistant.components.hassio.HassIO." "get_homeassistant_info", Mock(side_effect=HassioAPIError()), ), patch( "homeassistant.components.mqtt." "config_flow.FlowHandler.async_step_hassio", Mock(return_value=mock_coro({"type": "abort"})), ) as mock_mqtt: await hass.async_start() await async_setup_component(hass, "hassio", {}) await hass.async_block_till_done() assert aioclient_mock.call_count == 2 assert mock_mqtt.called mock_mqtt.assert_called_with({ "broker": "mock-broker", "port": 1883, "username": "******", "password": "******", "protocol": "3.1.1", "addon": "Mosquitto Test", })
async def test_coordinator_updates(hass, caplog): """Test coordinator updates.""" await async_setup_component(hass, "homeassistant", {}) with patch.dict(os.environ, MOCK_ENVIRON), patch( "homeassistant.components.hassio.HassIO.refresh_updates" ) as refresh_updates_mock: config_entry = MockConfigEntry(domain=DOMAIN, data={}, unique_id=DOMAIN) config_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert refresh_updates_mock.call_count == 1 with patch("homeassistant.components.hassio.HassIO.refresh_updates", ) as refresh_updates_mock: async_fire_time_changed(hass, dt_util.now() + timedelta(minutes=20)) await hass.async_block_till_done() assert refresh_updates_mock.call_count == 0 with patch("homeassistant.components.hassio.HassIO.refresh_updates", ) as refresh_updates_mock: await hass.services.async_call( "homeassistant", "update_entity", { "entity_id": [ "update.home_assistant_core_update", "update.home_assistant_supervisor_update", ] }, blocking=True, ) assert refresh_updates_mock.call_count == 1 # There is a 10s cooldown on the debouncer async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10)) await hass.async_block_till_done() with patch( "homeassistant.components.hassio.HassIO.refresh_updates", side_effect=HassioAPIError("Unknown"), ) as refresh_updates_mock: await hass.services.async_call( "homeassistant", "update_entity", { "entity_id": [ "update.home_assistant_core_update", "update.home_assistant_supervisor_update", ] }, blocking=True, ) assert refresh_updates_mock.call_count == 1 assert "Error on Supervisor API: Unknown" in caplog.text
def hassio_env(): """Fixture to inject hassio env.""" with patch.dict(os.environ, {"HASSIO": "127.0.0.1"}), patch( "homeassistant.components.hassio.HassIO.is_connected", return_value={"result": "ok", "data": {}}, ), patch.dict(os.environ, {"HASSIO_TOKEN": HASSIO_TOKEN}), patch( "homeassistant.components.hassio.HassIO.get_info", Mock(side_effect=HassioAPIError()), ): yield
async def test_hassio_discovery_startup_done(hass, aioclient_mock, hassio_client): """Test startup and discovery with hass discovery.""" aioclient_mock.get("http://127.0.0.1/discovery", json={ 'result': 'ok', 'data': { 'discovery': [{ "service": "mqtt", "uuid": "test", "addon": "mosquitto", "config": { 'broker': 'mock-broker', 'port': 1883, 'username': '******', 'password': '******', 'protocol': '3.1.1' } }] } }) aioclient_mock.get("http://127.0.0.1/addons/mosquitto/info", json={ 'result': 'ok', 'data': { 'name': "Mosquitto Test" } }) with patch('homeassistant.components.hassio.HassIO.update_hass_api', Mock(return_value=mock_coro({"result": "ok"}))), \ patch('homeassistant.components.hassio.HassIO.' 'get_homeassistant_info', Mock(side_effect=HassioAPIError())), \ patch('homeassistant.components.mqtt.' 'config_flow.FlowHandler.async_step_hassio', Mock(return_value=mock_coro({"type": "abort"})) ) as mock_mqtt: await hass.async_start() await async_setup_component(hass, 'hassio', {'http': { 'api_password': API_PASSWORD }}) await hass.async_block_till_done() assert aioclient_mock.call_count == 2 assert mock_mqtt.called mock_mqtt.assert_called_with({ 'broker': 'mock-broker', 'port': 1883, 'username': '******', 'password': '******', 'protocol': '3.1.1', 'addon': 'Mosquitto Test', })
def hassio_env(): """Fixture to inject hassio env.""" with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}), \ patch('homeassistant.components.hassio.HassIO.is_connected', Mock(return_value=mock_coro( {"result": "ok", "data": {}}))), \ patch.dict(os.environ, {'HASSIO_TOKEN': "123456"}), \ patch('homeassistant.components.hassio.HassIO.' 'get_homeassistant_info', Mock(side_effect=HassioAPIError())): yield
async def test_addon_info_failure(hass, supervisor, addon_info): """Test add-on info failure.""" addon_info.side_effect = HassioAPIError() result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER}) result = await hass.config_entries.flow.async_configure( result["flow_id"], {"use_addon": True}) assert result["type"] == "abort" assert result["reason"] == "addon_info_failed"
def hassio_stubs(hassio_env, hass, hass_client, aioclient_mock): """Create mock hassio http client.""" with patch('homeassistant.components.hassio.HassIO.update_hass_api', Mock(return_value=mock_coro({"result": "ok"}))), \ patch('homeassistant.components.hassio.HassIO.' 'get_homeassistant_info', Mock(side_effect=HassioAPIError())): hass.state = CoreState.starting hass.loop.run_until_complete(async_setup_component(hass, 'hassio', { 'http': { 'api_password': API_PASSWORD } }))
def hassio_stubs(hassio_env, hass, hass_client, aioclient_mock): """Create mock hassio http client.""" with patch( "homeassistant.components.hassio.HassIO.update_hass_api", return_value=mock_coro({"result": "ok"}), ), patch( "homeassistant.components.hassio.HassIO.update_hass_timezone", return_value=mock_coro({"result": "ok"}), ), patch( "homeassistant.components.hassio.HassIO.get_homeassistant_info", side_effect=HassioAPIError(), ): hass.state = CoreState.starting hass.loop.run_until_complete(async_setup_component(hass, "hassio", {}))
async def test_addon_info_failure(hass, supervisor, addon_info): """Test add-on info failure.""" hass.config.components.add("mqtt") addon_info.side_effect = HassioAPIError() await setup.async_setup_component(hass, "persistent_notification", {}) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER}) result = await hass.config_entries.flow.async_configure( result["flow_id"], {"use_addon": True}) assert result["type"] == "abort" assert result["reason"] == "addon_info_failed"
async def get_addons(self, only_installed=True): """Retrieve a list of addons from Hass.io.""" try: result = await self.send_command(COMMAND_GET_ADDONS, method="get") addons = result.get("data", {}).get("addons") if addons is None: raise HassioAPIError("No addons were returned.") if only_installed: return [addon for addon in addons if addon["installed"]] return addons except HassioAPIError as err: _LOGGER.error("Failed to retrieve addons: %s", err) return None
async def test_set_addon_config_failure(hass, supervisor, addon_installed, addon_options, set_addon_options): """Test add-on set config failure.""" set_addon_options.side_effect = HassioAPIError() result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER}) result = await hass.config_entries.flow.async_configure( result["flow_id"], {"use_addon": True}) result = await hass.config_entries.flow.async_configure( result["flow_id"], { "usb_path": "/test", "network_key": "abc123" }) assert result["type"] == "abort" assert result["reason"] == "addon_set_config_failed"
async def test_start_addon_failure( hass, supervisor, addon_installed, addon_options, set_addon_options, start_addon ): """Test add-on start failure.""" start_addon.side_effect = HassioAPIError() await setup.async_setup_component(hass, "persistent_notification", {}) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) result = await hass.config_entries.flow.async_configure( result["flow_id"], {"use_addon": True} ) result = await hass.config_entries.flow.async_configure( result["flow_id"], {"usb_path": "/test", "network_key": "abc123"} ) assert result["type"] == "form" assert result["errors"] == {"base": "addon_start_failed"}
async def test_coordinator_updates(hass, caplog): """Test coordinator.""" with patch.dict(os.environ, MOCK_ENVIRON), patch( "homeassistant.components.hassio.HassIO.refresh_updates" ) as refresh_updates_mock: config_entry = MockConfigEntry(domain=DOMAIN, data={}, unique_id=DOMAIN) config_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert refresh_updates_mock.call_count == 1 with patch( "homeassistant.components.hassio.HassIO.refresh_updates", side_effect=HassioAPIError("Unknown"), ) as refresh_updates_mock: async_fire_time_changed(hass, dt_util.now() + timedelta(minutes=5)) await hass.async_block_till_done() assert refresh_updates_mock.call_count == 1 assert ("Error fetching hassio data: Error on Supervisor API: Unknown" in caplog.text)
await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() assert entry.state is ConfigEntryState.SETUP_RETRY assert install_addon.call_count == 1 assert install_addon.call_args == call(hass, "core_zwave_js") assert set_addon_options.call_count == 1 assert set_addon_options.call_args == call( hass, "core_zwave_js", {"options": addon_options} ) assert start_addon.call_count == 1 assert start_addon.call_args == call(hass, "core_zwave_js") @pytest.mark.parametrize("addon_info_side_effect", [HassioAPIError("Boom")]) async def test_addon_info_failure( hass, addon_installed, install_addon, addon_options, set_addon_options, start_addon, ): """Test failure to get add-on info for Z-Wave JS add-on during entry setup.""" device = "/test" network_key = "abc123" entry = MockConfigEntry( domain=DOMAIN, title="Z-Wave JS", data={"use_addon": True, "usb_path": device, "network_key": network_key},
async def new_snapshot(self, data, full=False): """Create a new snapshot in Hass.io.""" if ATTR_NAME not in data: # provide a default name if none was supplied. data[ATTR_NAME] = datetime.now( self._hass.config.time_zone).strftime("%A, %b %d, %Y") _LOGGER.debug("Creating snapshot %s", data[ATTR_NAME]) command = COMMAND_SNAPSHOT_FULL if full else COMMAND_SNAPSHOT_PARTIAL keep_days = data.pop(ATTR_KEEP_DAYS, None) backup_path = data.pop(ATTR_BACKUP_PATH, None) if full: # performing full backup. exclude = data.pop(ATTR_EXCLUDE, None) if exclude: # handle exclude config. command = COMMAND_SNAPSHOT_PARTIAL # append addons. addons = await self.get_addons() if addons: excluded_addons = await self._replace_addon_names( exclude[ATTR_ADDONS], addons) data[ATTR_ADDONS] = [ addon["slug"] for addon in addons if addon["slug"] not in excluded_addons ] # append folders. excluded_folders = self._replace_folder_names( exclude[ATTR_FOLDERS]) data[ATTR_FOLDERS] = [ folder for folder in DEFAULT_SNAPSHOT_FOLDERS.values() if folder not in excluded_folders ] else: # performing partial backup. # replace addon names with their appropriate slugs. if ATTR_ADDONS in data: data[ATTR_ADDONS] = await self._replace_addon_names( data[ATTR_ADDONS]) # replace friendly folder names. if ATTR_FOLDERS in data: data[ATTR_FOLDERS] = self._replace_folder_names( data[ATTR_FOLDERS]) # ensure password is scrubbed from logs. password = data.get(ATTR_PASSWORD) if password: data[ATTR_PASSWORD] = "<hidden>" _LOGGER.debug( "New snapshot; command: %s, keep_days: %s, data: %s, timeout: %s", command, keep_days, data, self._backup_timeout, ) # re-add password if it existed. if password: data[ATTR_PASSWORD] = password del password # remove from memory # add to pending snapshots and update sensor. self._pending_snapshots += 1 if self.update_sensor_callback: self.update_sensor_callback() # make request to create new snapshot. try: result = await self.send_command(command, payload=data, timeout=self._backup_timeout) _LOGGER.debug("Snapshot create result: %s" % result) slug = result.get("data", {}).get("slug") if slug is None: error = "There may be a backup already in progress." if data.get("message"): error = f"{error} {data.get('message')}" raise HassioAPIError(error) # snapshot creation was successful _LOGGER.info("Snapshot created successfully; '%s' (%s)", data[ATTR_NAME], slug) self._hass.bus.async_fire(f"{DOMAIN}.snapshot_successful", { "name": data[ATTR_NAME], "slug": slug }) if keep_days is not None: # set snapshot expiry self._snapshots_expiry[slug] = datetime.now( timezone.utc) + timedelta(days=float(keep_days)) # write snapshot expiry to storage await self._snapshots_store.async_save(self._snapshots_expiry) # copy snapshot to location if specified if backup_path: await self.copy_snapshot(data[ATTR_NAME], slug, backup_path) except HassioAPIError as err: _LOGGER.error("Error during backup. %s", err) self._hass.bus.async_fire( f"{DOMAIN}.snapshot_failed", { "name": data[ATTR_NAME], "error": str(err) }, ) self.last_failure = data[ATTR_NAME] # remove from pending snapshots and update sensor. self._pending_snapshots -= 1 if self.update_sensor_callback: self.update_sensor_callback() # purging old snapshots if self._auto_purge: await self.purge_snapshots()
entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() assert entry.state == ENTRY_STATE_SETUP_RETRY assert install_addon.call_count == 1 assert install_addon.call_args == call(hass, "core_zwave_js") assert set_addon_options.call_count == 1 assert set_addon_options.call_args == call(hass, "core_zwave_js", {"options": addon_options}) assert start_addon.call_count == 1 assert start_addon.call_args == call(hass, "core_zwave_js") @pytest.mark.parametrize("addon_info_side_effect", [HassioAPIError("Boom")]) async def test_addon_info_failure( hass, addon_installed, install_addon, addon_options, set_addon_options, start_addon, ): """Test failure to get add-on info for Z-Wave JS add-on during entry setup.""" device = "/test" network_key = "abc123" entry = MockConfigEntry( domain=DOMAIN, title="Z-Wave JS", connection_class=CONN_CLASS_LOCAL_PUSH,
async def test_remove_entry(hass, stop_addon, uninstall_addon, caplog): """Test remove the config entry.""" # test successful remove without created add-on entry = MockConfigEntry( domain=DOMAIN, title="Z-Wave", connection_class=config_entries.CONN_CLASS_LOCAL_PUSH, data={"integration_created_addon": False}, ) entry.add_to_hass(hass) assert entry.state == config_entries.ENTRY_STATE_NOT_LOADED assert len(hass.config_entries.async_entries(DOMAIN)) == 1 await hass.config_entries.async_remove(entry.entry_id) assert entry.state == config_entries.ENTRY_STATE_NOT_LOADED assert len(hass.config_entries.async_entries(DOMAIN)) == 0 # test successful remove with created add-on entry = MockConfigEntry( domain=DOMAIN, title="Z-Wave", connection_class=config_entries.CONN_CLASS_LOCAL_PUSH, data={"integration_created_addon": True}, ) entry.add_to_hass(hass) assert len(hass.config_entries.async_entries(DOMAIN)) == 1 await hass.config_entries.async_remove(entry.entry_id) assert stop_addon.call_count == 1 assert uninstall_addon.call_count == 1 assert entry.state == config_entries.ENTRY_STATE_NOT_LOADED assert len(hass.config_entries.async_entries(DOMAIN)) == 0 stop_addon.reset_mock() uninstall_addon.reset_mock() # test add-on stop failure entry.add_to_hass(hass) assert len(hass.config_entries.async_entries(DOMAIN)) == 1 stop_addon.side_effect = HassioAPIError() await hass.config_entries.async_remove(entry.entry_id) assert stop_addon.call_count == 1 assert uninstall_addon.call_count == 0 assert entry.state == config_entries.ENTRY_STATE_NOT_LOADED assert len(hass.config_entries.async_entries(DOMAIN)) == 0 assert "Failed to stop the OpenZWave add-on" in caplog.text stop_addon.side_effect = None stop_addon.reset_mock() uninstall_addon.reset_mock() # test add-on uninstall failure entry.add_to_hass(hass) assert len(hass.config_entries.async_entries(DOMAIN)) == 1 uninstall_addon.side_effect = HassioAPIError() await hass.config_entries.async_remove(entry.entry_id) assert stop_addon.call_count == 1 assert uninstall_addon.call_count == 1 assert entry.state == config_entries.ENTRY_STATE_NOT_LOADED assert len(hass.config_entries.async_entries(DOMAIN)) == 0 assert "Failed to uninstall the OpenZWave add-on" in caplog.text
async def test_remove_entry( hass, addon_installed, stop_addon, create_shapshot, uninstall_addon, caplog ): """Test remove the config entry.""" # test successful remove without created add-on entry = MockConfigEntry( domain=DOMAIN, title="Z-Wave JS", data={"integration_created_addon": False}, ) entry.add_to_hass(hass) assert entry.state is ConfigEntryState.NOT_LOADED assert len(hass.config_entries.async_entries(DOMAIN)) == 1 await hass.config_entries.async_remove(entry.entry_id) assert entry.state is ConfigEntryState.NOT_LOADED assert len(hass.config_entries.async_entries(DOMAIN)) == 0 # test successful remove with created add-on entry = MockConfigEntry( domain=DOMAIN, title="Z-Wave JS", data={"integration_created_addon": True}, ) entry.add_to_hass(hass) assert len(hass.config_entries.async_entries(DOMAIN)) == 1 await hass.config_entries.async_remove(entry.entry_id) assert stop_addon.call_count == 1 assert stop_addon.call_args == call(hass, "core_zwave_js") assert create_shapshot.call_count == 1 assert create_shapshot.call_args == call( hass, {"name": "addon_core_zwave_js_1.0", "addons": ["core_zwave_js"]}, partial=True, ) assert uninstall_addon.call_count == 1 assert uninstall_addon.call_args == call(hass, "core_zwave_js") assert entry.state is ConfigEntryState.NOT_LOADED assert len(hass.config_entries.async_entries(DOMAIN)) == 0 stop_addon.reset_mock() create_shapshot.reset_mock() uninstall_addon.reset_mock() # test add-on stop failure entry.add_to_hass(hass) assert len(hass.config_entries.async_entries(DOMAIN)) == 1 stop_addon.side_effect = HassioAPIError() await hass.config_entries.async_remove(entry.entry_id) assert stop_addon.call_count == 1 assert stop_addon.call_args == call(hass, "core_zwave_js") assert create_shapshot.call_count == 0 assert uninstall_addon.call_count == 0 assert entry.state is ConfigEntryState.NOT_LOADED assert len(hass.config_entries.async_entries(DOMAIN)) == 0 assert "Failed to stop the Z-Wave JS add-on" in caplog.text stop_addon.side_effect = None stop_addon.reset_mock() create_shapshot.reset_mock() uninstall_addon.reset_mock() # test create snapshot failure entry.add_to_hass(hass) assert len(hass.config_entries.async_entries(DOMAIN)) == 1 create_shapshot.side_effect = HassioAPIError() await hass.config_entries.async_remove(entry.entry_id) assert stop_addon.call_count == 1 assert stop_addon.call_args == call(hass, "core_zwave_js") assert create_shapshot.call_count == 1 assert create_shapshot.call_args == call( hass, {"name": "addon_core_zwave_js_1.0", "addons": ["core_zwave_js"]}, partial=True, ) assert uninstall_addon.call_count == 0 assert entry.state is ConfigEntryState.NOT_LOADED assert len(hass.config_entries.async_entries(DOMAIN)) == 0 assert "Failed to create a snapshot of the Z-Wave JS add-on" in caplog.text create_shapshot.side_effect = None stop_addon.reset_mock() create_shapshot.reset_mock() uninstall_addon.reset_mock() # test add-on uninstall failure entry.add_to_hass(hass) assert len(hass.config_entries.async_entries(DOMAIN)) == 1 uninstall_addon.side_effect = HassioAPIError() await hass.config_entries.async_remove(entry.entry_id) assert stop_addon.call_count == 1 assert stop_addon.call_args == call(hass, "core_zwave_js") assert create_shapshot.call_count == 1 assert create_shapshot.call_args == call( hass, {"name": "addon_core_zwave_js_1.0", "addons": ["core_zwave_js"]}, partial=True, ) assert uninstall_addon.call_count == 1 assert uninstall_addon.call_args == call(hass, "core_zwave_js") assert entry.state is ConfigEntryState.NOT_LOADED assert len(hass.config_entries.async_entries(DOMAIN)) == 0 assert "Failed to uninstall the Z-Wave JS add-on" in caplog.text
"use_addon": True, "integration_created_addon": False, } assert len(mock_setup.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1 @pytest.mark.parametrize( "discovery_info, discovery_info_side_effect, server_version_side_effect, " "addon_info_side_effect, abort_reason", [ ( { "config": ADDON_DISCOVERY_INFO }, HassioAPIError(), None, None, "addon_get_discovery_info_failed", ), ( { "config": ADDON_DISCOVERY_INFO }, None, asyncio.TimeoutError, None, "cannot_connect", ), ( None,
"use_addon": True, "integration_created_addon": False, } assert len(mock_setup.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1 @pytest.mark.parametrize( "discovery_info, discovery_info_side_effect, server_version_side_effect, " "addon_info_side_effect, abort_reason", [ ( { "config": ADDON_DISCOVERY_INFO }, HassioAPIError(), None, None, "addon_get_discovery_info_failed", ), ( { "config": ADDON_DISCOVERY_INFO }, None, asyncio.TimeoutError, None, "cannot_connect", ), ( None,