mirror of
https://github.com/home-assistant/core.git
synced 2026-07-01 19:57:08 +01:00
Support Yardian YC models (#172347)
Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
@@ -21,7 +21,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: YardianConfigEntry) -> b
|
||||
host = entry.data[CONF_HOST]
|
||||
access_token = entry.data[CONF_ACCESS_TOKEN]
|
||||
|
||||
controller = AsyncYardianClient(async_get_clientsession(hass), host, access_token)
|
||||
# Change this line to use .create()
|
||||
# This ensures the coordinator's controller knows if it is YP or YC
|
||||
controller = await AsyncYardianClient.create(
|
||||
async_get_clientsession(hass), host, token=access_token
|
||||
)
|
||||
|
||||
coordinator = YardianUpdateCoordinator(hass, entry, controller)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
|
||||
@@ -34,10 +34,10 @@ class YardianConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
async def async_fetch_device_info(self, host: str, access_token: str) -> DeviceInfo:
|
||||
"""Fetch device info from Yardian."""
|
||||
yarcli = AsyncYardianClient(
|
||||
yarcli = await AsyncYardianClient.create(
|
||||
async_get_clientsession(self.hass),
|
||||
host,
|
||||
access_token,
|
||||
token=access_token,
|
||||
)
|
||||
return await yarcli.fetch_device_info()
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ def mock_config_entry() -> MockConfigEntry:
|
||||
CONF_ACCESS_TOKEN: "abc",
|
||||
CONF_NAME: "Yardian",
|
||||
"yid": "yid123",
|
||||
"model": "PRO1902",
|
||||
"model": "PRO1902C1",
|
||||
"serialNumber": "SN1",
|
||||
},
|
||||
title="Yardian Smart Sprinkler",
|
||||
@@ -48,12 +48,17 @@ def mock_yardian_client() -> Generator[AsyncMock]:
|
||||
) as client_cls,
|
||||
patch(
|
||||
"homeassistant.components.yardian.config_flow.AsyncYardianClient",
|
||||
autospec=True,
|
||||
) as flow_client_cls,
|
||||
new=client_cls,
|
||||
),
|
||||
):
|
||||
client = client_cls.return_value
|
||||
flow_client_cls.return_value = client
|
||||
|
||||
client_cls.create.return_value = client
|
||||
|
||||
client.fetch_device_info.return_value = {
|
||||
"name": "fake_name",
|
||||
"yid": "fake_yid",
|
||||
}
|
||||
client.fetch_device_state.return_value = YardianDeviceState(
|
||||
zones=[["Zone 1", 1], ["Zone 2", 0]],
|
||||
active_zones={0},
|
||||
|
||||
@@ -1,189 +1,76 @@
|
||||
"""Test the Yardian config flow."""
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
import pytest
|
||||
from pyyardian import NetworkException, NotAuthorizedException
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.yardian.const import DOMAIN, PRODUCT_NAME
|
||||
from homeassistant.config_entries import SOURCE_USER
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
|
||||
pytestmark = pytest.mark.usefixtures("mock_setup_entry")
|
||||
pytestmark = pytest.mark.usefixtures("mock_setup_entry", "mock_yardian_client")
|
||||
|
||||
|
||||
async def test_form(hass: HomeAssistant, mock_setup_entry: AsyncMock) -> None:
|
||||
async def test_form(hass: HomeAssistant) -> None:
|
||||
"""Test we get the form."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["errors"] == {}
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.yardian.config_flow.AsyncYardianClient.fetch_device_info",
|
||||
return_value={"name": "fake_name", "yid": "fake_yid"},
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
"host": "fake_host",
|
||||
"access_token": "fake_token",
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{"host": "fake_host", "access_token": "fake_token"},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == PRODUCT_NAME
|
||||
assert result2["data"] == {
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == PRODUCT_NAME
|
||||
assert result["data"] == {
|
||||
"host": "fake_host",
|
||||
"access_token": "fake_token",
|
||||
"name": "fake_name",
|
||||
"yid": "fake_yid",
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_form_invalid_auth(
|
||||
hass: HomeAssistant, mock_setup_entry: AsyncMock
|
||||
@pytest.mark.parametrize(
|
||||
("exception", "error"),
|
||||
[
|
||||
(NotAuthorizedException, "invalid_auth"),
|
||||
(NetworkException, "cannot_connect"),
|
||||
(Exception, "unknown"),
|
||||
],
|
||||
)
|
||||
async def test_form_errors(
|
||||
hass: HomeAssistant,
|
||||
mock_yardian_client: AsyncMock,
|
||||
exception: Exception,
|
||||
error: str,
|
||||
) -> None:
|
||||
"""Test we handle invalid auth."""
|
||||
"""Test we handle errors and recover."""
|
||||
mock_yardian_client.fetch_device_info.side_effect = exception
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.yardian.config_flow.AsyncYardianClient.fetch_device_info",
|
||||
side_effect=NotAuthorizedException,
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
"host": "fake_host",
|
||||
"access_token": "fake_token",
|
||||
},
|
||||
)
|
||||
|
||||
assert result2["type"] is FlowResultType.FORM
|
||||
assert result2["errors"] == {"base": "invalid_auth"}
|
||||
|
||||
# Should be recoverable after hits error
|
||||
with patch(
|
||||
"homeassistant.components.yardian.config_flow.AsyncYardianClient.fetch_device_info",
|
||||
return_value={"name": "fake_name", "yid": "fake_yid"},
|
||||
):
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
"host": "fake_host",
|
||||
"access_token": "fake_token",
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result3["title"] == PRODUCT_NAME
|
||||
assert result3["data"] == {
|
||||
"host": "fake_host",
|
||||
"access_token": "fake_token",
|
||||
"name": "fake_name",
|
||||
"yid": "fake_yid",
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_form_cannot_connect(
|
||||
hass: HomeAssistant, mock_setup_entry: AsyncMock
|
||||
) -> None:
|
||||
"""Test we handle cannot connect error."""
|
||||
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"],
|
||||
{"host": "fake_host", "access_token": "fake_token"},
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.yardian.config_flow.AsyncYardianClient.fetch_device_info",
|
||||
side_effect=NetworkException,
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
"host": "fake_host",
|
||||
"access_token": "fake_token",
|
||||
},
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["errors"] == {"base": error}
|
||||
|
||||
assert result2["type"] is FlowResultType.FORM
|
||||
assert result2["errors"] == {"base": "cannot_connect"}
|
||||
mock_yardian_client.fetch_device_info.side_effect = None
|
||||
|
||||
# Should be recoverable after hits error
|
||||
with patch(
|
||||
"homeassistant.components.yardian.config_flow.AsyncYardianClient.fetch_device_info",
|
||||
return_value={"name": "fake_name", "yid": "fake_yid"},
|
||||
):
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
"host": "fake_host",
|
||||
"access_token": "fake_token",
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result3["title"] == PRODUCT_NAME
|
||||
assert result3["data"] == {
|
||||
"host": "fake_host",
|
||||
"access_token": "fake_token",
|
||||
"name": "fake_name",
|
||||
"yid": "fake_yid",
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_form_uncategorized_error(
|
||||
hass: HomeAssistant, mock_setup_entry: AsyncMock
|
||||
) -> None:
|
||||
"""Test we handle uncategorized error."""
|
||||
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"],
|
||||
{"host": "fake_host", "access_token": "fake_token"},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.yardian.config_flow.AsyncYardianClient.fetch_device_info",
|
||||
side_effect=Exception,
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
"host": "fake_host",
|
||||
"access_token": "fake_token",
|
||||
},
|
||||
)
|
||||
|
||||
assert result2["type"] is FlowResultType.FORM
|
||||
assert result2["errors"] == {"base": "unknown"}
|
||||
|
||||
# Should be recoverable after hits error
|
||||
with patch(
|
||||
"homeassistant.components.yardian.config_flow.AsyncYardianClient.fetch_device_info",
|
||||
return_value={"name": "fake_name", "yid": "fake_yid"},
|
||||
):
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
"host": "fake_host",
|
||||
"access_token": "fake_token",
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result3["title"] == PRODUCT_NAME
|
||||
assert result3["data"] == {
|
||||
"host": "fake_host",
|
||||
"access_token": "fake_token",
|
||||
"name": "fake_name",
|
||||
"yid": "fake_yid",
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
|
||||
Reference in New Issue
Block a user