Improve tests of Fritz!Tools (part1) (#66972)

pull/67101/head
Michael 2022-02-23 01:35:22 +01:00 committed by GitHub
parent 1658d530e1
commit b8590fde40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1077 additions and 109 deletions

View File

@ -394,13 +394,10 @@ omit =
homeassistant/components/freebox/router.py
homeassistant/components/freebox/sensor.py
homeassistant/components/freebox/switch.py
homeassistant/components/fritz/__init__.py
homeassistant/components/fritz/binary_sensor.py
homeassistant/components/fritz/button.py
homeassistant/components/fritz/common.py
homeassistant/components/fritz/const.py
homeassistant/components/fritz/device_tracker.py
homeassistant/components/fritz/diagnostics.py
homeassistant/components/fritz/sensor.py
homeassistant/components/fritz/services.py
homeassistant/components/fritz/switch.py

View File

@ -1,115 +1,86 @@
"""Common stuff for AVM Fritz!Box tests."""
from unittest import mock
import logging
from unittest.mock import patch
from fritzconnection.core.processor import Service
from fritzconnection.lib.fritzhosts import FritzHosts
import pytest
from .const import MOCK_FB_SERVICES, MOCK_MESH_DATA, MOCK_MODELNAME
@pytest.fixture()
def fc_class_mock():
"""Fixture that sets up a mocked FritzConnection class."""
with patch("fritzconnection.FritzConnection", autospec=True) as result:
result.return_value = FritzConnectionMock()
yield result
LOGGER = logging.getLogger(__name__)
class FritzServiceMock(Service):
"""Service mocking."""
def __init__(self, serviceId: str, actions: dict) -> None:
"""Init Service mock."""
super().__init__()
self._actions = actions
self.serviceId = serviceId
class FritzConnectionMock: # pylint: disable=too-few-public-methods
"""FritzConnection mocking."""
FRITZBOX_DATA = {
("WANIPConn:1", "GetStatusInfo"): {
"NewConnectionStatus": "Connected",
"NewUptime": 35307,
},
("WANIPConnection:1", "GetStatusInfo"): {},
("WANCommonIFC:1", "GetCommonLinkProperties"): {
"NewLayer1DownstreamMaxBitRate": 10087000,
"NewLayer1UpstreamMaxBitRate": 2105000,
"NewPhysicalLinkStatus": "Up",
},
("WANCommonIFC:1", "GetAddonInfos"): {
"NewByteSendRate": 3438,
"NewByteReceiveRate": 67649,
"NewTotalBytesSent": 1712232562,
"NewTotalBytesReceived": 5221019883,
},
("LANEthernetInterfaceConfig:1", "GetStatistics"): {
"NewBytesSent": 23004321,
"NewBytesReceived": 12045,
},
("DeviceInfo:1", "GetInfo"): {
"NewSerialNumber": "abcdefgh",
"NewName": "TheName",
"NewModelName": "FRITZ!Box 7490",
},
}
FRITZBOX_DATA_INDEXED = {
("X_AVM-DE_Homeauto:1", "GetGenericDeviceInfos"): [
{
"NewSwitchIsValid": "VALID",
"NewMultimeterIsValid": "VALID",
"NewTemperatureIsValid": "VALID",
"NewDeviceId": 16,
"NewAIN": "08761 0114116",
"NewDeviceName": "FRITZ!DECT 200 #1",
"NewTemperatureOffset": "0",
"NewSwitchLock": "0",
"NewProductName": "FRITZ!DECT 200",
"NewPresent": "CONNECTED",
"NewMultimeterPower": 1673,
"NewHkrComfortTemperature": "0",
"NewSwitchMode": "AUTO",
"NewManufacturer": "AVM",
"NewMultimeterIsEnabled": "ENABLED",
"NewHkrIsTemperature": "0",
"NewFunctionBitMask": 2944,
"NewTemperatureIsEnabled": "ENABLED",
"NewSwitchState": "ON",
"NewSwitchIsEnabled": "ENABLED",
"NewFirmwareVersion": "03.87",
"NewHkrSetVentilStatus": "CLOSED",
"NewMultimeterEnergy": 5182,
"NewHkrComfortVentilStatus": "CLOSED",
"NewHkrReduceTemperature": "0",
"NewHkrReduceVentilStatus": "CLOSED",
"NewHkrIsEnabled": "DISABLED",
"NewHkrSetTemperature": "0",
"NewTemperatureCelsius": "225",
"NewHkrIsValid": "INVALID",
},
{},
],
("Hosts1", "GetGenericHostEntry"): [
{
"NewSerialNumber": 1234,
"NewName": "TheName",
"NewModelName": "FRITZ!Box 7490",
},
{},
],
}
MODELNAME = "FRITZ!Box 7490"
def __init__(self):
def __init__(self, services):
"""Inint Mocking class."""
self.modelname = self.MODELNAME
self.call_action = mock.Mock(side_effect=self._side_effect_call_action)
type(self).action_names = mock.PropertyMock(
side_effect=self._side_effect_action_names
)
self.modelname = MOCK_MODELNAME
self.call_action = self._call_action
self._services = services
self.services = {
srv: None
for srv, _ in list(self.FRITZBOX_DATA) + list(self.FRITZBOX_DATA_INDEXED)
srv: FritzServiceMock(serviceId=srv, actions=actions)
for srv, actions in services.items()
}
LOGGER.debug("-" * 80)
LOGGER.debug("FritzConnectionMock - services: %s", self.services)
def _call_action(self, service: str, action: str, **kwargs):
LOGGER.debug(
"_call_action service: %s, action: %s, **kwargs: %s",
service,
action,
{**kwargs},
)
if ":" in service:
service, number = service.split(":", 1)
service = service + number
elif not service[-1].isnumeric():
service = service + "1"
def _side_effect_call_action(self, service, action, **kwargs):
if kwargs:
index = next(iter(kwargs.values()))
return self.FRITZBOX_DATA_INDEXED[(service, action)][index]
return self.FRITZBOX_DATA[(service, action)]
if (index := kwargs.get("NewIndex")) is None:
index = next(iter(kwargs.values()))
def _side_effect_action_names(self):
return list(self.FRITZBOX_DATA) + list(self.FRITZBOX_DATA_INDEXED)
return self._services[service][action][index]
return self._services[service][action]
class FritzHostMock(FritzHosts):
"""FritzHosts mocking."""
def get_mesh_topology(self, raw=False):
"""Retrurn mocked mesh data."""
return MOCK_MESH_DATA
@pytest.fixture()
def fc_class_mock():
"""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)
yield result
@pytest.fixture()
def fh_class_mock():
"""Fixture that sets up a mocked FritzHosts class."""
with patch(
"homeassistant.components.fritz.common.FritzHosts",
new=FritzHostMock,
) as result:
yield result

View File

@ -26,9 +26,758 @@ MOCK_CONFIG = {
}
}
MOCK_HOST = "fake_host"
MOCK_IP = "192.168.178.1"
MOCK_IPS = {"fritz.box": "192.168.178.1", "printer": "192.168.178.2"}
MOCK_MODELNAME = "FRITZ!Box 7530 AX"
MOCK_FIRMWARE = "256.07.29"
MOCK_SERIAL_NUMBER = "fake_serial_number"
MOCK_FIRMWARE_INFO = [True, "1.1.1"]
MOCK_MESH_SSID = "TestSSID"
MOCK_MESH_MASTER_MAC = "1C:ED:6F:12:34:11"
MOCK_MESH_MASTER_WIFI1_MAC = "1C:ED:6F:12:34:12"
MOCK_MESH_SLAVE_MAC = "1C:ED:6F:12:34:21"
MOCK_MESH_SLAVE_WIFI1_MAC = "1C:ED:6F:12:34:22"
MOCK_FB_SERVICES: dict[str, dict] = {
"DeviceInfo1": {
"GetInfo": {
"NewSerialNumber": MOCK_MESH_MASTER_MAC,
"NewName": "TheName",
"NewModelName": MOCK_MODELNAME,
"NewSoftwareVersion": MOCK_FIRMWARE,
"NewUpTime": 2518179,
},
},
"Hosts1": {
"GetGenericHostEntry": [
{
"NewIPAddress": MOCK_IPS["fritz.box"],
"NewAddressSource": "Static",
"NewLeaseTimeRemaining": 0,
"NewMACAddress": MOCK_MESH_MASTER_MAC,
"NewInterfaceType": "",
"NewActive": True,
"NewHostName": "fritz.box",
},
{
"NewIPAddress": MOCK_IPS["printer"],
"NewAddressSource": "DHCP",
"NewLeaseTimeRemaining": 0,
"NewMACAddress": "AA:BB:CC:00:11:22",
"NewInterfaceType": "Ethernet",
"NewActive": True,
"NewHostName": "printer",
},
],
"X_AVM-DE_GetMeshListPath": {},
},
"LANEthernetInterfaceConfig1": {
"GetStatistics": {
"NewBytesSent": 23004321,
"NewBytesReceived": 12045,
},
},
"Layer3Forwarding1": {
"GetDefaultConnectionService": {
"NewDefaultConnectionService": "1.WANPPPConnection.1"
}
},
"UserInterface1": {
"GetInfo": {},
},
"WANCommonIFC1": {
"GetCommonLinkProperties": {
"NewLayer1DownstreamMaxBitRate": 10087000,
"NewLayer1UpstreamMaxBitRate": 2105000,
"NewPhysicalLinkStatus": "Up",
},
"GetAddonInfos": {
"NewByteSendRate": 3438,
"NewByteReceiveRate": 67649,
"NewTotalBytesSent": 1712232562,
"NewTotalBytesReceived": 5221019883,
"NewX_AVM_DE_TotalBytesSent64": 1712232562,
"NeWX_AVM_DE_TotalBytesReceived64": 5221019883,
},
"GetTotalBytesSent": {"NewTotalBytesSent": 1712232562},
"GetTotalBytesReceived": {"NewTotalBytesReceived": 5221019883},
},
"WANCommonInterfaceConfig1": {
"GetCommonLinkProperties": {
"NewWANAccessType": "DSL",
"NewLayer1UpstreamMaxBitRate": 51805000,
"NewLayer1DownstreamMaxBitRate": 318557000,
"NewPhysicalLinkStatus": "Up",
}
},
"WANDSLInterfaceConfig1": {
"GetInfo": {
"NewEnable": True,
"NewStatus": "Up",
"NewDataPath": "Interleaved",
"NewUpstreamCurrRate": 46720,
"NewDownstreamCurrRate": 292030,
"NewUpstreamMaxRate": 51348,
"NewDownstreamMaxRate": 315978,
"NewUpstreamNoiseMargin": 90,
"NewDownstreamNoiseMargin": 80,
"NewUpstreamAttenuation": 70,
"NewDownstreamAttenuation": 120,
"NewATURVendor": "41564d00",
"NewATURCountry": "0400",
"NewUpstreamPower": 500,
"NewDownstreamPower": 500,
}
},
"WANIPConn1": {
"GetStatusInfo": {
"NewConnectionStatus": "Connected",
"NewUptime": 35307,
},
"GetExternalIPAddress": {"NewExternalIPAddress": "1.2.3.4"},
},
"WANPPPConnection1": {
"GetInfo": {
"NewEnable": True,
"NewConnectionStatus": "Connected",
"NewUptime": 57199,
"NewUpstreamMaxBitRate": 46531924,
"NewDownstreamMaxBitRate": 43430530,
"NewExternalIPAddress": "1.2.3.4",
},
"GetPortMappingNumberOfEntries": {},
},
"X_AVM-DE_Homeauto1": {
"GetGenericDeviceInfos": [
{
"NewSwitchIsValid": "VALID",
"NewMultimeterIsValid": "VALID",
"NewTemperatureIsValid": "VALID",
"NewDeviceId": 16,
"NewAIN": "08761 0114116",
"NewDeviceName": "FRITZ!DECT 200 #1",
"NewTemperatureOffset": "0",
"NewSwitchLock": "0",
"NewProductName": "FRITZ!DECT 200",
"NewPresent": "CONNECTED",
"NewMultimeterPower": 1673,
"NewHkrComfortTemperature": "0",
"NewSwitchMode": "AUTO",
"NewManufacturer": "AVM",
"NewMultimeterIsEnabled": "ENABLED",
"NewHkrIsTemperature": "0",
"NewFunctionBitMask": 2944,
"NewTemperatureIsEnabled": "ENABLED",
"NewSwitchState": "ON",
"NewSwitchIsEnabled": "ENABLED",
"NewFirmwareVersion": "03.87",
"NewHkrSetVentilStatus": "CLOSED",
"NewMultimeterEnergy": 5182,
"NewHkrComfortVentilStatus": "CLOSED",
"NewHkrReduceTemperature": "0",
"NewHkrReduceVentilStatus": "CLOSED",
"NewHkrIsEnabled": "DISABLED",
"NewHkrSetTemperature": "0",
"NewTemperatureCelsius": "225",
"NewHkrIsValid": "INVALID",
},
{},
],
},
"X_AVM-DE_HostFilter1": {
"GetWANAccessByIP": {
MOCK_IPS["printer"]: {"NewDisallow": False, "NewWANAccess": "granted"}
}
},
}
MOCK_MESH_DATA = {
"schema_version": "1.9",
"nodes": [
{
"uid": "n-1",
"device_name": "fritz.box",
"device_model": "FRITZ!Box 7530 AX",
"device_manufacturer": "AVM",
"device_firmware_version": "256.07.29",
"device_mac_address": MOCK_MESH_MASTER_MAC,
"is_meshed": True,
"mesh_role": "master",
"meshd_version": "3.13",
"node_interfaces": [
{
"uid": "ni-5",
"name": "LANBridge",
"type": "LAN",
"mac_address": MOCK_MESH_MASTER_MAC,
"blocking_state": "NOT_BLOCKED",
"node_links": [],
},
{
"uid": "ni-30",
"name": "LAN:2",
"type": "LAN",
"mac_address": MOCK_MESH_MASTER_MAC,
"blocking_state": "NOT_BLOCKED",
"node_links": [],
},
{
"uid": "ni-32",
"name": "LAN:3",
"type": "LAN",
"mac_address": MOCK_MESH_MASTER_MAC,
"blocking_state": "NOT_BLOCKED",
"node_links": [],
},
{
"uid": "ni-31",
"name": "LAN:1",
"type": "LAN",
"mac_address": MOCK_MESH_MASTER_MAC,
"blocking_state": "NOT_BLOCKED",
"node_links": [
{
"uid": "nl-78",
"type": "LAN",
"state": "CONNECTED",
"last_connected": 1642872967,
"node_1_uid": "n-1",
"node_2_uid": "n-76",
"node_interface_1_uid": "ni-31",
"node_interface_2_uid": "ni-77",
"max_data_rate_rx": 1000000,
"max_data_rate_tx": 1000000,
"cur_data_rate_rx": 0,
"cur_data_rate_tx": 0,
"cur_availability_rx": 99,
"cur_availability_tx": 99,
}
],
},
{
"uid": "ni-33",
"name": "LAN:4",
"type": "LAN",
"mac_address": MOCK_MESH_MASTER_MAC,
"blocking_state": "NOT_BLOCKED",
"node_links": [],
},
{
"uid": "ni-230",
"name": "AP:2G:0",
"type": "WLAN",
"mac_address": MOCK_MESH_MASTER_WIFI1_MAC,
"blocking_state": "UNKNOWN",
"node_links": [
{
"uid": "nl-219",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1644618820,
"node_1_uid": "n-1",
"node_2_uid": "n-89",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-90",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 54000,
"cur_data_rate_tx": 65000,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 51,
"tx_rsni": 255,
"rx_rcpi": -38,
"tx_rcpi": 255,
},
{
"uid": "nl-168",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1645162418,
"node_1_uid": "n-1",
"node_2_uid": "n-118",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-119",
"max_data_rate_rx": 144400,
"max_data_rate_tx": 144400,
"cur_data_rate_rx": 144400,
"cur_data_rate_tx": 130000,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 37,
"tx_rsni": 255,
"rx_rcpi": -52,
"tx_rcpi": 255,
},
{
"uid": "nl-185",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1645273363,
"node_1_uid": "n-1",
"node_2_uid": "n-100",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-99",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 1000,
"cur_data_rate_tx": 1000,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 35,
"tx_rsni": 255,
"rx_rcpi": -54,
"tx_rcpi": 255,
},
{
"uid": "nl-166",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1644618912,
"node_1_uid": "n-1",
"node_2_uid": "n-16",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-15",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 54000,
"cur_data_rate_tx": 65000,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 41,
"tx_rsni": 255,
"rx_rcpi": -48,
"tx_rcpi": 255,
},
{
"uid": "nl-239",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1644618828,
"node_1_uid": "n-1",
"node_2_uid": "n-59",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-58",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 54000,
"cur_data_rate_tx": 65000,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 43,
"tx_rsni": 255,
"rx_rcpi": -46,
"tx_rcpi": 255,
},
{
"uid": "nl-173",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1645331764,
"node_1_uid": "n-1",
"node_2_uid": "n-137",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-138",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 72200,
"cur_data_rate_tx": 65000,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 38,
"tx_rsni": 255,
"rx_rcpi": -51,
"tx_rcpi": 255,
},
{
"uid": "nl-217",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1644618833,
"node_1_uid": "n-1",
"node_2_uid": "n-128",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-127",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 54000,
"cur_data_rate_tx": 72200,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 41,
"tx_rsni": 255,
"rx_rcpi": -48,
"tx_rcpi": 255,
},
{
"uid": "nl-198",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1644618820,
"node_1_uid": "n-1",
"node_2_uid": "n-105",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-106",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 48000,
"cur_data_rate_tx": 58500,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 28,
"tx_rsni": 255,
"rx_rcpi": -61,
"tx_rcpi": 255,
},
{
"uid": "nl-213",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1644618820,
"node_1_uid": "n-1",
"node_2_uid": "n-111",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-112",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 48000,
"cur_data_rate_tx": 1000,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 44,
"tx_rsni": 255,
"rx_rcpi": -45,
"tx_rcpi": 255,
},
{
"uid": "nl-224",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1644618831,
"node_1_uid": "n-1",
"node_2_uid": "n-197",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-196",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 48000,
"cur_data_rate_tx": 1000,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 51,
"tx_rsni": 255,
"rx_rcpi": -38,
"tx_rcpi": 255,
},
{
"uid": "nl-182",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1644618822,
"node_1_uid": "n-1",
"node_2_uid": "n-56",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-55",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 54000,
"cur_data_rate_tx": 72200,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 34,
"tx_rsni": 255,
"rx_rcpi": -55,
"tx_rcpi": 255,
},
{
"uid": "nl-205",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1644618820,
"node_1_uid": "n-1",
"node_2_uid": "n-109",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-108",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 54000,
"cur_data_rate_tx": 1000,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 43,
"tx_rsni": 255,
"rx_rcpi": -46,
"tx_rcpi": 255,
},
{
"uid": "nl-240",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1644618827,
"node_1_uid": "n-1",
"node_2_uid": "n-95",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-96",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 48000,
"cur_data_rate_tx": 58500,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 25,
"tx_rsni": 255,
"rx_rcpi": -64,
"tx_rcpi": 255,
},
{
"uid": "nl-146",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1642872967,
"node_1_uid": "n-1",
"node_2_uid": "n-167",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-134",
"max_data_rate_rx": 144400,
"max_data_rate_tx": 144400,
"cur_data_rate_rx": 144400,
"cur_data_rate_tx": 130000,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 48,
"tx_rsni": 255,
"rx_rcpi": -41,
"tx_rcpi": 255,
},
{
"uid": "nl-232",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1644618829,
"node_1_uid": "n-1",
"node_2_uid": "n-18",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-17",
"max_data_rate_rx": 72200,
"max_data_rate_tx": 72200,
"cur_data_rate_rx": 48000,
"cur_data_rate_tx": 21700,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 22,
"tx_rsni": 255,
"rx_rcpi": -67,
"tx_rcpi": 255,
},
],
"ssid": MOCK_MESH_SSID,
"opmode": "AP",
"security": "WPA2_WPA3_MIXED",
"supported_streams_tx": [
["20 MHz", 2],
["40 MHz", 0],
["80 MHz", 0],
["160 MHz", 0],
["80+80 MHz", 0],
],
"supported_streams_rx": [
["20 MHz", 2],
["40 MHz", 0],
["80 MHz", 0],
["160 MHz", 0],
["80+80 MHz", 0],
],
"current_channel": 13,
"phymodes": ["g", "n", "ax"],
"channel_utilization": 0,
"anpi": -91,
"steering_enabled": True,
"11k_friendly": True,
"11v_friendly": True,
"legacy_friendly": True,
"rrm_compliant": False,
"channel_list": [
{"channel": 1},
{"channel": 2},
{"channel": 3},
{"channel": 4},
{"channel": 5},
{"channel": 6},
{"channel": 7},
{"channel": 8},
{"channel": 9},
{"channel": 10},
{"channel": 11},
{"channel": 12},
{"channel": 13},
],
},
],
},
{
"uid": "n-76",
"device_name": "printer",
"device_model": "",
"device_manufacturer": "",
"device_firmware_version": "",
"device_mac_address": "AA:BB:CC:00:11:22",
"is_meshed": False,
"mesh_role": "unknown",
"meshd_version": "0.0",
"node_interfaces": [
{
"uid": "ni-77",
"name": "eth0",
"type": "LAN",
"mac_address": "AA:BB:CC:00:11:22",
"blocking_state": "UNKNOWN",
"node_links": [
{
"uid": "nl-78",
"type": "LAN",
"state": "CONNECTED",
"last_connected": 1642872967,
"node_1_uid": "n-1",
"node_2_uid": "n-76",
"node_interface_1_uid": "ni-31",
"node_interface_2_uid": "ni-77",
"max_data_rate_rx": 1000000,
"max_data_rate_tx": 1000000,
"cur_data_rate_rx": 0,
"cur_data_rate_tx": 0,
"cur_availability_rx": 99,
"cur_availability_tx": 99,
}
],
}
],
},
{
"uid": "n-167",
"device_name": "fritz-repeater",
"device_model": "FRITZ!Box 7490",
"device_manufacturer": "AVM",
"device_firmware_version": "113.07.29",
"device_mac_address": MOCK_MESH_SLAVE_MAC,
"is_meshed": True,
"mesh_role": "slave",
"meshd_version": "3.13",
"node_interfaces": [
{
"uid": "ni-140",
"name": "LAN:3",
"type": "LAN",
"mac_address": MOCK_MESH_SLAVE_MAC,
"blocking_state": "UNKNOWN",
"node_links": [],
},
{
"uid": "ni-139",
"name": "LAN:4",
"type": "LAN",
"mac_address": MOCK_MESH_SLAVE_MAC,
"blocking_state": "UNKNOWN",
"node_links": [],
},
{
"uid": "ni-141",
"name": "LAN:2",
"type": "LAN",
"mac_address": MOCK_MESH_SLAVE_MAC,
"blocking_state": "UNKNOWN",
"node_links": [],
},
{
"uid": "ni-134",
"name": "UPLINK:2G:0",
"type": "WLAN",
"mac_address": MOCK_MESH_SLAVE_WIFI1_MAC,
"blocking_state": "UNKNOWN",
"node_links": [
{
"uid": "nl-146",
"type": "WLAN",
"state": "CONNECTED",
"last_connected": 1642872967,
"node_1_uid": "n-1",
"node_2_uid": "n-167",
"node_interface_1_uid": "ni-230",
"node_interface_2_uid": "ni-134",
"max_data_rate_rx": 144400,
"max_data_rate_tx": 144400,
"cur_data_rate_rx": 144400,
"cur_data_rate_tx": 130000,
"cur_availability_rx": 100,
"cur_availability_tx": 100,
"rx_rsni": 48,
"tx_rsni": 255,
"rx_rcpi": -41,
"tx_rcpi": 255,
}
],
"ssid": "",
"opmode": "WDS_REPEATER",
"security": "WPA3PSK",
"supported_streams_tx": [
["20 MHz", 3],
["40 MHz", 3],
["80 MHz", 0],
["160 MHz", 0],
["80+80 MHz", 0],
],
"supported_streams_rx": [
["20 MHz", 3],
["40 MHz", 3],
["80 MHz", 0],
["160 MHz", 0],
["80+80 MHz", 0],
],
"current_channel": 13,
"phymodes": ["b", "g", "n"],
"channel_utilization": 0,
"anpi": 255,
"steering_enabled": True,
"11k_friendly": False,
"11v_friendly": True,
"legacy_friendly": True,
"rrm_compliant": False,
"channel_list": [
{"channel": 1},
{"channel": 2},
{"channel": 3},
{"channel": 4},
{"channel": 5},
{"channel": 6},
{"channel": 7},
{"channel": 8},
{"channel": 9},
{"channel": 10},
{"channel": 11},
{"channel": 12},
{"channel": 13},
],
"client_position": "unknown",
},
{
"uid": "ni-143",
"name": "LANBridge",
"type": "LAN",
"mac_address": MOCK_MESH_SLAVE_MAC,
"blocking_state": "UNKNOWN",
"node_links": [],
},
{
"uid": "ni-142",
"name": "LAN:1",
"type": "LAN",
"mac_address": MOCK_MESH_SLAVE_MAC,
"blocking_state": "UNKNOWN",
"node_links": [],
},
],
},
],
}
MOCK_USER_DATA = MOCK_CONFIG[DOMAIN][CONF_DEVICES][0]
MOCK_DEVICE_INFO = {
@ -38,7 +787,7 @@ MOCK_DEVICE_INFO = {
MOCK_SSDP_DATA = ssdp.SsdpServiceInfo(
ssdp_usn="mock_usn",
ssdp_st="mock_st",
ssdp_location=f"https://{MOCK_IP}:12345/test",
ssdp_location=f"https://{MOCK_IPS['fritz.box']}:12345/test",
upnp={
ATTR_UPNP_FRIENDLY_NAME: "fake_name",
ATTR_UPNP_UDN: "uuid:only-a-test",

View File

@ -0,0 +1,75 @@
"""Tests for Shelly button platform."""
from unittest.mock import patch
import pytest
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
from homeassistant.components.fritz.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNKNOWN
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from .const import MOCK_USER_DATA
from tests.common import MockConfigEntry
async def test_button_setup(hass: HomeAssistant, fc_class_mock, fh_class_mock):
"""Test setup of Fritz!Tools buttons."""
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
buttons = hass.states.async_all(BUTTON_DOMAIN)
assert len(buttons) == 4
for button in buttons:
assert button.state == STATE_UNKNOWN
@pytest.mark.parametrize(
"entity_id, wrapper_method",
[
("button.mock_title_firmware_update", "async_trigger_firmware_update"),
("button.mock_title_reboot", "async_trigger_reboot"),
("button.mock_title_reconnect", "async_trigger_reconnect"),
("button.mock_title_cleanup", "async_trigger_cleanup"),
],
)
async def test_buttons(
hass: HomeAssistant,
entity_id: str,
wrapper_method: str,
fc_class_mock,
fh_class_mock,
):
"""Test Fritz!Tools buttons."""
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
button = hass.states.get(entity_id)
assert button
assert button.state == STATE_UNKNOWN
with patch(
f"homeassistant.components.fritz.common.AvmWrapper.{wrapper_method}"
) as mock_press_action:
await hass.services.async_call(
BUTTON_DOMAIN,
SERVICE_PRESS,
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
await hass.async_block_till_done()
mock_press_action.assert_called_once()
button = hass.states.get(entity_id)
assert button.state != STATE_UNKNOWN

View File

@ -26,7 +26,7 @@ from homeassistant.data_entry_flow import (
from .const import (
MOCK_FIRMWARE_INFO,
MOCK_IP,
MOCK_IPS,
MOCK_REQUEST,
MOCK_SSDP_DATA,
MOCK_USER_DATA,
@ -51,7 +51,7 @@ async def test_user(hass: HomeAssistant, fc_class_mock, mock_get_source_ip):
"requests.post"
) as mock_request_post, patch(
"homeassistant.components.fritz.config_flow.socket.gethostbyname",
return_value=MOCK_IP,
return_value=MOCK_IPS["fritz.box"],
):
mock_request_get.return_value.status_code = 200
@ -102,7 +102,7 @@ async def test_user_already_configured(
"requests.post"
) as mock_request_post, patch(
"homeassistant.components.fritz.config_flow.socket.gethostbyname",
return_value=MOCK_IP,
return_value=MOCK_IPS["fritz.box"],
):
mock_request_get.return_value.status_code = 200
@ -295,7 +295,7 @@ async def test_ssdp_already_configured(
side_effect=fc_class_mock,
), patch("homeassistant.components.fritz.common.FritzStatus"), patch(
"homeassistant.components.fritz.config_flow.socket.gethostbyname",
return_value=MOCK_IP,
return_value=MOCK_IPS["fritz.box"],
):
result = await hass.config_entries.flow.async_init(
@ -322,7 +322,7 @@ async def test_ssdp_already_configured_host(
side_effect=fc_class_mock,
), patch("homeassistant.components.fritz.common.FritzStatus"), patch(
"homeassistant.components.fritz.config_flow.socket.gethostbyname",
return_value=MOCK_IP,
return_value=MOCK_IPS["fritz.box"],
):
result = await hass.config_entries.flow.async_init(
@ -349,7 +349,7 @@ async def test_ssdp_already_configured_host_uuid(
side_effect=fc_class_mock,
), patch("homeassistant.components.fritz.common.FritzStatus"), patch(
"homeassistant.components.fritz.config_flow.socket.gethostbyname",
return_value=MOCK_IP,
return_value=MOCK_IPS["fritz.box"],
):
result = await hass.config_entries.flow.async_init(
@ -420,7 +420,7 @@ async def test_ssdp(hass: HomeAssistant, fc_class_mock, mock_get_source_ip):
)
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
assert result["data"][CONF_HOST] == MOCK_IP
assert result["data"][CONF_HOST] == MOCK_IPS["fritz.box"]
assert result["data"][CONF_PASSWORD] == "fake_pass"
assert result["data"][CONF_USERNAME] == "fake_user"

View File

@ -0,0 +1,80 @@
"""Tests for the AVM Fritz!Box integration."""
from __future__ import annotations
from aiohttp import ClientSession
from homeassistant.components.diagnostics import REDACTED
from homeassistant.components.fritz.common import AvmWrapper
from homeassistant.components.fritz.const import DOMAIN
from homeassistant.components.fritz.diagnostics import TO_REDACT
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from .const import MOCK_USER_DATA
from tests.common import MockConfigEntry
from tests.components.diagnostics import get_diagnostics_for_config_entry
async def test_entry_diagnostics(
hass: HomeAssistant, hass_client: ClientSession, fc_class_mock, fh_class_mock
):
"""Test config entry diagnostics."""
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
entry_dict = entry.as_dict()
for key in TO_REDACT:
entry_dict["data"][key] = REDACTED
result = await get_diagnostics_for_config_entry(hass, hass_client, entry)
avm_wrapper: AvmWrapper = hass.data[DOMAIN][entry.entry_id]
assert result == {
"entry": entry_dict,
"device_info": {
"client_devices": [
{
"connected_to": device.connected_to,
"connection_type": device.connection_type,
"hostname": device.hostname,
"is_connected": device.is_connected,
"last_activity": device.last_activity.isoformat(),
"wan_access": device.wan_access,
}
for _, device in avm_wrapper.devices.items()
],
"connection_type": "WANPPPConnection",
"current_firmware": "256.07.29",
"discovered_services": [
"DeviceInfo1",
"Hosts1",
"LANEthernetInterfaceConfig1",
"Layer3Forwarding1",
"UserInterface1",
"WANCommonIFC1",
"WANCommonInterfaceConfig1",
"WANDSLInterfaceConfig1",
"WANIPConn1",
"WANPPPConnection1",
"X_AVM-DE_Homeauto1",
"X_AVM-DE_HostFilter1",
],
"is_router": True,
"last_exception": None,
"last_update success": True,
"latest_firmware": None,
"mesh_role": "master",
"model": "FRITZ!Box 7530 AX",
"update_available": False,
"wan_link_properties": {
"NewLayer1DownstreamMaxBitRate": 318557000,
"NewLayer1UpstreamMaxBitRate": 51805000,
"NewPhysicalLinkStatus": "Up",
"NewWANAccessType": "DSL",
},
},
}

View File

@ -0,0 +1,96 @@
"""Tests for AVM Fritz!Box."""
from unittest.mock import patch
from fritzconnection.core.exceptions import FritzSecurityError
import pytest
from homeassistant.components.device_tracker.const import (
CONF_CONSIDER_HOME,
DEFAULT_CONSIDER_HOME,
)
from homeassistant.components.fritz.const import DOMAIN, FRITZ_EXCEPTIONS
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from .const import MOCK_USER_DATA
from tests.common import MockConfigEntry
async def test_setup(hass: HomeAssistant, fc_class_mock, fh_class_mock):
"""Test setup and unload of Fritz!Tools."""
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
await hass.config_entries.async_unload(entry.entry_id)
assert entry.state == ConfigEntryState.NOT_LOADED
async def test_options_reload(hass: HomeAssistant, fc_class_mock, fh_class_mock):
"""Test reload of Fritz!Tools, when options changed."""
entry = MockConfigEntry(
domain=DOMAIN,
data=MOCK_USER_DATA,
options={CONF_CONSIDER_HOME: DEFAULT_CONSIDER_HOME.total_seconds()},
)
entry.add_to_hass(hass)
with patch(
"homeassistant.config_entries.ConfigEntries.async_reload",
return_value=None,
) as mock_reload:
assert await async_setup_component(hass, DOMAIN, {})
await hass.async_block_till_done()
assert entry.state == ConfigEntryState.LOADED
result = await hass.config_entries.options.async_init(entry.entry_id)
await hass.async_block_till_done()
await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={CONF_CONSIDER_HOME: 60},
)
await hass.async_block_till_done()
mock_reload.assert_called_once()
async def test_setup_auth_fail(hass: HomeAssistant):
"""Test starting a flow by user with an already configured device."""
entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA)
entry.add_to_hass(hass)
with patch(
"homeassistant.components.fritz.common.FritzConnection",
side_effect=FritzSecurityError,
):
assert await async_setup_component(hass, DOMAIN, {})
await hass.async_block_till_done()
assert entry.state == ConfigEntryState.SETUP_ERROR
@pytest.mark.parametrize(
"error",
FRITZ_EXCEPTIONS,
)
async def test_setup_fail(hass: HomeAssistant, error):
"""Test starting a flow by user with an already configured device."""
entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA)
entry.add_to_hass(hass)
with patch(
"homeassistant.components.fritz.common.FritzConnection",
side_effect=error,
):
assert await async_setup_component(hass, DOMAIN, {})
await hass.async_block_till_done()
assert entry.state == ConfigEntryState.SETUP_RETRY