Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion homeassistant/components/duco/diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from dataclasses import asdict
from typing import Any

from duco_connectivity.exceptions import DucoConnectionError
from duco_connectivity.exceptions import DucoConnectionError, DucoError

from homeassistant.components.diagnostics import async_redact_data
from homeassistant.const import CONF_HOST
Expand Down Expand Up @@ -52,6 +52,12 @@ async def async_get_config_entry_diagnostics(
translation_domain=DOMAIN,
translation_key="connection_error",
) from err
except DucoError as err:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="api_error",
translation_placeholders={"error": repr(err)},
) from err

api_info: dict[str, Any] = {"public_api_version": api_info_obj.public_api_version}
if api_info_obj.reported_api_version is not None:
Expand Down
50 changes: 36 additions & 14 deletions tests/components/duco/test_diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
from http import HTTPStatus
from unittest.mock import AsyncMock

from duco_connectivity import ApiInfo, DucoConnectionError
from duco_connectivity import ApiInfo
from duco_connectivity.exceptions import (
DucoConnectionError,
DucoError,
DucoResponseError,
)
import pytest
from syrupy.assertion import SnapshotAssertion

Expand All @@ -16,6 +21,29 @@
from tests.components.diagnostics import get_diagnostics_for_config_entry
from tests.typing import ClientSessionGenerator

CLIENT_ERROR_CASES = [
pytest.param(
"async_get_api_info",
DucoConnectionError("Server disconnected"),
id="api-info-connection-error",
),
pytest.param(
"async_get_lan_info",
DucoConnectionError("Server disconnected"),
id="lan-info-connection-error",
),
pytest.param(
"async_get_diagnostics",
DucoResponseError(500, "/info", "bad response"),
id="diagnostics-response-error",
),
pytest.param(
"async_get_write_requests_remaining",
DucoResponseError(500, "/info", "bad response"),
id="write-budget-response-error",
),
]


@pytest.mark.usefixtures("init_integration")
async def test_diagnostics(
Expand All @@ -34,25 +62,19 @@ async def test_diagnostics(

@pytest.mark.usefixtures("init_integration")
@pytest.mark.parametrize(
"failing_method",
[
"async_get_api_info",
"async_get_lan_info",
"async_get_diagnostics",
"async_get_write_requests_remaining",
],
("failing_method", "raised_error"),
CLIENT_ERROR_CASES,
)
async def test_diagnostics_connection_error(
async def test_diagnostics_client_error(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
mock_config_entry: MockConfigEntry,
mock_duco_client: AsyncMock,
failing_method: str,
raised_error: DucoError,
) -> None:
"""Test that a connection error during diagnostics returns a 500 response."""
getattr(mock_duco_client, failing_method).side_effect = DucoConnectionError(
"Server disconnected"
)
"""Test that client errors during diagnostics return a 500 response."""
getattr(mock_duco_client, failing_method).side_effect = raised_error
assert await async_setup_component(hass, DIAGNOSTICS_DOMAIN, {})
await hass.async_block_till_done()
client = await hass_client()
Expand All @@ -70,7 +92,7 @@ async def test_diagnostics_without_optional_software_version(
) -> None:
"""Test that an optional software version is omitted from diagnostics."""
# BoardInfo is a frozen dataclass, so the mock must be updated before
# integration setup the coordinator stores board_info during async_setup.
# integration setup - the coordinator stores board_info during async_setup.
mock_duco_client.async_get_board_info.return_value = replace(
mock_duco_client.async_get_board_info.return_value,
software_version=None,
Expand Down
Loading