Raise ConfigEntryNotReady mqtt setup fails In LG ThinQ (#140488)
Co-authored-by: yunseon.park <yunseon.park@lge.com>pull/135772/merge
parent
35f9cc55f1
commit
83f2acddf8
|
@ -22,7 +22,7 @@ from homeassistant.helpers import device_registry as dr
|
|||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
|
||||
from .const import CONF_CONNECT_CLIENT_ID, MQTT_SUBSCRIPTION_INTERVAL
|
||||
from .const import CONF_CONNECT_CLIENT_ID, DOMAIN, MQTT_SUBSCRIPTION_INTERVAL
|
||||
from .coordinator import DeviceDataUpdateCoordinator, async_setup_device_coordinator
|
||||
from .mqtt import ThinQMQTT
|
||||
|
||||
|
@ -137,7 +137,15 @@ async def async_setup_mqtt(
|
|||
entry.runtime_data.mqtt_client = mqtt_client
|
||||
|
||||
# Try to connect.
|
||||
result = await mqtt_client.async_connect()
|
||||
try:
|
||||
result = await mqtt_client.async_connect()
|
||||
except (AttributeError, ThinQAPIException, TypeError, ValueError) as exc:
|
||||
raise ConfigEntryNotReady(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="failed_to_connect_mqtt",
|
||||
translation_placeholders={"error": str(exc)},
|
||||
) from exc
|
||||
|
||||
if not result:
|
||||
_LOGGER.error("Failed to set up mqtt connection")
|
||||
return
|
||||
|
|
|
@ -43,19 +43,16 @@ class ThinQMQTT:
|
|||
|
||||
async def async_connect(self) -> bool:
|
||||
"""Create a mqtt client and then try to connect."""
|
||||
try:
|
||||
self.client = await ThinQMQTTClient(
|
||||
self.thinq_api, self.client_id, self.on_message_received
|
||||
)
|
||||
if self.client is None:
|
||||
return False
|
||||
|
||||
# Connect to server and create certificate.
|
||||
return await self.client.async_prepare_mqtt()
|
||||
except (ThinQAPIException, TypeError, ValueError):
|
||||
_LOGGER.exception("Failed to connect")
|
||||
self.client = await ThinQMQTTClient(
|
||||
self.thinq_api, self.client_id, self.on_message_received
|
||||
)
|
||||
if self.client is None:
|
||||
return False
|
||||
|
||||
# Connect to server and create certificate.
|
||||
return await self.client.async_prepare_mqtt()
|
||||
|
||||
async def async_disconnect(self, event: Event | None = None) -> None:
|
||||
"""Unregister client and disconnects handlers."""
|
||||
await self.async_end_subscribes()
|
||||
|
|
|
@ -1034,5 +1034,10 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"exceptions": {
|
||||
"failed_to_connect_mqtt": {
|
||||
"message": "Failed to connect MQTT: {error}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ def mock_uuid() -> Generator[AsyncMock]:
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_thinq_api(mock_thinq_mqtt_client: AsyncMock) -> Generator[AsyncMock]:
|
||||
def mock_config_thinq_api() -> Generator[AsyncMock]:
|
||||
"""Mock a thinq api."""
|
||||
with (
|
||||
patch("homeassistant.components.lg_thinq.ThinQApi", autospec=True) as mock_api,
|
||||
|
@ -77,6 +77,26 @@ def mock_thinq_api(mock_thinq_mqtt_client: AsyncMock) -> Generator[AsyncMock]:
|
|||
new=mock_api,
|
||||
),
|
||||
):
|
||||
thinq_api = mock_api.return_value
|
||||
thinq_api.async_get_device_list.return_value = ["air_conditioner"]
|
||||
yield thinq_api
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_invalid_thinq_api(mock_config_thinq_api: AsyncMock) -> AsyncMock:
|
||||
"""Mock an invalid thinq api."""
|
||||
mock_config_thinq_api.async_get_device_list = AsyncMock(
|
||||
side_effect=ThinQAPIException(
|
||||
code="1309", message="Not allowed api call", headers=None
|
||||
)
|
||||
)
|
||||
return mock_config_thinq_api
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_thinq_api() -> Generator[AsyncMock]:
|
||||
"""Mock a thinq api."""
|
||||
with patch("homeassistant.components.lg_thinq.ThinQApi", autospec=True) as mock_api:
|
||||
thinq_api = mock_api.return_value
|
||||
thinq_api.async_get_device_list.return_value = [
|
||||
load_json_object_fixture("air_conditioner/device.json", DOMAIN)
|
||||
|
@ -92,19 +112,10 @@ def mock_thinq_api(mock_thinq_mqtt_client: AsyncMock) -> Generator[AsyncMock]:
|
|||
|
||||
@pytest.fixture
|
||||
def mock_thinq_mqtt_client() -> Generator[AsyncMock]:
|
||||
"""Mock a thinq api."""
|
||||
"""Mock a thinq mqtt client."""
|
||||
with patch(
|
||||
"homeassistant.components.lg_thinq.mqtt.ThinQMQTTClient", autospec=True
|
||||
) as mock_api:
|
||||
yield mock_api
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_invalid_thinq_api(mock_thinq_api: AsyncMock) -> AsyncMock:
|
||||
"""Mock an invalid thinq api."""
|
||||
mock_thinq_api.async_get_device_list = AsyncMock(
|
||||
side_effect=ThinQAPIException(
|
||||
code="1309", message="Not allowed api call", headers=None
|
||||
)
|
||||
)
|
||||
return mock_thinq_api
|
||||
"homeassistant.components.lg_thinq.mqtt.ThinQMQTTClient",
|
||||
autospec=True,
|
||||
return_value=True,
|
||||
):
|
||||
yield
|
||||
|
|
|
@ -15,7 +15,7 @@ from tests.common import MockConfigEntry
|
|||
|
||||
async def test_config_flow(
|
||||
hass: HomeAssistant,
|
||||
mock_thinq_api: AsyncMock,
|
||||
mock_config_thinq_api: AsyncMock,
|
||||
mock_uuid: AsyncMock,
|
||||
mock_setup_entry: AsyncMock,
|
||||
) -> None:
|
||||
|
@ -37,11 +37,12 @@ async def test_config_flow(
|
|||
CONF_CONNECT_CLIENT_ID: MOCK_CONNECT_CLIENT_ID,
|
||||
}
|
||||
|
||||
mock_thinq_api.async_get_device_list.assert_called_once()
|
||||
mock_config_thinq_api.async_get_device_list.assert_called_once()
|
||||
|
||||
|
||||
async def test_config_flow_invalid_pat(
|
||||
hass: HomeAssistant, mock_invalid_thinq_api: AsyncMock
|
||||
hass: HomeAssistant,
|
||||
mock_invalid_thinq_api: AsyncMock,
|
||||
) -> None:
|
||||
"""Test that an thinq flow should be aborted with an invalid PAT."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -55,7 +56,9 @@ async def test_config_flow_invalid_pat(
|
|||
|
||||
|
||||
async def test_config_flow_already_configured(
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_thinq_api: AsyncMock
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_config_thinq_api: AsyncMock,
|
||||
) -> None:
|
||||
"""Test that thinq flow should be aborted when already configured."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
|
|
@ -1,22 +1,29 @@
|
|||
"""Tests for the LG ThinQ integration."""
|
||||
|
||||
from unittest.mock import AsyncMock
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import setup_integration
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_load_unload_entry(
|
||||
hass: HomeAssistant,
|
||||
mock_thinq_api: AsyncMock,
|
||||
mock_thinq_mqtt_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test load and unload entry."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.lg_thinq.ThinQMQTT.async_connect",
|
||||
return_value=True,
|
||||
):
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
assert mock_config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
|
@ -24,3 +31,21 @@ async def test_load_unload_entry(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exception", [AttributeError(), TypeError(), ValueError()])
|
||||
async def test_config_not_ready(
|
||||
hass: HomeAssistant,
|
||||
mock_thinq_api: AsyncMock,
|
||||
mock_thinq_mqtt_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
"""Test for setup failure exception occurred."""
|
||||
with patch(
|
||||
"homeassistant.components.lg_thinq.ThinQMQTT.async_connect",
|
||||
side_effect=exception,
|
||||
):
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
|
Loading…
Reference in New Issue