Skip to content

Commit cbb45ce

Browse files
committed
feat: add color temperature property to TapoLightEntity and update tests for new structure
1 parent 1e88e08 commit cbb45ce

10 files changed

Lines changed: 116 additions & 61 deletions

File tree

‎custom_components/tapo/light.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ def color_temp(self):
103103
(self.min_color_temp_kelvin, self.max_color_temp_kelvin),
104104
)
105105

106+
@property
107+
def color_temp_kelvin(self):
108+
return self.device.color_temp
109+
106110
@property
107111
def effect(self) -> Optional[str]:
108112
if effect := self.device.effect:

‎tests/conftest.py‎

Lines changed: 85 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,65 @@
11
"""Global fixtures for tapo integration."""
22

3+
from dataclasses import dataclass
34
import json
45
from unittest.mock import AsyncMock, MagicMock, patch
56

7+
from homeassistant.config_entries import ConfigEntry
68
from homeassistant.const import CONF_SCAN_INTERVAL
79
from homeassistant.core import HomeAssistant
810
from homeassistant.helpers import device_registry as dr
911
from homeassistant.setup import async_setup_component
1012
from plugp100.api.light_effect_preset import LightEffectPreset
1113
from plugp100.common.functional.tri import Success, Try
12-
from plugp100.discovery.discovered_device import DiscoveredDevice
13-
from plugp100.new.child.tapostripsocket import TapoStripSocket
14-
from plugp100.new.components.energy_component import EnergyComponent
15-
from plugp100.new.components.light_component import HS, LightComponent
16-
from plugp100.new.components.light_effect_component import LightEffectComponent
17-
from plugp100.new.components.overheat_component import OverheatComponent
18-
from plugp100.new.tapobulb import TapoBulb
19-
from plugp100.new.tapodevice import TapoDevice
20-
from plugp100.new.tapohub import TapoHub
21-
from plugp100.new.tapoplug import TapoPlug
22-
from plugp100.responses.alarm_type_list import AlarmTypeList
23-
from plugp100.responses.components import Components
14+
from plugp100.components.energy import EnergyComponent
15+
from plugp100.components.light_effect import LightEffectComponent
16+
from plugp100.components.overheat import OverheatComponent
17+
from plugp100.devices.base import TapoDevice
18+
from plugp100.devices.bulb import TapoBulb
19+
from plugp100.devices.children.strip_socket import TapoStripSocket
20+
from plugp100.devices.hub import TapoHub
21+
from plugp100.devices.plug import TapoPlug
22+
from plugp100.discovery import DiscoveredDevice
2423
import pytest
2524
from pytest_homeassistant_custom_component.common import MockConfigEntry, load_fixture
2625

2726
from custom_components.tapo.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, DOMAIN
2827

2928
pytest_plugins = ("pytest_homeassistant_custom_component",)
3029

30+
31+
@dataclass
32+
class HS:
33+
hue: float
34+
saturation: float
35+
36+
37+
class LightComponent:
38+
def __init__(self, *_args, **_kwargs) -> None:
39+
pass
40+
41+
42+
class AlarmTypeList(list):
43+
@property
44+
def tones(self):
45+
return list(self)
46+
47+
48+
class Components:
49+
def __init__(self, component_list: list[dict[str, int]]) -> None:
50+
self.component_list = [component["id"] for component in component_list]
51+
self._versions = {
52+
component["id"]: component["ver_code"] for component in component_list
53+
}
54+
55+
def get_version(self, component: str) -> int:
56+
return self._versions[component]
57+
58+
@classmethod
59+
def try_from_json(cls, payload: dict[str, list[dict[str, int]]]) -> "Components":
60+
return cls(payload["component_list"])
61+
62+
3163
IP_ADDRESS = "1.2.3.4"
3264
MAC_ADDRESS = "1a:22:33:b4:c5:66"
3365

@@ -42,30 +74,33 @@ def expected_lingering_tasks() -> bool:
4274
return True
4375

4476

77+
@pytest.fixture(autouse=True)
78+
def disable_background_discovery():
79+
with patch(
80+
"custom_components.tapo.discovery_tapo_devices",
81+
AsyncMock(return_value={}),
82+
):
83+
yield
84+
85+
4586
@pytest.fixture()
4687
def mock_discovery():
4788
discovered_device = mock_discovered_device()
4889
device = _mock_base_device(MagicMock(auto_spec=TapoDevice))
4990
with patch(
50-
"custom_components.tapo.discovery_tapo_devices",
51-
AsyncMock(return_value={device.mac: discovered_device}),
91+
"custom_components.tapo.config_flow.connect_discovered_device",
92+
AsyncMock(return_value=device),
5293
):
53-
with patch.object(
54-
discovered_device,
55-
"get_tapo_device",
56-
side_effect=AsyncMock(return_value=device),
94+
with patch(
95+
"custom_components.tapo.hass_tapo.connect_discovered_device",
96+
AsyncMock(return_value=device),
5797
):
58-
with patch(
59-
"plugp100.discovery.discovered_device.DiscoveredDevice.get_tapo_device",
60-
side_effect=AsyncMock(return_value=device),
61-
):
62-
yield discovered_device
98+
yield discovered_device
6399

64100

65101
async def setup_platform(
66102
hass: HomeAssistant, device: TapoDevice, platforms: list[str]
67103
) -> MockConfigEntry:
68-
hass.config.components.add(DOMAIN)
69104
await device.update()
70105
config_entry = MockConfigEntry(
71106
domain=DOMAIN,
@@ -79,19 +114,35 @@ async def setup_platform(
79114
unique_id=dr.format_mac(device.mac),
80115
)
81116
config_entry.add_to_hass(hass)
117+
118+
original_forward = hass.config_entries.async_forward_entry_setups
119+
120+
async def _forward_only_requested(
121+
entry: ConfigEntry, _platforms: list[str]
122+
) -> bool:
123+
return await original_forward(entry, platforms)
124+
82125
with patch(
83126
"custom_components.tapo.hass_tapo.connect", AsyncMock(return_value=device)
84127
):
85-
with patch.object(hass.config_entries, "async_forward_entry_setup"):
86-
assert await hass.config_entries.async_setup(config_entry.entry_id) is True
87-
assert await async_setup_component(hass, DOMAIN, {}) is True
88-
await hass.async_block_till_done()
89-
90-
for platform in platforms:
91-
assert await hass.config_entries.async_forward_entry_setup(
92-
config_entry, platform
93-
)
94-
await hass.async_block_till_done()
128+
with patch(
129+
"custom_components.tapo.discovery_tapo_devices",
130+
AsyncMock(return_value={}),
131+
):
132+
with patch.object(
133+
hass.config_entries,
134+
"async_forward_entry_setups",
135+
side_effect=_forward_only_requested,
136+
):
137+
assert (
138+
await async_setup_component(
139+
hass,
140+
DOMAIN,
141+
{DOMAIN: {"discovery": False}},
142+
)
143+
is True
144+
)
145+
await hass.async_block_till_done()
95146

96147
return config_entry
97148

‎tests/test_config_flow.py‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
from unittest.mock import AsyncMock, MagicMock, patch
1+
from unittest.mock import AsyncMock, patch
22

33
from homeassistant import config_entries
44
from homeassistant.const import CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_USERNAME
55
from homeassistant.core import HomeAssistant
66
from homeassistant.data_entry_flow import FlowResultType
77
from homeassistant.helpers import device_registry as dr
88
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
9-
from plugp100.discovery.discovered_device import DiscoveredDevice
10-
from plugp100.new.tapodevice import TapoDevice
9+
from plugp100.discovery import DiscoveredDevice
1110
from pytest_homeassistant_custom_component.common import MockConfigEntry
1211

1312
from custom_components.tapo import (
@@ -42,7 +41,6 @@ async def test_discovery_auth(
4241
assert result["type"] == "form"
4342
assert result["step_id"] == STEP_DISCOVERY_REQUIRE_AUTH
4443

45-
mock_discovery.get_tapo_device = AsyncMock(return_value=MagicMock(TapoDevice))
4644
auth_result = await hass.config_entries.flow.async_configure(
4745
result["flow_id"],
4846
user_input={
@@ -92,7 +90,9 @@ async def test_discovery_ip_change_dhcp(
9290
DOMAIN,
9391
context={"source": config_entries.SOURCE_DHCP},
9492
data=DhcpServiceInfo(
95-
ip="127.0.0.2", macaddress=MAC_ADDRESS, hostname="hostname"
93+
ip="127.0.0.2",
94+
macaddress=MAC_ADDRESS.replace(":", ""),
95+
hostname="hostname",
9696
),
9797
)
9898
assert discovery_result["type"] is FlowResultType.ABORT

‎tests/test_light.py‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from homeassistant.components.light import (
66
ATTR_BRIGHTNESS,
77
ATTR_COLOR_MODE,
8-
ATTR_COLOR_TEMP,
98
ATTR_COLOR_TEMP_KELVIN,
109
ATTR_EFFECT,
1110
ATTR_EFFECT_LIST,
@@ -38,7 +37,6 @@ async def test_light_color_state(hass: HomeAssistant, tapo_device: MagicMock):
3837
]
3938
assert state_entity.attributes[ATTR_COLOR_MODE] == ColorMode.COLOR_TEMP
4039
assert state_entity.attributes[ATTR_BRIGHTNESS] == 255 # means 100 on tapo
41-
assert state_entity.attributes[ATTR_COLOR_TEMP] == 154 # is merids, means 6493K
4240
assert state_entity.attributes[ATTR_COLOR_TEMP_KELVIN] == 6493
4341
assert state_entity.attributes[ATTR_MAX_COLOR_TEMP_KELVIN] == 6500
4442
assert state_entity.attributes[ATTR_MIN_COLOR_TEMP_KELVIN] == 2500
@@ -69,7 +67,7 @@ async def test_light_color_service_call(hass: HomeAssistant, tapo_device: MagicM
6967
await hass.services.async_call(
7068
LIGHT_DOMAIN,
7169
SERVICE_TURN_ON,
72-
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP: 300},
70+
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 3333},
7371
blocking=True,
7472
)
7573
tapo_device.set_color_temperature.assert_called_with(3333)
@@ -172,7 +170,7 @@ async def test_color_temp_only_light(hass: HomeAssistant, tapo_device: MagicMock
172170
await hass.services.async_call(
173171
LIGHT_DOMAIN,
174172
SERVICE_TURN_ON,
175-
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 30, ATTR_COLOR_TEMP: 300},
173+
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 30, ATTR_COLOR_TEMP_KELVIN: 3333},
176174
blocking=True,
177175
)
178176
tapo_device.set_color_temperature.assert_called_with(3333)

‎tests/unit/hub/test_binary_sensor.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from plugp100.new.components.battery_component import BatteryComponent
2-
from plugp100.new.components.motion_sensor_component import MotionSensorComponent
3-
from plugp100.new.components.smart_door_component import SmartDoorComponent
4-
from plugp100.new.components.water_leak_component import WaterLeakComponent
1+
from plugp100.components.battery import BatteryComponent
2+
from plugp100.components.motion_sensor import MotionSensorComponent
3+
from plugp100.components.smart_door import SmartDoorComponent
4+
from plugp100.components.water_leak import WaterLeakComponent
55

66
from custom_components.tapo.hub.binary_sensor import COMPONENT_MAPPING
77

‎tests/unit/hub/test_climate.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
from homeassistant.components.climate import ClimateEntityFeature, HVACMode
44
from homeassistant.const import UnitOfTemperature
55
from plugp100.common.functional.tri import Try
6-
from plugp100.new.child.tapohubchildren import KE100Device
7-
from plugp100.responses.hub_childs.ke100_device_state import TRVState
8-
from plugp100.responses.temperature_unit import TemperatureUnit
6+
from plugp100.devices.children.trv import KE100Device
7+
from plugp100.models.hub_children.trv import TRVState
8+
from plugp100.models.temperature import TemperatureUnit
99
import pytest
1010

1111
from custom_components.tapo.coordinators import TapoDataCoordinator

‎tests/unit/hub/test_event.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from unittest.mock import AsyncMock, MagicMock, Mock
44

55
from plugp100.common.functional.tri import Success
6-
from plugp100.new.child.tapohubchildren import TriggerButtonDevice
7-
from plugp100.responses.hub_childs.s200b_device_state import (
6+
from plugp100.devices.children.trigger_button import TriggerButtonDevice
7+
from plugp100.models.hub_children.button import (
88
RotationEvent,
99
SingleClickEvent,
1010
)

‎tests/unit/hub/test_number.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
from homeassistant.components.number import NumberDeviceClass, NumberMode
44
from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfTemperature
55
from plugp100.common.functional.tri import Try
6-
from plugp100.new.child.tapohubchildren import KE100Device, TriggerButtonDevice
7-
from plugp100.responses.temperature_unit import TemperatureUnit
6+
from plugp100.devices.children.trigger_button import TriggerButtonDevice
7+
from plugp100.devices.children.trv import KE100Device
8+
from plugp100.models.temperature import TemperatureUnit
89
import pytest
910

1011
from custom_components.tapo.coordinators import TapoDataCoordinator

‎tests/unit/hub/test_sensor.py‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
from homeassistant.components.sensor import SensorDeviceClass, SensorStateClass
55
from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfTime
66
from plugp100.common.functional.tri import Success
7-
from plugp100.new.child.tapohubchildren import TapoHubChildDevice, TriggerButtonDevice
8-
from plugp100.new.components.battery_component import BatteryComponent
9-
from plugp100.new.components.humidity_component import HumidityComponent
10-
from plugp100.new.components.report_mode_component import ReportModeComponent
11-
from plugp100.new.components.temperature_component import TemperatureComponent
7+
from plugp100.components.battery import BatteryComponent
8+
from plugp100.components.humidity import HumidityComponent
9+
from plugp100.components.report_mode import ReportModeComponent
10+
from plugp100.components.temperature import TemperatureComponent
11+
from plugp100.devices.base import TapoDevice
12+
from plugp100.devices.children.trigger_button import TriggerButtonDevice
1213
import pytest
1314

1415
from custom_components.tapo.coordinators import TapoDataCoordinator
@@ -48,7 +49,7 @@ class TestBatteryLevelSensor:
4849
def init_data(self):
4950
self.coordinator = Mock(TapoDataCoordinator)
5051
self.device = _mock_battery_component(
51-
_mock_hub_child_device(MagicMock(auto_spec=TapoHubChildDevice))
52+
_mock_hub_child_device(MagicMock(auto_spec=TapoDevice))
5253
)
5354
self.battery_sensor = BatteryLevelSensor(
5455
coordinator=self.coordinator, device=self.device

‎tests/unit/hub/test_switch.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from homeassistant.components.switch import SwitchDeviceClass
44
from plugp100.common.functional.tri import Try
5-
from plugp100.new.child.tapohubchildren import KE100Device
5+
from plugp100.devices.children.trv import KE100Device
66
import pytest
77

88
from custom_components.tapo.coordinators import TapoDataCoordinator

0 commit comments

Comments
 (0)