diff --git a/.coveragerc b/.coveragerc index 4dd8dea258d..71542ebad3a 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1328,9 +1328,6 @@ omit = homeassistant/components/tplink_omada/__init__.py homeassistant/components/tplink_omada/binary_sensor.py homeassistant/components/tplink_omada/controller.py - homeassistant/components/tplink_omada/coordinator.py - homeassistant/components/tplink_omada/entity.py - homeassistant/components/tplink_omada/switch.py homeassistant/components/tplink_omada/update.py homeassistant/components/traccar/device_tracker.py homeassistant/components/tractive/__init__.py diff --git a/tests/components/tplink_omada/conftest.py b/tests/components/tplink_omada/conftest.py new file mode 100644 index 00000000000..8f977de588c --- /dev/null +++ b/tests/components/tplink_omada/conftest.py @@ -0,0 +1,87 @@ +"""Test fixtures for TP-Link Omada integration.""" +from collections.abc import Generator +import json +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest +from tplink_omada_client.devices import OmadaSwitch, OmadaSwitchPortDetails + +from homeassistant.components.tplink_omada.config_flow import CONF_SITE +from homeassistant.components.tplink_omada.const import DOMAIN +from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, CONF_VERIFY_SSL +from homeassistant.core import HomeAssistant + +from tests.common import MockConfigEntry, load_fixture + + +@pytest.fixture +def mock_config_entry() -> MockConfigEntry: + """Return the default mocked config entry.""" + return MockConfigEntry( + title="Test Omada Controller", + domain=DOMAIN, + data={ + CONF_HOST: "127.0.0.1", + CONF_PASSWORD: "mocked-password", + CONF_USERNAME: "mocked-user", + CONF_VERIFY_SSL: False, + CONF_SITE: "Default", + }, + unique_id="12345", + ) + + +@pytest.fixture +def mock_setup_entry() -> Generator[AsyncMock, None, None]: + """Mock setting up a config entry.""" + with patch( + "homeassistant.components.tplink_omada.async_setup_entry", return_value=True + ) as mock_setup: + yield mock_setup + + +@pytest.fixture +def mock_omada_site_client() -> Generator[AsyncMock, None, None]: + """Mock Omada site client.""" + site_client = AsyncMock() + switch1_data = json.loads(load_fixture("switch-TL-SG3210XHP-M2.json", DOMAIN)) + switch1 = OmadaSwitch(switch1_data) + site_client.get_switches.return_value = [switch1] + + switch1_ports_data = json.loads( + load_fixture("switch-ports-TL-SG3210XHP-M2.json", DOMAIN) + ) + switch1_ports = [OmadaSwitchPortDetails(p) for p in switch1_ports_data] + site_client.get_switch_ports.return_value = switch1_ports + + return site_client + + +@pytest.fixture +def mock_omada_client( + mock_omada_site_client: AsyncMock, +) -> Generator[MagicMock, None, None]: + """Mock Omada client.""" + with patch( + "homeassistant.components.tplink_omada.create_omada_client", + autospec=True, + ) as client_mock: + client = client_mock.return_value + + client.get_site_client.return_value = mock_omada_site_client + yield client + + +@pytest.fixture +async def init_integration( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_omada_client: MagicMock, +) -> MockConfigEntry: + """Set up the TP-Link Omada integration for testing.""" + mock_config_entry.add_to_hass(hass) + + await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + return mock_config_entry diff --git a/tests/components/tplink_omada/fixtures/switch-TL-SG3210XHP-M2.json b/tests/components/tplink_omada/fixtures/switch-TL-SG3210XHP-M2.json new file mode 100644 index 00000000000..2e3f21406b0 --- /dev/null +++ b/tests/components/tplink_omada/fixtures/switch-TL-SG3210XHP-M2.json @@ -0,0 +1,683 @@ +{ + "type": "switch", + "mac": "54-AF-97-00-00-01", + "name": "Test PoE Switch", + "model": "TL-SG3210XHP-M2", + "modelVersion": "1.0", + "compoundModel": "TL-SG3210XHP-M2 v1.0", + "showModel": "TL-SG3210XHP-M2 v1.0", + "firmwareVersion": "1.0.12 Build 20230203 Rel.36545", + "version": "1.0.12", + "hwVersion": "1.0", + "status": 14, + "statusCategory": 1, + "site": "000000000000000000000000", + "omadacId": "00000000000000000000000000000000", + "compatible": 0, + "sn": "Y220000000001", + "addedInAdvanced": false, + "deviceMisc": { + "portNum": 10 + }, + "devCap": { + "maxMirrorGroup": 1, + "maxMirroredPort": 9, + "maxLagNum": 8, + "maxLagMember": 8, + "poePortNum": 8, + "poeSupport": true, + "supportBt": false, + "jumboSupport": true, + "jumboOddSupport": false, + "lagCap": { + "lacpModSupport": true, + "lagHashAlgSupport": true, + "lagHashAlgs": [0, 1, 2, 3, 4, 5] + }, + "eeeSupport": true, + "flowControlSupport": true, + "loopbackVlanBasedSupport": true, + "dhcpL2RelaySupport": true, + "sfpBeginNum": 9, + "sfpNum": 2 + }, + "ledSetting": 2, + "mvlanNetworkId": "000000000000000000000000", + "ipSetting": { + "mode": "dhcp", + "fallback": true, + "fallbackIp": "192.168.0.1", + "fallbackMask": "255.255.255.0" + }, + "loopbackDetectEnable": true, + "stp": 0, + "priority": 32768, + "snmp": { + "location": "", + "contact": "" + }, + "ports": [ + { + "id": "000000000000000000000001", + "port": 1, + "name": "Port1", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "operation": "switching", + "portStatus": { + "port": 1, + "linkStatus": 1, + "linkSpeed": 2, + "duplex": 2, + "poe": true, + "poePower": 2.7, + "tx": 22048870335, + "rx": 6155774646, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ] + }, + { + "id": "000000000000000000000002", + "port": 2, + "name": "Port2", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "operation": "switching", + "portStatus": { + "port": 2, + "linkStatus": 1, + "linkSpeed": 3, + "duplex": 2, + "poe": false, + "poePower": 0.0, + "tx": 2111818481511, + "rx": 297809855535, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ] + }, + { + "id": "000000000000000000000003", + "port": 3, + "name": "Primary AP", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "operation": "switching", + "portStatus": { + "port": 3, + "linkStatus": 1, + "linkSpeed": 4, + "duplex": 2, + "poe": true, + "poePower": 9.8, + "tx": 2118915311852, + "rx": 1222744181939, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ] + }, + { + "id": "000000000000000000000004", + "port": 4, + "name": "Port4", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "operation": "switching", + "portStatus": { + "port": 4, + "linkStatus": 0, + "linkSpeed": 0, + "duplex": 0, + "poe": false, + "poePower": 0.0, + "tx": 0, + "rx": 0, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ] + }, + { + "id": "000000000000000000000005", + "port": 5, + "name": "Port5", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "operation": "switching", + "portStatus": { + "port": 5, + "linkStatus": 1, + "linkSpeed": 3, + "duplex": 2, + "poe": true, + "poePower": 7.2, + "tx": 357059477760, + "rx": 59530432926, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ] + }, + { + "id": "000000000000000000000006", + "port": 6, + "name": "Port6", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "operation": "switching", + "portStatus": { + "port": 6, + "linkStatus": 1, + "linkSpeed": 3, + "duplex": 2, + "poe": false, + "poePower": 0.0, + "tx": 20729276425, + "rx": 1260359882, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ] + }, + { + "id": "000000000000000000000007", + "port": 7, + "name": "Port7", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "operation": "switching", + "portStatus": { + "port": 7, + "linkStatus": 0, + "linkSpeed": 0, + "duplex": 0, + "poe": false, + "poePower": 0.0, + "tx": 6884938116575, + "rx": 3015211000000, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ] + }, + { + "id": "000000000000000000000008", + "port": 8, + "name": "Family Room Kiosk", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "operation": "switching", + "portStatus": { + "port": 8, + "linkStatus": 1, + "linkSpeed": 3, + "duplex": 2, + "poe": true, + "poePower": 1.9, + "tx": 17735212467, + "rx": 2751725454, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ] + }, + { + "id": "000000000000000000000009", + "port": 9, + "name": "Port9", + "disable": false, + "type": 3, + "maxSpeed": 5, + "profileId": "00000000", + "profileName": "All", + "operation": "switching", + "portStatus": { + "port": 9, + "linkStatus": 0, + "linkSpeed": 0, + "duplex": 0, + "poe": false, + "tx": 0, + "rx": 0, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 5, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 3, + "duplex": 2 + } + ] + }, + { + "id": "00000000000000000000000a", + "port": 10, + "name": "Uplink", + "disable": false, + "type": 3, + "maxSpeed": 5, + "profileId": "00000000", + "profileName": "All", + "operation": "switching", + "portStatus": { + "port": 10, + "linkStatus": 1, + "linkSpeed": 5, + "duplex": 2, + "poe": false, + "tx": 4599788287992, + "rx": 11431810000000, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 5, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 3, + "duplex": 2 + } + ] + } + ], + "lags": [], + "tagIds": [], + "ip": "192.168.0.12", + "lastSeen": 1687385981898, + "needUpgrade": false, + "uptime": "97day(s) 23h 57m 34s", + "uptimeLong": 8467054, + "cpuUtil": 18, + "memUtil": 72, + "poeRemain": 218.399994, + "poeRemainPercent": 91.0, + "fanStatus": 0, + "downlinkList": [ + { + "port": 3, + "model": "EAP660 HD", + "hwVersion": "1.0", + "modelVersion": "1.0", + "mac": "B4-B0-24-00-00-01", + "name": "Access Point 1", + "linkSpeed": 4, + "duplex": 2 + }, + { + "port": 5, + "model": "EAP653", + "hwVersion": "1.0", + "modelVersion": "1.0", + "mac": "34-60-F9-00-00-01E", + "name": "Access Point 2", + "linkSpeed": 3, + "duplex": 2 + } + ], + "download": 16037273330382, + "upload": 16133033034917, + "supportVlanIf": true, + "jumbo": 1518, + "lagHashAlg": 2, + "speeds": [2, 3, 4, 5] +} diff --git a/tests/components/tplink_omada/fixtures/switch-ports-TL-SG3210XHP-M2.json b/tests/components/tplink_omada/fixtures/switch-ports-TL-SG3210XHP-M2.json new file mode 100644 index 00000000000..b079b2d2fb7 --- /dev/null +++ b/tests/components/tplink_omada/fixtures/switch-ports-TL-SG3210XHP-M2.json @@ -0,0 +1,974 @@ +[ + { + "id": "000000000000000000000001", + "port": 1, + "switchId": "640934810000000000000000", + "switchMac": "54-AF-97-00-00-01", + "site": "000000000000000000000000", + "name": "Port1", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "profileOverrideEnable": false, + "operation": "switching", + "linkSpeed": 0, + "duplex": 0, + "dot1x": 2, + "poe": 1, + "bandWidthCtrlType": 0, + "bandCtrl": { + "egressEnable": false, + "egressLimit": 0, + "egressUnit": 1, + "ingressEnable": false, + "ingressLimit": 0, + "ingressUnit": 1 + }, + "stormCtrl": { + "unknownUnicastEnable": false, + "unknownUnicast": 0, + "multicastEnable": false, + "multicast": 0, + "broadcastEnable": false, + "broadcast": 0, + "action": 0, + "recoverTime": 3600 + }, + "lldpMedEnable": true, + "topoNotifyEnable": false, + "spanningTreeEnable": false, + "loopbackDetectEnable": true, + "loopbackDetectVlanBasedEnable": false, + "portIsolationEnable": false, + "portStatus": { + "port": 1, + "linkStatus": 1, + "linkSpeed": 2, + "duplex": 2, + "poe": true, + "poePower": 2.7, + "tx": 22265663705, + "rx": 6202420396, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ], + "eeeEnable": false, + "flowControlEnable": false, + "dhcpL2RelaySettings": { + "enable": false, + "format": 0 + } + }, + { + "id": "000000000000000000000002", + "port": 2, + "switchId": "640934810000000000000000", + "switchMac": "54-AF-97-00-00-01", + "site": "000000000000000000000000", + "name": "Port2", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "profileOverrideEnable": true, + "operation": "switching", + "linkSpeed": 0, + "duplex": 0, + "dot1x": 1, + "poe": 1, + "bandWidthCtrlType": 0, + "bandCtrl": { + "egressEnable": false, + "egressLimit": 0, + "egressUnit": 1, + "ingressEnable": false, + "ingressLimit": 0, + "ingressUnit": 1 + }, + "stormCtrl": { + "unknownUnicastEnable": false, + "unknownUnicast": 0, + "multicastEnable": false, + "multicast": 0, + "broadcastEnable": false, + "broadcast": 0, + "action": 0, + "recoverTime": 3600 + }, + "lldpMedEnable": true, + "topoNotifyEnable": false, + "spanningTreeEnable": false, + "loopbackDetectEnable": true, + "loopbackDetectVlanBasedEnable": false, + "portIsolationEnable": false, + "portStatus": { + "port": 2, + "linkStatus": 1, + "linkSpeed": 3, + "duplex": 2, + "poe": false, + "poePower": 0.0, + "tx": 2136778000000, + "rx": 298419647322, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ], + "eeeEnable": false, + "flowControlEnable": false, + "dhcpL2RelaySettings": { + "enable": false, + "format": 0 + } + }, + { + "id": "000000000000000000000003", + "port": 3, + "switchId": "640934810000000000000000", + "switchMac": "54-AF-97-00-00-01", + "site": "000000000000000000000000", + "name": "Port3", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "profileOverrideEnable": false, + "operation": "switching", + "linkSpeed": 0, + "duplex": 0, + "dot1x": 2, + "poe": 1, + "bandWidthCtrlType": 0, + "bandCtrl": { + "egressEnable": false, + "egressLimit": 0, + "egressUnit": 1, + "ingressEnable": false, + "ingressLimit": 0, + "ingressUnit": 1 + }, + "stormCtrl": { + "unknownUnicastEnable": false, + "unknownUnicast": 0, + "multicastEnable": false, + "multicast": 0, + "broadcastEnable": false, + "broadcast": 0, + "action": 0, + "recoverTime": 3600 + }, + "lldpMedEnable": true, + "topoNotifyEnable": false, + "spanningTreeEnable": false, + "loopbackDetectEnable": true, + "loopbackDetectVlanBasedEnable": false, + "portIsolationEnable": false, + "portStatus": { + "port": 3, + "linkStatus": 1, + "linkSpeed": 4, + "duplex": 2, + "poe": true, + "poePower": 10.0, + "tx": 2139129000000, + "rx": 1241262105432, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ], + "eeeEnable": false, + "flowControlEnable": false, + "dhcpL2RelaySettings": { + "enable": false, + "format": 0 + } + }, + { + "id": "000000000000000000000004", + "port": 4, + "switchId": "640934810000000000000000", + "switchMac": "54-AF-97-00-00-01", + "site": "000000000000000000000000", + "name": "Port4", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "profileOverrideEnable": false, + "operation": "switching", + "linkSpeed": 0, + "duplex": 0, + "dot1x": 2, + "poe": 1, + "bandWidthCtrlType": 0, + "bandCtrl": { + "egressEnable": false, + "egressLimit": 0, + "egressUnit": 1, + "ingressEnable": false, + "ingressLimit": 0, + "ingressUnit": 1 + }, + "stormCtrl": { + "unknownUnicastEnable": false, + "unknownUnicast": 0, + "multicastEnable": false, + "multicast": 0, + "broadcastEnable": false, + "broadcast": 0, + "action": 0, + "recoverTime": 3600 + }, + "lldpMedEnable": true, + "topoNotifyEnable": false, + "spanningTreeEnable": false, + "loopbackDetectEnable": false, + "loopbackDetectVlanBasedEnable": false, + "portIsolationEnable": false, + "portStatus": { + "port": 4, + "linkStatus": 0, + "linkSpeed": 0, + "duplex": 0, + "poe": false, + "poePower": 0.0, + "tx": 0, + "rx": 0, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ], + "eeeEnable": false, + "flowControlEnable": false, + "dhcpL2RelaySettings": { + "enable": false, + "format": 0 + } + }, + { + "id": "000000000000000000000005", + "port": 5, + "switchId": "640934810000000000000000", + "switchMac": "54-AF-97-00-00-01", + "site": "000000000000000000000000", + "name": "Port5", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "profileOverrideEnable": false, + "operation": "switching", + "linkSpeed": 0, + "duplex": 0, + "dot1x": 2, + "poe": 1, + "bandWidthCtrlType": 0, + "bandCtrl": { + "egressEnable": false, + "egressLimit": 0, + "egressUnit": 1, + "ingressEnable": false, + "ingressLimit": 0, + "ingressUnit": 1 + }, + "stormCtrl": { + "unknownUnicastEnable": false, + "unknownUnicast": 0, + "multicastEnable": false, + "multicast": 0, + "broadcastEnable": false, + "broadcast": 0, + "action": 0, + "recoverTime": 3600 + }, + "lldpMedEnable": true, + "topoNotifyEnable": false, + "spanningTreeEnable": false, + "loopbackDetectEnable": true, + "loopbackDetectVlanBasedEnable": false, + "portIsolationEnable": false, + "portStatus": { + "port": 5, + "linkStatus": 1, + "linkSpeed": 3, + "duplex": 2, + "poe": true, + "poePower": 7.7, + "tx": 358431854723, + "rx": 62202058965, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ], + "eeeEnable": false, + "flowControlEnable": false, + "dhcpL2RelaySettings": { + "enable": false, + "format": 0 + } + }, + { + "id": "000000000000000000000006", + "port": 6, + "switchId": "640934810000000000000000", + "switchMac": "54-AF-97-00-00-01", + "site": "000000000000000000000000", + "name": "Port6", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "profileOverrideEnable": false, + "operation": "switching", + "linkSpeed": 0, + "duplex": 0, + "dot1x": 2, + "poe": 1, + "bandWidthCtrlType": 0, + "bandCtrl": { + "egressEnable": false, + "egressLimit": 0, + "egressUnit": 1, + "ingressEnable": false, + "ingressLimit": 0, + "ingressUnit": 1 + }, + "stormCtrl": { + "unknownUnicastEnable": false, + "unknownUnicast": 0, + "multicastEnable": false, + "multicast": 0, + "broadcastEnable": false, + "broadcast": 0, + "action": 0, + "recoverTime": 3600 + }, + "lldpMedEnable": true, + "topoNotifyEnable": false, + "spanningTreeEnable": false, + "loopbackDetectEnable": false, + "loopbackDetectVlanBasedEnable": false, + "portIsolationEnable": false, + "portStatus": { + "port": 6, + "linkStatus": 1, + "linkSpeed": 3, + "duplex": 2, + "poe": false, + "poePower": 0.0, + "tx": 21045680895, + "rx": 1266702649, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ], + "eeeEnable": false, + "flowControlEnable": false, + "dhcpL2RelaySettings": { + "enable": false, + "format": 0 + } + }, + { + "id": "000000000000000000000007", + "port": 7, + "switchId": "640934810000000000000000", + "switchMac": "54-AF-97-00-00-01", + "site": "000000000000000000000000", + "name": "Port7", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "profileOverrideEnable": false, + "operation": "switching", + "linkSpeed": 0, + "duplex": 0, + "dot1x": 2, + "poe": 1, + "bandWidthCtrlType": 0, + "bandCtrl": { + "egressEnable": false, + "egressLimit": 0, + "egressUnit": 1, + "ingressEnable": false, + "ingressLimit": 0, + "ingressUnit": 1 + }, + "stormCtrl": { + "unknownUnicastEnable": false, + "unknownUnicast": 0, + "multicastEnable": false, + "multicast": 0, + "broadcastEnable": false, + "broadcast": 0, + "action": 0, + "recoverTime": 3600 + }, + "lldpMedEnable": true, + "topoNotifyEnable": false, + "spanningTreeEnable": false, + "loopbackDetectEnable": false, + "loopbackDetectVlanBasedEnable": false, + "portIsolationEnable": false, + "portStatus": { + "port": 7, + "linkStatus": 0, + "linkSpeed": 0, + "duplex": 0, + "poe": false, + "poePower": 0.0, + "tx": 6884938116575, + "rx": 3015211000000, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ], + "eeeEnable": false, + "flowControlEnable": false, + "dhcpL2RelaySettings": { + "enable": false, + "format": 0 + } + }, + { + "id": "000000000000000000000008", + "port": 8, + "switchId": "640934810000000000000000", + "switchMac": "54-AF-97-00-00-01", + "site": "000000000000000000000000", + "name": "Port8", + "disable": false, + "type": 1, + "maxSpeed": 4, + "profileId": "00000000", + "profileName": "All", + "profileOverrideEnable": false, + "operation": "switching", + "linkSpeed": 0, + "duplex": 0, + "dot1x": 2, + "poe": 1, + "bandWidthCtrlType": 0, + "bandCtrl": { + "egressEnable": false, + "egressLimit": 0, + "egressUnit": 1, + "ingressEnable": false, + "ingressLimit": 0, + "ingressUnit": 1 + }, + "stormCtrl": { + "unknownUnicastEnable": false, + "unknownUnicast": 0, + "multicastEnable": false, + "multicast": 0, + "broadcastEnable": false, + "broadcast": 0, + "action": 0, + "recoverTime": 3600 + }, + "lldpMedEnable": true, + "topoNotifyEnable": false, + "spanningTreeEnable": false, + "loopbackDetectEnable": false, + "loopbackDetectVlanBasedEnable": false, + "portIsolationEnable": false, + "portStatus": { + "port": 8, + "linkStatus": 1, + "linkSpeed": 3, + "duplex": 2, + "poe": true, + "poePower": 1.9, + "tx": 17983115259, + "rx": 2764463784, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 2, + "duplex": 1 + }, + { + "linkSpeed": 2, + "duplex": 2 + }, + { + "linkSpeed": 4, + "duplex": 0 + }, + { + "linkSpeed": 4, + "duplex": 2 + }, + { + "linkSpeed": 0, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 1 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 0, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 2 + }, + { + "linkSpeed": 2, + "duplex": 0 + } + ], + "eeeEnable": false, + "flowControlEnable": false, + "dhcpL2RelaySettings": { + "enable": false, + "format": 0 + } + }, + { + "id": "000000000000000000000009", + "port": 9, + "switchId": "640934810000000000000000", + "switchMac": "54-AF-97-00-00-01", + "site": "000000000000000000000000", + "name": "Port9", + "disable": false, + "type": 3, + "maxSpeed": 5, + "profileId": "00000000", + "profileName": "All", + "profileOverrideEnable": false, + "operation": "switching", + "linkSpeed": 5, + "duplex": 2, + "dot1x": 2, + "poe": 1, + "bandWidthCtrlType": 0, + "bandCtrl": { + "egressEnable": false, + "egressLimit": 0, + "egressUnit": 1, + "ingressEnable": false, + "ingressLimit": 0, + "ingressUnit": 1 + }, + "stormCtrl": { + "unknownUnicastEnable": false, + "unknownUnicast": 0, + "multicastEnable": false, + "multicast": 0, + "broadcastEnable": false, + "broadcast": 0, + "action": 0, + "recoverTime": 3600 + }, + "lldpMedEnable": true, + "topoNotifyEnable": false, + "spanningTreeEnable": false, + "loopbackDetectEnable": true, + "loopbackDetectVlanBasedEnable": false, + "portIsolationEnable": false, + "portStatus": { + "port": 9, + "linkStatus": 0, + "linkSpeed": 0, + "duplex": 0, + "poe": false, + "tx": 0, + "rx": 0, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 5, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 3, + "duplex": 2 + } + ], + "eeeEnable": false, + "flowControlEnable": false, + "dhcpL2RelaySettings": { + "enable": false, + "format": 0 + } + }, + { + "id": "00000000000000000000000a", + "port": 10, + "switchId": "640934810000000000000000", + "switchMac": "54-AF-97-00-00-01", + "site": "000000000000000000000000", + "name": "Port10", + "disable": false, + "type": 3, + "maxSpeed": 5, + "profileId": "00000000", + "profileName": "All", + "profileOverrideEnable": false, + "operation": "switching", + "linkSpeed": 5, + "duplex": 2, + "dot1x": 2, + "poe": 1, + "bandWidthCtrlType": 0, + "bandCtrl": { + "egressEnable": false, + "egressLimit": 0, + "egressUnit": 1, + "ingressEnable": false, + "ingressLimit": 0, + "ingressUnit": 1 + }, + "stormCtrl": { + "unknownUnicastEnable": false, + "unknownUnicast": 0, + "multicastEnable": false, + "multicast": 0, + "broadcastEnable": false, + "broadcast": 0, + "action": 0, + "recoverTime": 3600 + }, + "lldpMedEnable": true, + "topoNotifyEnable": false, + "spanningTreeEnable": false, + "loopbackDetectEnable": true, + "loopbackDetectVlanBasedEnable": false, + "portIsolationEnable": false, + "portStatus": { + "port": 10, + "linkStatus": 1, + "linkSpeed": 5, + "duplex": 2, + "poe": false, + "tx": 4621489812572, + "rx": 11477190000000, + "stpDiscarding": false + }, + "portCap": [ + { + "linkSpeed": 5, + "duplex": 2 + }, + { + "linkSpeed": 3, + "duplex": 0 + }, + { + "linkSpeed": 3, + "duplex": 2 + } + ], + "eeeEnable": false, + "flowControlEnable": false, + "dhcpL2RelaySettings": { + "enable": false, + "format": 0 + } + } +] diff --git a/tests/components/tplink_omada/snapshots/test_switch.ambr b/tests/components/tplink_omada/snapshots/test_switch.ambr new file mode 100644 index 00000000000..b48f6a5e749 --- /dev/null +++ b/tests/components/tplink_omada/snapshots/test_switch.ambr @@ -0,0 +1,345 @@ +# serializer version: 1 +# name: test_poe_switches + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test PoE Switch Port 1 PoE', + 'icon': 'mdi:ethernet', + }), + 'context': , + 'entity_id': 'switch.test_poe_switch_port_1_poe', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_poe_switches.1 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'switch', + 'entity_category': , + 'entity_id': 'switch.test_poe_switch_port_1_poe', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:ethernet', + 'original_name': 'Port 1 PoE', + 'platform': 'tplink_omada', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '54-AF-97-00-00-01_000000000000000000000001_poe', + 'unit_of_measurement': None, + }) +# --- +# name: test_poe_switches.10 + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test PoE Switch Port 6 PoE', + 'icon': 'mdi:ethernet', + }), + 'context': , + 'entity_id': 'switch.test_poe_switch_port_6_poe', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_poe_switches.11 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'switch', + 'entity_category': , + 'entity_id': 'switch.test_poe_switch_port_6_poe', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:ethernet', + 'original_name': 'Port 6 PoE', + 'platform': 'tplink_omada', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '54-AF-97-00-00-01_000000000000000000000006_poe', + 'unit_of_measurement': None, + }) +# --- +# name: test_poe_switches.12 + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test PoE Switch Port 7 PoE', + 'icon': 'mdi:ethernet', + }), + 'context': , + 'entity_id': 'switch.test_poe_switch_port_7_poe', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_poe_switches.13 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'switch', + 'entity_category': , + 'entity_id': 'switch.test_poe_switch_port_7_poe', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:ethernet', + 'original_name': 'Port 7 PoE', + 'platform': 'tplink_omada', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '54-AF-97-00-00-01_000000000000000000000007_poe', + 'unit_of_measurement': None, + }) +# --- +# name: test_poe_switches.14 + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test PoE Switch Port 8 PoE', + 'icon': 'mdi:ethernet', + }), + 'context': , + 'entity_id': 'switch.test_poe_switch_port_8_poe', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_poe_switches.15 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'switch', + 'entity_category': , + 'entity_id': 'switch.test_poe_switch_port_8_poe', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:ethernet', + 'original_name': 'Port 8 PoE', + 'platform': 'tplink_omada', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '54-AF-97-00-00-01_000000000000000000000008_poe', + 'unit_of_measurement': None, + }) +# --- +# name: test_poe_switches.2 + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test PoE Switch Port 2 PoE', + 'icon': 'mdi:ethernet', + }), + 'context': , + 'entity_id': 'switch.test_poe_switch_port_2_poe', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_poe_switches.3 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'switch', + 'entity_category': , + 'entity_id': 'switch.test_poe_switch_port_2_poe', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:ethernet', + 'original_name': 'Port 2 PoE', + 'platform': 'tplink_omada', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '54-AF-97-00-00-01_000000000000000000000002_poe', + 'unit_of_measurement': None, + }) +# --- +# name: test_poe_switches.4 + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test PoE Switch Port 3 PoE', + 'icon': 'mdi:ethernet', + }), + 'context': , + 'entity_id': 'switch.test_poe_switch_port_3_poe', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_poe_switches.5 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'switch', + 'entity_category': , + 'entity_id': 'switch.test_poe_switch_port_3_poe', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:ethernet', + 'original_name': 'Port 3 PoE', + 'platform': 'tplink_omada', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '54-AF-97-00-00-01_000000000000000000000003_poe', + 'unit_of_measurement': None, + }) +# --- +# name: test_poe_switches.6 + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test PoE Switch Port 4 PoE', + 'icon': 'mdi:ethernet', + }), + 'context': , + 'entity_id': 'switch.test_poe_switch_port_4_poe', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_poe_switches.7 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'switch', + 'entity_category': , + 'entity_id': 'switch.test_poe_switch_port_4_poe', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:ethernet', + 'original_name': 'Port 4 PoE', + 'platform': 'tplink_omada', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '54-AF-97-00-00-01_000000000000000000000004_poe', + 'unit_of_measurement': None, + }) +# --- +# name: test_poe_switches.8 + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test PoE Switch Port 5 PoE', + 'icon': 'mdi:ethernet', + }), + 'context': , + 'entity_id': 'switch.test_poe_switch_port_5_poe', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_poe_switches.9 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'switch', + 'entity_category': , + 'entity_id': 'switch.test_poe_switch_port_5_poe', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:ethernet', + 'original_name': 'Port 5 PoE', + 'platform': 'tplink_omada', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '54-AF-97-00-00-01_000000000000000000000005_poe', + 'unit_of_measurement': None, + }) +# --- diff --git a/tests/components/tplink_omada/test_switch.py b/tests/components/tplink_omada/test_switch.py new file mode 100644 index 00000000000..dd8b520e0a8 --- /dev/null +++ b/tests/components/tplink_omada/test_switch.py @@ -0,0 +1,122 @@ +"""Tests for TP-Link Omada switch entities.""" +from unittest.mock import MagicMock + +from syrupy.assertion import SnapshotAssertion +from tplink_omada_client.definitions import PoEMode +from tplink_omada_client.devices import OmadaSwitch, OmadaSwitchPortDetails +from tplink_omada_client.omadasiteclient import SwitchPortOverrides + +from homeassistant.components import switch +from homeassistant.const import ATTR_ENTITY_ID +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from tests.common import MockConfigEntry + + +async def test_poe_switches( + hass: HomeAssistant, + mock_omada_site_client: MagicMock, + init_integration: MockConfigEntry, + snapshot: SnapshotAssertion, +) -> None: + """Test PoE switch.""" + poe_switch_mac = "54-AF-97-00-00-01" + for i in range(1, 9): + await _test_poe_switch( + hass, + mock_omada_site_client, + f"switch.test_poe_switch_port_{i}_poe", + poe_switch_mac, + i, + snapshot, + ) + + +async def _test_poe_switch( + hass: HomeAssistant, + mock_omada_site_client: MagicMock, + entity_id: str, + network_switch_mac: str, + port_num: int, + snapshot: SnapshotAssertion, +) -> None: + entity_registry = er.async_get(hass) + + def assert_update_switch_port( + device: OmadaSwitch, + switch_port_details: OmadaSwitchPortDetails, + poe_enabled: bool, + overrides: SwitchPortOverrides = None, + ) -> None: + assert device + assert device.mac == network_switch_mac + assert switch_port_details + assert switch_port_details.port == port_num + assert overrides + assert overrides.enable_poe == poe_enabled + + entity = hass.states.get(entity_id) + assert entity == snapshot + entry = entity_registry.async_get(entity_id) + assert entry == snapshot + + mock_omada_site_client.update_switch_port.reset_mock() + mock_omada_site_client.update_switch_port.return_value = await _update_port_details( + mock_omada_site_client, port_num, False + ) + await call_service(hass, "turn_off", entity_id) + mock_omada_site_client.update_switch_port.assert_called_once() + ( + device, + switch_port_details, + ) = mock_omada_site_client.update_switch_port.call_args.args + assert_update_switch_port( + device, + switch_port_details, + False, + **mock_omada_site_client.update_switch_port.call_args.kwargs, + ) + entity = hass.states.get(entity_id) + assert entity.state == "off" + + mock_omada_site_client.update_switch_port.reset_mock() + mock_omada_site_client.update_switch_port.return_value = await _update_port_details( + mock_omada_site_client, port_num, True + ) + await call_service(hass, "turn_on", entity_id) + mock_omada_site_client.update_switch_port.assert_called_once() + device, switch_port = mock_omada_site_client.update_switch_port.call_args.args + assert_update_switch_port( + device, + switch_port, + True, + **mock_omada_site_client.update_switch_port.call_args.kwargs, + ) + entity = hass.states.get(entity_id) + assert entity.state == "on" + + +async def _update_port_details( + mock_omada_site_client: MagicMock, + port_num: int, + poe_enabled: bool, +) -> OmadaSwitchPortDetails: + switch_ports = await mock_omada_site_client.get_switch_ports() + port_details: OmadaSwitchPortDetails = None + for details in switch_ports: + if details.port == port_num: + port_details = details + break + + assert port_details is not None + raw_data = port_details.raw_data.copy() + raw_data["poe"] = PoEMode.ENABLED if poe_enabled else PoEMode.DISABLED + return OmadaSwitchPortDetails(raw_data) + + +def call_service(hass: HomeAssistant, service: str, entity_id: str): + """Call any service on entity.""" + return hass.services.async_call( + switch.DOMAIN, service, {ATTR_ENTITY_ID: entity_id}, blocking=True + )