mirror of
https://github.com/home-assistant/core.git
synced 2026-02-15 07:36:16 +00:00
Improve quality scale to silver HDFury integration (#161077)
This commit is contained in:
@@ -19,6 +19,8 @@ from .const import DOMAIN
|
||||
from .coordinator import HDFuryConfigEntry
|
||||
from .entity import HDFuryEntity
|
||||
|
||||
PARALLEL_UPDATES = 1
|
||||
|
||||
|
||||
@dataclass(kw_only=True, frozen=True)
|
||||
class HDFuryButtonEntityDescription(ButtonEntityDescription):
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/hdfury",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"quality_scale": "bronze",
|
||||
"quality_scale": "silver",
|
||||
"requirements": ["hdfury==1.3.1"]
|
||||
}
|
||||
|
||||
@@ -35,11 +35,11 @@ rules:
|
||||
entity-unavailable: done
|
||||
integration-owner: done
|
||||
log-when-unavailable: done
|
||||
parallel-updates: todo
|
||||
parallel-updates: done
|
||||
reauthentication-flow:
|
||||
status: exempt
|
||||
comment: Integration has no authentication flow.
|
||||
test-coverage: todo
|
||||
test-coverage: done
|
||||
|
||||
# Gold
|
||||
devices: done
|
||||
|
||||
@@ -20,6 +20,8 @@ from .const import DOMAIN
|
||||
from .coordinator import HDFuryConfigEntry, HDFuryCoordinator
|
||||
from .entity import HDFuryEntity
|
||||
|
||||
PARALLEL_UPDATES = 1
|
||||
|
||||
|
||||
@dataclass(kw_only=True, frozen=True)
|
||||
class HDFurySelectEntityDescription(SelectEntityDescription):
|
||||
@@ -77,13 +79,11 @@ async def async_setup_entry(
|
||||
|
||||
coordinator = entry.runtime_data
|
||||
|
||||
entities: list[HDFuryEntity] = []
|
||||
|
||||
for description in SELECT_PORTS:
|
||||
if description.key not in coordinator.data.info:
|
||||
continue
|
||||
|
||||
entities.append(HDFurySelect(coordinator, description))
|
||||
entities: list[HDFuryEntity] = [
|
||||
HDFurySelect(coordinator, description)
|
||||
for description in SELECT_PORTS
|
||||
if description.key in coordinator.data.info
|
||||
]
|
||||
|
||||
# Add OPMODE select if present
|
||||
if "opmode" in coordinator.data.info:
|
||||
|
||||
@@ -8,6 +8,8 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
from .coordinator import HDFuryConfigEntry
|
||||
from .entity import HDFuryEntity
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
SENSORS: tuple[SensorEntityDescription, ...] = (
|
||||
SensorEntityDescription(
|
||||
key="RX0",
|
||||
|
||||
@@ -16,6 +16,8 @@ from .const import DOMAIN
|
||||
from .coordinator import HDFuryConfigEntry
|
||||
from .entity import HDFuryEntity
|
||||
|
||||
PARALLEL_UPDATES = 1
|
||||
|
||||
|
||||
@dataclass(kw_only=True, frozen=True)
|
||||
class HDFurySwitchEntityDescription(SwitchEntityDescription):
|
||||
|
||||
@@ -6,7 +6,8 @@ from hdfury import HDFuryError
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
|
||||
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
import homeassistant.helpers.entity_registry as er
|
||||
@@ -47,9 +48,9 @@ async def test_button_presses(
|
||||
await setup_integration(hass, mock_config_entry, [Platform.BUTTON])
|
||||
|
||||
await hass.services.async_call(
|
||||
"button",
|
||||
"press",
|
||||
{"entity_id": entity_id},
|
||||
BUTTON_DOMAIN,
|
||||
SERVICE_PRESS,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
@@ -67,10 +68,13 @@ async def test_button_press_error(
|
||||
|
||||
await setup_integration(hass, mock_config_entry, [Platform.BUTTON])
|
||||
|
||||
with pytest.raises(HomeAssistantError):
|
||||
with pytest.raises(
|
||||
HomeAssistantError,
|
||||
match="An error occurred while communicating with HDFury device",
|
||||
):
|
||||
await hass.services.async_call(
|
||||
"button",
|
||||
"press",
|
||||
{"entity_id": "button.hdfury_vrroom_02_restart"},
|
||||
BUTTON_DOMAIN,
|
||||
SERVICE_PRESS,
|
||||
{ATTR_ENTITY_ID: "button.hdfury_vrroom_02_restart"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
@@ -1,14 +1,25 @@
|
||||
"""Tests for the HDFury select platform."""
|
||||
|
||||
from datetime import timedelta
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from hdfury import HDFuryError
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.components.select import (
|
||||
DOMAIN as SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_OPTION, STATE_UNAVAILABLE, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
import homeassistant.helpers.entity_registry as er
|
||||
|
||||
from . import setup_integration
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||
|
||||
|
||||
async def test_select_entities(
|
||||
@@ -21,3 +32,133 @@ async def test_select_entities(
|
||||
|
||||
await setup_integration(hass, mock_config_entry, [Platform.SELECT])
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
async def test_select_operation_mode(
|
||||
hass: HomeAssistant,
|
||||
mock_hdfury_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test selecting operation mode."""
|
||||
|
||||
await setup_integration(hass, mock_config_entry, [Platform.SELECT])
|
||||
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{
|
||||
ATTR_ENTITY_ID: "select.hdfury_vrroom_02_operation_mode",
|
||||
ATTR_OPTION: "1",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mock_hdfury_client.set_operation_mode.assert_awaited_once_with("1")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("entity_id"),
|
||||
[
|
||||
("select.hdfury_vrroom_02_port_select_tx0"),
|
||||
("select.hdfury_vrroom_02_port_select_tx1"),
|
||||
],
|
||||
)
|
||||
async def test_select_tx_ports(
|
||||
hass: HomeAssistant,
|
||||
mock_hdfury_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_id: str,
|
||||
) -> None:
|
||||
"""Test selecting TX ports."""
|
||||
|
||||
await setup_integration(hass, mock_config_entry, [Platform.SELECT])
|
||||
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{
|
||||
ATTR_ENTITY_ID: entity_id,
|
||||
ATTR_OPTION: "1",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mock_hdfury_client.set_port_selection.assert_awaited()
|
||||
|
||||
|
||||
async def test_select_operation_mode_error(
|
||||
hass: HomeAssistant,
|
||||
mock_hdfury_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test operation mode select raises HomeAssistantError."""
|
||||
|
||||
mock_hdfury_client.set_operation_mode.side_effect = HDFuryError()
|
||||
|
||||
await setup_integration(hass, mock_config_entry, [Platform.SELECT])
|
||||
|
||||
with pytest.raises(
|
||||
HomeAssistantError,
|
||||
match="An error occurred while communicating with HDFury device",
|
||||
):
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{
|
||||
ATTR_ENTITY_ID: "select.hdfury_vrroom_02_operation_mode",
|
||||
ATTR_OPTION: "1",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_select_ports_missing_state(
|
||||
hass: HomeAssistant,
|
||||
mock_hdfury_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test TX port selection fails when TX state is incomplete."""
|
||||
|
||||
mock_hdfury_client.get_info.return_value = {
|
||||
"portseltx0": "0",
|
||||
"portseltx1": None,
|
||||
"opmode": "0",
|
||||
}
|
||||
|
||||
await setup_integration(hass, mock_config_entry, [Platform.SELECT])
|
||||
|
||||
with pytest.raises(
|
||||
HomeAssistantError,
|
||||
match="An error occurred while validating TX states",
|
||||
):
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{
|
||||
ATTR_ENTITY_ID: "select.hdfury_vrroom_02_port_select_tx0",
|
||||
ATTR_OPTION: "0",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_select_entities_unavailable_on_error(
|
||||
hass: HomeAssistant,
|
||||
mock_hdfury_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test API error causes entities to become unavailable."""
|
||||
|
||||
await setup_integration(hass, mock_config_entry, [Platform.SELECT])
|
||||
|
||||
mock_hdfury_client.get_info.side_effect = HDFuryError()
|
||||
|
||||
freezer.tick(timedelta(seconds=61))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
hass.states.get("select.hdfury_vrroom_02_port_select_tx0").state
|
||||
== STATE_UNAVAILABLE
|
||||
)
|
||||
|
||||
@@ -1,19 +1,28 @@
|
||||
"""Tests for the HDFury switch platform."""
|
||||
|
||||
from datetime import timedelta
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from hdfury import HDFuryError
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
STATE_UNAVAILABLE,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
import homeassistant.helpers.entity_registry as er
|
||||
|
||||
from . import setup_integration
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||
|
||||
|
||||
async def test_switch_entities(
|
||||
@@ -34,15 +43,15 @@ async def test_switch_entities(
|
||||
(
|
||||
"switch.hdfury_vrroom_02_auto_switch_inputs",
|
||||
"set_auto_switch_inputs",
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
),
|
||||
(
|
||||
"switch.hdfury_vrroom_02_auto_switch_inputs",
|
||||
"set_auto_switch_inputs",
|
||||
"turn_off",
|
||||
SERVICE_TURN_OFF,
|
||||
),
|
||||
("switch.hdfury_vrroom_02_oled_display", "set_oled", "turn_on"),
|
||||
("switch.hdfury_vrroom_02_oled_display", "set_oled", "turn_off"),
|
||||
("switch.hdfury_vrroom_02_oled_display", "set_oled", SERVICE_TURN_ON),
|
||||
("switch.hdfury_vrroom_02_oled_display", "set_oled", SERVICE_TURN_OFF),
|
||||
],
|
||||
)
|
||||
async def test_switch_turn_on_off(
|
||||
@@ -58,9 +67,9 @@ async def test_switch_turn_on_off(
|
||||
await setup_integration(hass, mock_config_entry, [Platform.SWITCH])
|
||||
|
||||
await hass.services.async_call(
|
||||
"switch",
|
||||
SWITCH_DOMAIN,
|
||||
service,
|
||||
{"entity_id": entity_id},
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
@@ -70,8 +79,8 @@ async def test_switch_turn_on_off(
|
||||
@pytest.mark.parametrize(
|
||||
("service", "method"),
|
||||
[
|
||||
("turn_on", "set_auto_switch_inputs"),
|
||||
("turn_off", "set_auto_switch_inputs"),
|
||||
(SERVICE_TURN_ON, "set_auto_switch_inputs"),
|
||||
(SERVICE_TURN_OFF, "set_auto_switch_inputs"),
|
||||
],
|
||||
)
|
||||
async def test_switch_turn_error(
|
||||
@@ -92,8 +101,30 @@ async def test_switch_turn_error(
|
||||
match="An error occurred while communicating with HDFury device",
|
||||
):
|
||||
await hass.services.async_call(
|
||||
"switch",
|
||||
SWITCH_DOMAIN,
|
||||
service,
|
||||
{"entity_id": "switch.hdfury_vrroom_02_auto_switch_inputs"},
|
||||
{ATTR_ENTITY_ID: "switch.hdfury_vrroom_02_auto_switch_inputs"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_switch_entities_unavailable_on_error(
|
||||
hass: HomeAssistant,
|
||||
mock_hdfury_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test API error causes entities to become unavailable."""
|
||||
|
||||
await setup_integration(hass, mock_config_entry, [Platform.SWITCH])
|
||||
|
||||
mock_hdfury_client.get_info.side_effect = HDFuryError()
|
||||
|
||||
freezer.tick(timedelta(seconds=61))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
hass.states.get("switch.hdfury_vrroom_02_auto_switch_inputs").state
|
||||
== STATE_UNAVAILABLE
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user