mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 20:27:08 +00:00
Fix authentication error when adding new devices to SMLIGHT (#138373)
* Fix authentication issue Fixes #138216 * Fix incorrect mocks in unsupported device tests * set _device_name in auth flow also * Update get_info Mock to handle authentication * Update tests
This commit is contained in:
parent
6ef1178a35
commit
a3cde3d8ab
@ -77,12 +77,14 @@ class SmlightConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
if user_input is not None:
|
||||
try:
|
||||
info = await self.client.get_info()
|
||||
|
||||
if info.model not in Devices:
|
||||
return self.async_abort(reason="unsupported_device")
|
||||
|
||||
if not await self._async_check_auth_required(user_input):
|
||||
info = await self.client.get_info()
|
||||
self._host = str(info.device_ip)
|
||||
self._device_name = str(info.hostname)
|
||||
|
||||
if info.model not in Devices:
|
||||
return self.async_abort(reason="unsupported_device")
|
||||
|
||||
return await self._async_complete_entry(user_input)
|
||||
except SmlightConnectionError:
|
||||
return self.async_abort(reason="cannot_connect")
|
||||
|
@ -3,6 +3,7 @@
|
||||
from collections.abc import AsyncGenerator, Generator
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from pysmlight.exceptions import SmlightAuthError
|
||||
from pysmlight.sse import sseClient
|
||||
from pysmlight.web import CmdWrapper, Firmware, Info, Sensors
|
||||
import pytest
|
||||
@ -81,9 +82,16 @@ def mock_smlight_client(request: pytest.FixtureRequest) -> Generator[MagicMock]:
|
||||
):
|
||||
api = smlight_mock.return_value
|
||||
api.host = MOCK_HOST
|
||||
api.get_info.return_value = Info.from_dict(
|
||||
load_json_object_fixture("info.json", DOMAIN)
|
||||
)
|
||||
|
||||
def get_info_side_effect(*args, **kwargs) -> Info:
|
||||
"""Return the info."""
|
||||
if api.check_auth_needed.return_value and not api.authenticate.called:
|
||||
raise SmlightAuthError
|
||||
|
||||
return Info.from_dict(load_json_object_fixture("info.json", DOMAIN))
|
||||
|
||||
api.get_info.side_effect = get_info_side_effect
|
||||
|
||||
api.get_sensors.return_value = Sensors.from_dict(
|
||||
load_json_object_fixture("sensors.json", DOMAIN)
|
||||
)
|
||||
|
@ -45,6 +45,7 @@ async def test_buttons(
|
||||
mock_smlight_client: MagicMock,
|
||||
) -> None:
|
||||
"""Test creation of button entities."""
|
||||
mock_smlight_client.get_info.side_effect = None
|
||||
mock_smlight_client.get_info.return_value = MOCK_ROUTER
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
@ -78,6 +79,7 @@ async def test_disabled_by_default_buttons(
|
||||
mock_smlight_client: MagicMock,
|
||||
) -> None:
|
||||
"""Test the disabled by default buttons."""
|
||||
mock_smlight_client.get_info.side_effect = None
|
||||
mock_smlight_client.get_info.return_value = MOCK_ROUTER
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
@ -96,7 +98,8 @@ async def test_remove_router_reconnect(
|
||||
mock_smlight_client: MagicMock,
|
||||
) -> None:
|
||||
"""Test removal of orphaned router reconnect button."""
|
||||
save_mock = mock_smlight_client.get_info.return_value
|
||||
save_mock = mock_smlight_client.get_info.side_effect
|
||||
mock_smlight_client.get_info.side_effect = None
|
||||
mock_smlight_client.get_info.return_value = MOCK_ROUTER
|
||||
mock_config_entry = await setup_integration(hass, mock_config_entry)
|
||||
|
||||
@ -106,7 +109,7 @@ async def test_remove_router_reconnect(
|
||||
assert len(entities) == 4
|
||||
assert entities[3].unique_id == "aa:bb:cc:dd:ee:ff-reconnect_zigbee_router"
|
||||
|
||||
mock_smlight_client.get_info.return_value = save_mock
|
||||
mock_smlight_client.get_info.side_effect = save_mock
|
||||
|
||||
freezer.tick(SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
|
@ -66,6 +66,46 @@ async def test_user_flow(hass: HomeAssistant, mock_setup_entry: AsyncMock) -> No
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_user_flow_auth(
|
||||
hass: HomeAssistant, mock_smlight_client: MagicMock, mock_setup_entry: AsyncMock
|
||||
) -> None:
|
||||
"""Test the full manual user flow with authentication."""
|
||||
|
||||
mock_smlight_client.check_auth_needed.return_value = True
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {}
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_HOST: "slzb-06p7.local",
|
||||
},
|
||||
)
|
||||
assert result2["type"] is FlowResultType.FORM
|
||||
assert result2["step_id"] == "auth"
|
||||
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_USERNAME: MOCK_USERNAME,
|
||||
CONF_PASSWORD: MOCK_PASSWORD,
|
||||
},
|
||||
)
|
||||
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result3["title"] == "SLZB-06p7"
|
||||
assert result3["data"] == {
|
||||
CONF_USERNAME: MOCK_USERNAME,
|
||||
CONF_PASSWORD: MOCK_PASSWORD,
|
||||
CONF_HOST: MOCK_HOST,
|
||||
}
|
||||
assert result3["context"]["unique_id"] == "aa:bb:cc:dd:ee:ff"
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_zeroconf_flow(
|
||||
hass: HomeAssistant,
|
||||
mock_smlight_client: MagicMock,
|
||||
@ -145,7 +185,7 @@ async def test_zeroconf_flow_auth(
|
||||
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result3["context"]["source"] == "zeroconf"
|
||||
assert result3["context"]["unique_id"] == "aa:bb:cc:dd:ee:ff"
|
||||
assert result3["title"] == "slzb-06"
|
||||
assert result3["title"] == "SLZB-06p7"
|
||||
assert result3["data"] == {
|
||||
CONF_USERNAME: MOCK_USERNAME,
|
||||
CONF_PASSWORD: MOCK_PASSWORD,
|
||||
@ -162,6 +202,7 @@ async def test_zeroconf_unsupported_abort(
|
||||
mock_smlight_client: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort zeroconf flow if device unsupported."""
|
||||
mock_smlight_client.get_info.side_effect = None
|
||||
mock_smlight_client.get_info.return_value = Info(model="SLZB-X")
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
@ -186,6 +227,7 @@ async def test_user_unsupported_abort(
|
||||
mock_smlight_client: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort user flow if unsupported device."""
|
||||
mock_smlight_client.get_info.side_effect = None
|
||||
mock_smlight_client.get_info.return_value = Info(model="SLZB-X")
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
@ -206,15 +248,13 @@ async def test_user_unsupported_abort(
|
||||
assert result2["reason"] == "unsupported_device"
|
||||
|
||||
|
||||
async def test_user_unsupported_abort_auth(
|
||||
async def test_user_unsupported_device_abort_auth(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_smlight_client: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort user flow if unsupported device (with auth)."""
|
||||
mock_smlight_client.check_auth_needed.return_value = True
|
||||
mock_smlight_client.authenticate.side_effect = SmlightAuthError
|
||||
mock_smlight_client.get_info.side_effect = SmlightAuthError
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
@ -366,7 +406,7 @@ async def test_user_invalid_auth(
|
||||
}
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
assert len(mock_smlight_client.get_info.mock_calls) == 4
|
||||
assert len(mock_smlight_client.get_info.mock_calls) == 3
|
||||
|
||||
|
||||
async def test_user_cannot_connect(
|
||||
|
@ -165,6 +165,7 @@ async def test_device_legacy_firmware(
|
||||
"""Test device setup for old firmware version that dont support required API."""
|
||||
LEGACY_VERSION = "v0.9.9"
|
||||
mock_smlight_client.get_sensors.side_effect = SmlightError
|
||||
mock_smlight_client.get_info.side_effect = None
|
||||
mock_smlight_client.get_info.return_value = Info(
|
||||
legacy_api=2, sw_version=LEGACY_VERSION, MAC="AA:BB:CC:DD:EE:FF"
|
||||
)
|
||||
|
@ -132,6 +132,7 @@ async def test_update_firmware(
|
||||
|
||||
event_function(MOCK_FIRMWARE_DONE)
|
||||
|
||||
mock_smlight_client.get_info.side_effect = None
|
||||
mock_smlight_client.get_info.return_value = Info(
|
||||
sw_version="v2.7.5",
|
||||
)
|
||||
@ -153,6 +154,7 @@ async def test_update_zigbee2_firmware(
|
||||
mock_smlight_client: MagicMock,
|
||||
) -> None:
|
||||
"""Test update of zigbee2 firmware where available."""
|
||||
mock_smlight_client.get_info.side_effect = None
|
||||
mock_smlight_client.get_info.return_value = Info.from_dict(
|
||||
load_json_object_fixture("info-MR1.json", DOMAIN)
|
||||
)
|
||||
@ -195,6 +197,7 @@ async def test_update_legacy_firmware_v2(
|
||||
mock_smlight_client: MagicMock,
|
||||
) -> None:
|
||||
"""Test firmware update for legacy v2 firmware."""
|
||||
mock_smlight_client.get_info.side_effect = None
|
||||
mock_smlight_client.get_info.return_value = Info(
|
||||
sw_version="v2.0.18",
|
||||
legacy_api=1,
|
||||
@ -220,6 +223,7 @@ async def test_update_legacy_firmware_v2(
|
||||
|
||||
event_function(MOCK_FIRMWARE_DONE)
|
||||
|
||||
mock_smlight_client.get_info.side_effect = None
|
||||
mock_smlight_client.get_info.return_value = Info(
|
||||
sw_version="v2.7.5",
|
||||
)
|
||||
@ -333,6 +337,7 @@ async def test_update_release_notes(
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
) -> None:
|
||||
"""Test firmware release notes."""
|
||||
mock_smlight_client.get_info.side_effect = None
|
||||
mock_smlight_client.get_info.return_value = Info.from_dict(
|
||||
load_json_object_fixture("info-MR1.json", DOMAIN)
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user