From b8a85d7c064c483021ed638a10be8afb39f67cc2 Mon Sep 17 00:00:00 2001 From: Sebastian Heiden Date: Wed, 24 May 2023 13:56:24 +0000 Subject: [PATCH 1/6] Fix Setup Config Flow for LaMetric SKY --- homeassistant/components/lametric/config_flow.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/lametric/config_flow.py b/homeassistant/components/lametric/config_flow.py index 8e9da5851cf50..b59a0b57b27b4 100644 --- a/homeassistant/components/lametric/config_flow.py +++ b/homeassistant/components/lametric/config_flow.py @@ -248,6 +248,12 @@ async def _async_step_create_entry(self, host: str, api_key: str) -> FlowResult: updates={CONF_HOST: lametric.host, CONF_API_KEY: lametric.api_key} ) + notify_sound: Sound | None + if device.model == "sa5": + notify_sound = None + else: + notify_sound = Sound(sound=NotificationSound.WIN) + await lametric.notify( notification=Notification( priority=NotificationPriority.CRITICAL, @@ -255,7 +261,7 @@ async def _async_step_create_entry(self, host: str, api_key: str) -> FlowResult: model=Model( cycles=2, frames=[Simple(text="Connected to Home Assistant!", icon=7956)], - sound=Sound(sound=NotificationSound.WIN), + sound=notify_sound, ), ) ) From 41ab9d63cea7cd1c9f492005dea628c8e24cb59d Mon Sep 17 00:00:00 2001 From: Sebastian Heiden Date: Wed, 24 May 2023 21:23:20 +0200 Subject: [PATCH 2/6] Refactor Config Flow Fix for LaMetric SKY Co-authored-by: Franck Nijhof --- homeassistant/components/lametric/config_flow.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/lametric/config_flow.py b/homeassistant/components/lametric/config_flow.py index b59a0b57b27b4..1dad190d70675 100644 --- a/homeassistant/components/lametric/config_flow.py +++ b/homeassistant/components/lametric/config_flow.py @@ -248,10 +248,8 @@ async def _async_step_create_entry(self, host: str, api_key: str) -> FlowResult: updates={CONF_HOST: lametric.host, CONF_API_KEY: lametric.api_key} ) - notify_sound: Sound | None - if device.model == "sa5": - notify_sound = None - else: + notify_sound: Sound | None = None + if device.model != "sa5": notify_sound = Sound(sound=NotificationSound.WIN) await lametric.notify( From 231628b2df97862916ee9776159d75a5a55bee17 Mon Sep 17 00:00:00 2001 From: Sebastian Heiden Date: Wed, 24 May 2023 20:47:42 +0000 Subject: [PATCH 3/6] Add test for notification sound for LaMetric TIME --- tests/components/lametric/test_config_flow.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/components/lametric/test_config_flow.py b/tests/components/lametric/test_config_flow.py index 8fd0ef061ac14..2ad7a17affb10 100644 --- a/tests/components/lametric/test_config_flow.py +++ b/tests/components/lametric/test_config_flow.py @@ -6,6 +6,9 @@ LaMetricConnectionError, LaMetricConnectionTimeoutError, LaMetricError, + Notification, + NotificationSound, + Sound, ) import pytest @@ -238,6 +241,10 @@ async def test_full_manual( assert len(mock_lametric.device.mock_calls) == 1 assert len(mock_lametric.notify.mock_calls) == 1 + + notification: Notification = mock_lametric.notify.mock_calls[0][2]["notification"] + assert notification.model.sound == Sound(sound=NotificationSound.WIN) + assert len(mock_setup_entry.mock_calls) == 1 From 9b9d78b849f4a1491046e20ba846a6e69def1854 Mon Sep 17 00:00:00 2001 From: Sebastian Heiden Date: Wed, 24 May 2023 21:41:19 +0000 Subject: [PATCH 4/6] Add test for no sound for LaMetric SKY --- tests/components/lametric/conftest.py | 6 +- .../lametric/fixtures/device_sa5.json | 71 +++++++++++++++++++ tests/components/lametric/test_config_flow.py | 45 ++++++++++++ 3 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 tests/components/lametric/fixtures/device_sa5.json diff --git a/tests/components/lametric/conftest.py b/tests/components/lametric/conftest.py index 177204b6f241e..38111c94c38c4 100644 --- a/tests/components/lametric/conftest.py +++ b/tests/components/lametric/conftest.py @@ -66,8 +66,8 @@ def mock_lametric_cloud() -> Generator[MagicMock, None, None]: yield lametric -@pytest.fixture -def mock_lametric() -> Generator[MagicMock, None, None]: +@pytest.fixture(params=["device.json"]) +def mock_lametric(request) -> Generator[MagicMock, None, None]: """Return a mocked LaMetric client.""" with patch( "homeassistant.components.lametric.coordinator.LaMetricDevice", autospec=True @@ -79,7 +79,7 @@ def mock_lametric() -> Generator[MagicMock, None, None]: lametric.api_key = "mock-api-key" lametric.host = "127.0.0.1" lametric.device.return_value = Device.parse_raw( - load_fixture("device.json", DOMAIN) + load_fixture(request.param, DOMAIN) ) yield lametric diff --git a/tests/components/lametric/fixtures/device_sa5.json b/tests/components/lametric/fixtures/device_sa5.json new file mode 100644 index 0000000000000..47120f672efda --- /dev/null +++ b/tests/components/lametric/fixtures/device_sa5.json @@ -0,0 +1,71 @@ +{ + "audio": { + "volume": 100, + "volume_limit": { + "max": 100, + "min": 0 + }, + "volume_range": { + "max": 100, + "min": 0 + } + }, + "bluetooth": { + "active": true, + "address": "AA:BB:CC:DD:EE:FF", + "available": true, + "discoverable": true, + "low_energy": { + "active": true, + "advertising": true, + "connectable": true + }, + "name": "SKY0123", + "pairable": false + }, + "display": { + "brightness": 66, + "brightness_limit": { + "max": 100, + "min": 2 + }, + "brightness_mode": "manual", + "brightness_range": { + "max": 100, + "min": 0 + }, + "height": 8, + "on": true, + "screensaver": { + "enabled": true, + "modes": { + "screen_off": { + "enabled": false + }, + "time_based": { + "enabled": false + } + }, + "widget": "" + }, + "type": "mixed", + "width": 64 + }, + "id": "12345", + "mode": "manual", + "model": "sa5", + "name": "spyfly's LaMetric SKY", + "os_version": "3.0.13", + "serial_number": "SA52100000123TBNC", + "wifi": { + "active": true, + "mac": "AA:BB:CC:DD:EE:FF", + "available": true, + "encryption": "WPA", + "ssid": "IoT", + "ip": "127.0.0.1", + "mode": "dhcp", + "netmask": "255.255.255.0", + "strength": 58 + } +} diff --git a/tests/components/lametric/test_config_flow.py b/tests/components/lametric/test_config_flow.py index 2ad7a17affb10..9ae1535b2451e 100644 --- a/tests/components/lametric/test_config_flow.py +++ b/tests/components/lametric/test_config_flow.py @@ -901,3 +901,48 @@ async def test_reauth_manual( assert len(mock_lametric.device.mock_calls) == 1 assert len(mock_lametric.notify.mock_calls) == 1 + + +@pytest.mark.usefixtures("mock_setup_entry") +@pytest.mark.parametrize("mock_lametric", ["device_sa5.json"], indirect=True) +async def test_reauth_manual_sky( + hass: HomeAssistant, + mock_lametric: MagicMock, + mock_config_entry: MockConfigEntry, +) -> None: + """Test reauth flow with manual entry for LaMetric Sky.""" + mock_config_entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={ + "source": SOURCE_REAUTH, + "unique_id": mock_config_entry.unique_id, + "entry_id": mock_config_entry.entry_id, + }, + data=mock_config_entry.data, + ) + + flow_id = result["flow_id"] + + await hass.config_entries.flow.async_configure( + flow_id, user_input={"next_step_id": "manual_entry"} + ) + + result2 = await hass.config_entries.flow.async_configure( + flow_id, user_input={CONF_API_KEY: "mock-api-key"} + ) + + assert result2.get("type") == FlowResultType.ABORT + assert result2.get("reason") == "reauth_successful" + assert mock_config_entry.data == { + CONF_HOST: "127.0.0.1", + CONF_API_KEY: "mock-api-key", + CONF_MAC: "AA:BB:CC:DD:EE:FF", + } + + assert len(mock_lametric.device.mock_calls) == 1 + assert len(mock_lametric.notify.mock_calls) == 1 + + notification: Notification = mock_lametric.notify.mock_calls[0][2]["notification"] + assert notification.model.sound is None From ee91d30426716e156d596f28a5aa1af97de4dd24 Mon Sep 17 00:00:00 2001 From: Sebastian Heiden Date: Fri, 26 May 2023 11:28:17 +0000 Subject: [PATCH 5/6] Add a seperate fixture for LaMetric SKY --- tests/components/lametric/conftest.py | 24 ++++++++++++++++--- tests/components/lametric/test_config_flow.py | 11 +++++---- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/tests/components/lametric/conftest.py b/tests/components/lametric/conftest.py index 38111c94c38c4..62029ec5e5e6f 100644 --- a/tests/components/lametric/conftest.py +++ b/tests/components/lametric/conftest.py @@ -66,9 +66,27 @@ def mock_lametric_cloud() -> Generator[MagicMock, None, None]: yield lametric -@pytest.fixture(params=["device.json"]) +@pytest.fixture def mock_lametric(request) -> Generator[MagicMock, None, None]: - """Return a mocked LaMetric client.""" + """Return a mocked LaMetric TIME client.""" + with patch( + "homeassistant.components.lametric.coordinator.LaMetricDevice", autospec=True + ) as lametric_mock, patch( + "homeassistant.components.lametric.config_flow.LaMetricDevice", + new=lametric_mock, + ): + lametric = lametric_mock.return_value + lametric.api_key = "mock-api-key" + lametric.host = "127.0.0.1" + lametric.device.return_value = Device.parse_raw( + load_fixture("device.json", DOMAIN) + ) + yield lametric + + +@pytest.fixture +def mock_lametric_sky(request) -> Generator[MagicMock, None, None]: + """Return a mocked LaMetric SKY client.""" with patch( "homeassistant.components.lametric.coordinator.LaMetricDevice", autospec=True ) as lametric_mock, patch( @@ -79,7 +97,7 @@ def mock_lametric(request) -> Generator[MagicMock, None, None]: lametric.api_key = "mock-api-key" lametric.host = "127.0.0.1" lametric.device.return_value = Device.parse_raw( - load_fixture(request.param, DOMAIN) + load_fixture("device_sa5.json", DOMAIN) ) yield lametric diff --git a/tests/components/lametric/test_config_flow.py b/tests/components/lametric/test_config_flow.py index 9ae1535b2451e..4cb669b3d6384 100644 --- a/tests/components/lametric/test_config_flow.py +++ b/tests/components/lametric/test_config_flow.py @@ -904,10 +904,9 @@ async def test_reauth_manual( @pytest.mark.usefixtures("mock_setup_entry") -@pytest.mark.parametrize("mock_lametric", ["device_sa5.json"], indirect=True) async def test_reauth_manual_sky( hass: HomeAssistant, - mock_lametric: MagicMock, + mock_lametric_sky: MagicMock, mock_config_entry: MockConfigEntry, ) -> None: """Test reauth flow with manual entry for LaMetric Sky.""" @@ -941,8 +940,10 @@ async def test_reauth_manual_sky( CONF_MAC: "AA:BB:CC:DD:EE:FF", } - assert len(mock_lametric.device.mock_calls) == 1 - assert len(mock_lametric.notify.mock_calls) == 1 + assert len(mock_lametric_sky.device.mock_calls) == 1 + assert len(mock_lametric_sky.notify.mock_calls) == 1 - notification: Notification = mock_lametric.notify.mock_calls[0][2]["notification"] + notification: Notification = mock_lametric_sky.notify.mock_calls[0][2][ + "notification" + ] assert notification.model.sound is None From 285a0d066e720ee01ae7718a24dae8c46b065689 Mon Sep 17 00:00:00 2001 From: Sebastian Heiden Date: Thu, 1 Jun 2023 12:46:42 +0000 Subject: [PATCH 6/6] Added multi-device fixture support for LaMetric --- tests/components/lametric/conftest.py | 24 +++++-------------- tests/components/lametric/test_config_flow.py | 11 ++++----- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/tests/components/lametric/conftest.py b/tests/components/lametric/conftest.py index 62029ec5e5e6f..b3a9f2d866509 100644 --- a/tests/components/lametric/conftest.py +++ b/tests/components/lametric/conftest.py @@ -67,26 +67,14 @@ def mock_lametric_cloud() -> Generator[MagicMock, None, None]: @pytest.fixture -def mock_lametric(request) -> Generator[MagicMock, None, None]: - """Return a mocked LaMetric TIME client.""" - with patch( - "homeassistant.components.lametric.coordinator.LaMetricDevice", autospec=True - ) as lametric_mock, patch( - "homeassistant.components.lametric.config_flow.LaMetricDevice", - new=lametric_mock, - ): - lametric = lametric_mock.return_value - lametric.api_key = "mock-api-key" - lametric.host = "127.0.0.1" - lametric.device.return_value = Device.parse_raw( - load_fixture("device.json", DOMAIN) - ) - yield lametric +def device_fixture() -> str: + """Return the device fixture for a specific device.""" + return "device" @pytest.fixture -def mock_lametric_sky(request) -> Generator[MagicMock, None, None]: - """Return a mocked LaMetric SKY client.""" +def mock_lametric(request, device_fixture: str) -> Generator[MagicMock, None, None]: + """Return a mocked LaMetric TIME client.""" with patch( "homeassistant.components.lametric.coordinator.LaMetricDevice", autospec=True ) as lametric_mock, patch( @@ -97,7 +85,7 @@ def mock_lametric_sky(request) -> Generator[MagicMock, None, None]: lametric.api_key = "mock-api-key" lametric.host = "127.0.0.1" lametric.device.return_value = Device.parse_raw( - load_fixture("device_sa5.json", DOMAIN) + load_fixture(f"{device_fixture}.json", DOMAIN) ) yield lametric diff --git a/tests/components/lametric/test_config_flow.py b/tests/components/lametric/test_config_flow.py index 4cb669b3d6384..0fa3a2d983822 100644 --- a/tests/components/lametric/test_config_flow.py +++ b/tests/components/lametric/test_config_flow.py @@ -904,9 +904,10 @@ async def test_reauth_manual( @pytest.mark.usefixtures("mock_setup_entry") +@pytest.mark.parametrize("device_fixture", ["device_sa5"]) async def test_reauth_manual_sky( hass: HomeAssistant, - mock_lametric_sky: MagicMock, + mock_lametric: MagicMock, mock_config_entry: MockConfigEntry, ) -> None: """Test reauth flow with manual entry for LaMetric Sky.""" @@ -940,10 +941,8 @@ async def test_reauth_manual_sky( CONF_MAC: "AA:BB:CC:DD:EE:FF", } - assert len(mock_lametric_sky.device.mock_calls) == 1 - assert len(mock_lametric_sky.notify.mock_calls) == 1 + assert len(mock_lametric.device.mock_calls) == 1 + assert len(mock_lametric.notify.mock_calls) == 1 - notification: Notification = mock_lametric_sky.notify.mock_calls[0][2][ - "notification" - ] + notification: Notification = mock_lametric.notify.mock_calls[0][2]["notification"] assert notification.model.sound is None