From 8c34067f17f0506d56d61e095be5d99523468e83 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Wed, 8 Jun 2022 01:11:38 +0200 Subject: [PATCH] Fix creating unique IDs for WiFi switches in Fritz!Tools (#73183) --- homeassistant/components/fritz/switch.py | 11 +- tests/components/fritz/conftest.py | 12 +- tests/components/fritz/const.py | 3 +- tests/components/fritz/test_button.py | 2 +- tests/components/fritz/test_config_flow.py | 2 +- tests/components/fritz/test_diagnostics.py | 2 +- tests/components/fritz/test_init.py | 2 +- tests/components/fritz/test_sensor.py | 2 +- tests/components/fritz/test_switch.py | 189 +++++++++++++++++++++ tests/components/fritz/test_update.py | 2 +- 10 files changed, 216 insertions(+), 11 deletions(-) create mode 100644 tests/components/fritz/test_switch.py diff --git a/homeassistant/components/fritz/switch.py b/homeassistant/components/fritz/switch.py index cac6e735a81..a45cd347463 100644 --- a/homeassistant/components/fritz/switch.py +++ b/homeassistant/components/fritz/switch.py @@ -169,7 +169,16 @@ def wifi_entities_list( } for i, network in networks.copy().items(): networks[i]["switch_name"] = network["ssid"] - if len([j for j, n in networks.items() if n["ssid"] == network["ssid"]]) > 1: + if ( + len( + [ + j + for j, n in networks.items() + if slugify(n["ssid"]) == slugify(network["ssid"]) + ] + ) + > 1 + ): networks[i]["switch_name"] += f" ({WIFI_STANDARD[i]})" _LOGGER.debug("WiFi networks list: %s", networks) diff --git a/tests/components/fritz/conftest.py b/tests/components/fritz/conftest.py index b073335f20a..edbde883f56 100644 --- a/tests/components/fritz/conftest.py +++ b/tests/components/fritz/conftest.py @@ -1,4 +1,4 @@ -"""Common stuff for AVM Fritz!Box tests.""" +"""Common stuff for Fritz!Tools tests.""" import logging from unittest.mock import MagicMock, patch @@ -73,13 +73,19 @@ class FritzHostMock(FritzHosts): return MOCK_MESH_DATA +@pytest.fixture(name="fc_data") +def fc_data_mock(): + """Fixture for default fc_data.""" + return MOCK_FB_SERVICES + + @pytest.fixture() -def fc_class_mock(): +def fc_class_mock(fc_data): """Fixture that sets up a mocked FritzConnection class.""" with patch( "homeassistant.components.fritz.common.FritzConnection", autospec=True ) as result: - result.return_value = FritzConnectionMock(MOCK_FB_SERVICES) + result.return_value = FritzConnectionMock(fc_data) yield result diff --git a/tests/components/fritz/const.py b/tests/components/fritz/const.py index f8f6f8370d7..32f2211d16b 100644 --- a/tests/components/fritz/const.py +++ b/tests/components/fritz/const.py @@ -1,4 +1,4 @@ -"""Common stuff for AVM Fritz!Box tests.""" +"""Common stuff for Fritz!Tools tests.""" from homeassistant.components import ssdp from homeassistant.components.fritz.const import DOMAIN from homeassistant.components.ssdp import ATTR_UPNP_FRIENDLY_NAME, ATTR_UPNP_UDN @@ -194,6 +194,7 @@ MOCK_FB_SERVICES: dict[str, dict] = { }, } + MOCK_MESH_DATA = { "schema_version": "1.9", "nodes": [ diff --git a/tests/components/fritz/test_button.py b/tests/components/fritz/test_button.py index a6ff579958a..a2bd6132731 100644 --- a/tests/components/fritz/test_button.py +++ b/tests/components/fritz/test_button.py @@ -1,4 +1,4 @@ -"""Tests for Shelly button platform.""" +"""Tests for Fritz!Tools button platform.""" from unittest.mock import patch import pytest diff --git a/tests/components/fritz/test_config_flow.py b/tests/components/fritz/test_config_flow.py index 6d014782842..619f06f5493 100644 --- a/tests/components/fritz/test_config_flow.py +++ b/tests/components/fritz/test_config_flow.py @@ -1,4 +1,4 @@ -"""Tests for AVM Fritz!Box config flow.""" +"""Tests for Fritz!Tools config flow.""" import dataclasses from unittest.mock import patch diff --git a/tests/components/fritz/test_diagnostics.py b/tests/components/fritz/test_diagnostics.py index a4b4942c375..2c0b42d6bdf 100644 --- a/tests/components/fritz/test_diagnostics.py +++ b/tests/components/fritz/test_diagnostics.py @@ -1,4 +1,4 @@ -"""Tests for the AVM Fritz!Box integration.""" +"""Tests for Fritz!Tools diagnostics platform.""" from __future__ import annotations from aiohttp import ClientSession diff --git a/tests/components/fritz/test_init.py b/tests/components/fritz/test_init.py index fd67321d235..9f7a17de900 100644 --- a/tests/components/fritz/test_init.py +++ b/tests/components/fritz/test_init.py @@ -1,4 +1,4 @@ -"""Tests for AVM Fritz!Box.""" +"""Tests for Fritz!Tools.""" from unittest.mock import patch from fritzconnection.core.exceptions import FritzSecurityError diff --git a/tests/components/fritz/test_sensor.py b/tests/components/fritz/test_sensor.py index 31e142a3e47..73a7c1068ae 100644 --- a/tests/components/fritz/test_sensor.py +++ b/tests/components/fritz/test_sensor.py @@ -1,4 +1,4 @@ -"""Tests for Shelly button platform.""" +"""Tests for Fritz!Tools sensor platform.""" from __future__ import annotations from datetime import timedelta diff --git a/tests/components/fritz/test_switch.py b/tests/components/fritz/test_switch.py new file mode 100644 index 00000000000..1e744bb62e6 --- /dev/null +++ b/tests/components/fritz/test_switch.py @@ -0,0 +1,189 @@ +"""Tests for Fritz!Tools switch platform.""" +from __future__ import annotations + +import pytest + +from homeassistant.components.fritz.const import DOMAIN +from homeassistant.config_entries import ConfigEntryState +from homeassistant.const import Platform +from homeassistant.core import HomeAssistant +from homeassistant.setup import async_setup_component + +from .const import MOCK_FB_SERVICES, MOCK_USER_DATA + +from tests.common import MockConfigEntry + +MOCK_WLANCONFIGS_SAME_SSID: dict[str, dict] = { + "WLANConfiguration1": { + "GetInfo": { + "NewEnable": True, + "NewStatus": "Up", + "NewMaxBitRate": "Auto", + "NewChannel": 13, + "NewSSID": "WiFi", + "NewBeaconType": "11iandWPA3", + "NewX_AVM-DE_PossibleBeaconTypes": "None,11i,11iandWPA3", + "NewMACAddressControlEnabled": False, + "NewStandard": "ax", + "NewBSSID": "1C:ED:6F:12:34:12", + "NewBasicEncryptionModes": "None", + "NewBasicAuthenticationMode": "None", + "NewMaxCharsSSID": 32, + "NewMinCharsSSID": 1, + "NewAllowedCharsSSID": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + "NewMinCharsPSK": 64, + "NewMaxCharsPSK": 64, + "NewAllowedCharsPSK": "0123456789ABCDEFabcdef", + } + }, + "WLANConfiguration2": { + "GetInfo": { + "NewEnable": True, + "NewStatus": "Up", + "NewMaxBitRate": "Auto", + "NewChannel": 52, + "NewSSID": "WiFi", + "NewBeaconType": "11iandWPA3", + "NewX_AVM-DE_PossibleBeaconTypes": "None,11i,11iandWPA3", + "NewMACAddressControlEnabled": False, + "NewStandard": "ax", + "NewBSSID": "1C:ED:6F:12:34:13", + "NewBasicEncryptionModes": "None", + "NewBasicAuthenticationMode": "None", + "NewMaxCharsSSID": 32, + "NewMinCharsSSID": 1, + "NewAllowedCharsSSID": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + "NewMinCharsPSK": 64, + "NewMaxCharsPSK": 64, + "NewAllowedCharsPSK": "0123456789ABCDEFabcdef", + } + }, +} +MOCK_WLANCONFIGS_DIFF_SSID: dict[str, dict] = { + "WLANConfiguration1": { + "GetInfo": { + "NewEnable": True, + "NewStatus": "Up", + "NewMaxBitRate": "Auto", + "NewChannel": 13, + "NewSSID": "WiFi", + "NewBeaconType": "11iandWPA3", + "NewX_AVM-DE_PossibleBeaconTypes": "None,11i,11iandWPA3", + "NewMACAddressControlEnabled": False, + "NewStandard": "ax", + "NewBSSID": "1C:ED:6F:12:34:12", + "NewBasicEncryptionModes": "None", + "NewBasicAuthenticationMode": "None", + "NewMaxCharsSSID": 32, + "NewMinCharsSSID": 1, + "NewAllowedCharsSSID": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + "NewMinCharsPSK": 64, + "NewMaxCharsPSK": 64, + "NewAllowedCharsPSK": "0123456789ABCDEFabcdef", + } + }, + "WLANConfiguration2": { + "GetInfo": { + "NewEnable": True, + "NewStatus": "Up", + "NewMaxBitRate": "Auto", + "NewChannel": 52, + "NewSSID": "WiFi2", + "NewBeaconType": "11iandWPA3", + "NewX_AVM-DE_PossibleBeaconTypes": "None,11i,11iandWPA3", + "NewMACAddressControlEnabled": False, + "NewStandard": "ax", + "NewBSSID": "1C:ED:6F:12:34:13", + "NewBasicEncryptionModes": "None", + "NewBasicAuthenticationMode": "None", + "NewMaxCharsSSID": 32, + "NewMinCharsSSID": 1, + "NewAllowedCharsSSID": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + "NewMinCharsPSK": 64, + "NewMaxCharsPSK": 64, + "NewAllowedCharsPSK": "0123456789ABCDEFabcdef", + } + }, +} +MOCK_WLANCONFIGS_DIFF2_SSID: dict[str, dict] = { + "WLANConfiguration1": { + "GetInfo": { + "NewEnable": True, + "NewStatus": "Up", + "NewMaxBitRate": "Auto", + "NewChannel": 13, + "NewSSID": "WiFi", + "NewBeaconType": "11iandWPA3", + "NewX_AVM-DE_PossibleBeaconTypes": "None,11i,11iandWPA3", + "NewMACAddressControlEnabled": False, + "NewStandard": "ax", + "NewBSSID": "1C:ED:6F:12:34:12", + "NewBasicEncryptionModes": "None", + "NewBasicAuthenticationMode": "None", + "NewMaxCharsSSID": 32, + "NewMinCharsSSID": 1, + "NewAllowedCharsSSID": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + "NewMinCharsPSK": 64, + "NewMaxCharsPSK": 64, + "NewAllowedCharsPSK": "0123456789ABCDEFabcdef", + } + }, + "WLANConfiguration2": { + "GetInfo": { + "NewEnable": True, + "NewStatus": "Up", + "NewMaxBitRate": "Auto", + "NewChannel": 52, + "NewSSID": "WiFi+", + "NewBeaconType": "11iandWPA3", + "NewX_AVM-DE_PossibleBeaconTypes": "None,11i,11iandWPA3", + "NewMACAddressControlEnabled": False, + "NewStandard": "ax", + "NewBSSID": "1C:ED:6F:12:34:13", + "NewBasicEncryptionModes": "None", + "NewBasicAuthenticationMode": "None", + "NewMaxCharsSSID": 32, + "NewMinCharsSSID": 1, + "NewAllowedCharsSSID": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + "NewMinCharsPSK": 64, + "NewMaxCharsPSK": 64, + "NewAllowedCharsPSK": "0123456789ABCDEFabcdef", + } + }, +} + + +@pytest.mark.parametrize( + "fc_data, expected_wifi_names", + [ + ( + {**MOCK_FB_SERVICES, **MOCK_WLANCONFIGS_SAME_SSID}, + ["WiFi (2.4Ghz)", "WiFi (5Ghz)"], + ), + ({**MOCK_FB_SERVICES, **MOCK_WLANCONFIGS_DIFF_SSID}, ["WiFi", "WiFi2"]), + ( + {**MOCK_FB_SERVICES, **MOCK_WLANCONFIGS_DIFF2_SSID}, + ["WiFi (2.4Ghz)", "WiFi+ (5Ghz)"], + ), + ], +) +async def test_switch_setup( + hass: HomeAssistant, + expected_wifi_names: list[str], + fc_class_mock, + fh_class_mock, +): + """Test setup of Fritz!Tools switches.""" + + entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) + entry.add_to_hass(hass) + + assert await async_setup_component(hass, DOMAIN, {}) + await hass.async_block_till_done() + assert entry.state == ConfigEntryState.LOADED + + switches = hass.states.async_all(Platform.SWITCH) + assert len(switches) == 3 + assert switches[0].name == f"Mock Title Wi-Fi {expected_wifi_names[0]}" + assert switches[1].name == f"Mock Title Wi-Fi {expected_wifi_names[1]}" + assert switches[2].name == "printer Internet Access" diff --git a/tests/components/fritz/test_update.py b/tests/components/fritz/test_update.py index 2261ef3ef9b..32bdf361847 100644 --- a/tests/components/fritz/test_update.py +++ b/tests/components/fritz/test_update.py @@ -1,4 +1,4 @@ -"""The tests for the Fritzbox update entity.""" +"""Tests for Fritz!Tools update platform.""" from unittest.mock import patch