Пример #1
0
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
Пример #2
0
    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."
        )
Пример #3
0
    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)
Пример #4
0
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"
Пример #5
0
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",
        })
Пример #6
0
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
Пример #7
0
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
Пример #8
0
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',
        })
Пример #9
0
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
Пример #10
0
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"
Пример #11
0
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
            }
        }))
Пример #12
0
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", {}))
Пример #13
0
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"
Пример #14
0
    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
Пример #15
0
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"
Пример #16
0
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"}
Пример #17
0
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)
Пример #18
0
    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},
Пример #19
0
    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()
Пример #20
0
    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,
Пример #21
0
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
Пример #22
0
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
Пример #23
0
        "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,
Пример #24
0
        "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,