1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-17 15:44:52 +01:00

Simplify mocking of Tuya device notifications (#165998)

This commit is contained in:
epenet
2026-03-19 13:24:10 +01:00
committed by GitHub
parent 6869369ab2
commit abca80dc13
4 changed files with 33 additions and 38 deletions

View File

@@ -33,14 +33,31 @@ DEVICE_MOCKS = sorted(
class MockDeviceListener(DeviceListener):
"""Mocked DeviceListener for testing."""
async def _async_update_device(
self,
device: CustomerDevice,
updated_status_properties: list[str] | None,
dp_timestamps: dict[str, int] | None,
) -> None:
"""Trigger dispatcher_send for device update and wait for entity tasks to complete."""
self.update_device(device, updated_status_properties, dp_timestamps)
await self.hass.async_block_till_done()
async def async_mock_online(self, device: CustomerDevice) -> None:
"""Mock online event from the manager."""
device.online = True
await self._async_update_device(device, None, None)
async def async_mock_offline(self, device: CustomerDevice) -> None:
"""Mock offline event from the manager."""
device.online = False
await self._async_update_device(device, None, None)
async def async_send_device_update(
self,
hass: HomeAssistant,
device: CustomerDevice,
updated_status_properties: dict[str, Any] | None = None,
dp_timestamps: dict[str, int] | None = None,
*,
online: bool | None = None,
) -> None:
"""Mock update device method."""
property_list: list[str] | None = None
@@ -53,10 +70,7 @@ class MockDeviceListener(DeviceListener):
)
device.status[key] = value
property_list.append(key)
if online is not None:
device.online = online
self.update_device(device, property_list, dp_timestamps)
await hass.async_block_till_done()
await self._async_update_device(device, property_list, dp_timestamps)
async def create_device(hass: HomeAssistant, mock_device_code: str) -> CustomerDevice:
@@ -198,13 +212,13 @@ async def check_selective_state_update(
# Trigger device offline
freezer.tick(10)
await mock_listener.async_send_device_update(hass, mock_device, online=False)
await mock_listener.async_mock_offline(mock_device)
assert hass.states.get(entity_id).state == STATE_UNAVAILABLE
assert hass.states.get(entity_id).last_reported.isoformat() == unavailable_reported
# Trigger device online
freezer.tick(10)
await mock_listener.async_send_device_update(hass, mock_device, online=True)
await mock_listener.async_mock_online(mock_device)
assert hass.states.get(entity_id).state == initial_state
assert hass.states.get(entity_id).last_reported.isoformat() == available_reported
@@ -212,12 +226,12 @@ async def check_selective_state_update(
# in updated properties - state should not change
freezer.tick(10)
mock_device.status[dpcode] = None
await mock_listener.async_send_device_update(hass, mock_device, {})
await mock_listener.async_send_device_update(mock_device, {})
assert hass.states.get(entity_id).state == initial_state
assert hass.states.get(entity_id).last_reported.isoformat() == available_reported
# Trigger device update with provided updates
freezer.tick(30)
await mock_listener.async_send_device_update(hass, mock_device, updates)
await mock_listener.async_send_device_update(mock_device, updates)
assert hass.states.get(entity_id).state == expected_state
assert hass.states.get(entity_id).last_reported.isoformat() == last_reported

View File

@@ -117,9 +117,7 @@ async def test_bitmap(
assert hass.states.get("binary_sensor.dehumidifier_defrost").state == "off"
assert hass.states.get("binary_sensor.dehumidifier_wet").state == "off"
await mock_listener.async_send_device_update(
hass, mock_device, {"fault": fault_value}
)
await mock_listener.async_send_device_update(mock_device, {"fault": fault_value})
assert hass.states.get("binary_sensor.dehumidifier_tank_full").state == tankfull
assert hass.states.get("binary_sensor.dehumidifier_defrost").state == defrost

View File

@@ -35,9 +35,7 @@ async def test_platform_setup_and_discovery(
for mock_device in mock_devices:
# Simulate an initial device update to generate events
await mock_listener.async_send_device_update(
hass, mock_device, mock_device.status
)
await mock_listener.async_send_device_update(mock_device, mock_device.status)
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
@@ -78,7 +76,7 @@ async def test_alarm_message_event(
mock_device.status[dpcode] = value
await mock_listener.async_send_device_update(hass, mock_device, mock_device.status)
await mock_listener.async_send_device_update(mock_device, mock_device.status)
# Verify event was triggered with correct type and decoded URL
state = hass.states.get(entity_id)
@@ -109,35 +107,27 @@ async def test_selective_state_update(
# Device receives a data update - event gets triggered and state gets updated
freezer.tick(10)
await mock_listener.async_send_device_update(
hass, mock_device, {"switch_mode1": "click"}
)
await mock_listener.async_send_device_update(mock_device, {"switch_mode1": "click"})
assert hass.states.get(entity_id).state == "2024-01-01T00:00:10.000+00:00"
# Device goes offline
freezer.tick(10)
mock_device.online = False
await mock_listener.async_send_device_update(hass, mock_device, None)
await mock_listener.async_mock_offline(mock_device)
assert hass.states.get(entity_id).state == STATE_UNAVAILABLE
# Device comes back online - state should go back to last known value,
# not new datetime since no new data update has come in
freezer.tick(10)
mock_device.online = True
await mock_listener.async_send_device_update(hass, mock_device, None)
await mock_listener.async_mock_online(mock_device)
assert hass.states.get(entity_id).state == "2024-01-01T00:00:10.000+00:00"
# Device receives a new data update - event gets triggered and state gets updated
freezer.tick(10)
await mock_listener.async_send_device_update(
hass, mock_device, {"switch_mode1": "click"}
)
await mock_listener.async_send_device_update(mock_device, {"switch_mode1": "click"})
assert hass.states.get(entity_id).state == "2024-01-01T00:00:40.000+00:00"
# Device receives a data update on a different datapoint - event doesn't
# get triggered and state doesn't get updated
freezer.tick(10)
await mock_listener.async_send_device_update(
hass, mock_device, {"switch_mode2": "click"}
)
await mock_listener.async_send_device_update(mock_device, {"switch_mode2": "click"})
assert hass.states.get(entity_id).state == "2024-01-01T00:00:40.000+00:00"

View File

@@ -107,7 +107,6 @@ async def test_delta_report_sensor(
# Send delta update
await mock_listener.async_send_device_update(
hass,
mock_device,
{"add_ele": 200},
{"add_ele": timestamp},
@@ -119,7 +118,6 @@ async def test_delta_report_sensor(
# Send delta update (multiple dpcode)
timestamp += 100
await mock_listener.async_send_device_update(
hass,
mock_device,
{"add_ele": 300, "switch_1": True},
{"add_ele": timestamp, "switch_1": timestamp},
@@ -130,7 +128,6 @@ async def test_delta_report_sensor(
# Send delta update (timestamp not incremented)
await mock_listener.async_send_device_update(
hass,
mock_device,
{"add_ele": 500},
{"add_ele": timestamp}, # same timestamp
@@ -141,7 +138,6 @@ async def test_delta_report_sensor(
# Send delta update (unrelated dpcode)
await mock_listener.async_send_device_update(
hass,
mock_device,
{"switch_1": False},
{"switch_1": timestamp + 100},
@@ -153,7 +149,6 @@ async def test_delta_report_sensor(
# Send delta update
timestamp += 100
await mock_listener.async_send_device_update(
hass,
mock_device,
{"add_ele": 100},
{"add_ele": timestamp},
@@ -166,7 +161,6 @@ async def test_delta_report_sensor(
timestamp += 100
mock_device.status["add_ele"] = None
await mock_listener.async_send_device_update(
hass,
mock_device,
{"add_ele": None},
{"add_ele": timestamp},
@@ -178,7 +172,6 @@ async def test_delta_report_sensor(
# Send delta update (no timestamp - skipped)
mock_device.status["add_ele"] = 200
await mock_listener.async_send_device_update(
hass,
mock_device,
{"add_ele": 200},
None,