|
3 | 3 | from unittest import mock
|
4 | 4 |
|
5 | 5 | import pytest
|
6 |
| -from zigpy.device import Device |
7 | 6 | from zigpy.quirks.registry import DeviceRegistry
|
8 | 7 | from zigpy.quirks.v2 import CustomDeviceV2
|
9 | 8 | import zigpy.types as t
|
|
12 | 11 |
|
13 | 12 | from tests.common import ClusterListener, wait_for_zigpy_tasks
|
14 | 13 | import zhaquirks
|
| 14 | +from zhaquirks.tuya import TUYA_QUERY_DATA |
15 | 15 | from zhaquirks.tuya.builder import (
|
16 | 16 | TuyaIasContact,
|
17 | 17 | TuyaIasFire,
|
|
24 | 24 | )
|
25 | 25 | from zhaquirks.tuya.mcu import TuyaMCUCluster, TuyaOnOffNM
|
26 | 26 |
|
27 |
| -from .async_mock import sentinel |
28 |
| - |
29 | 27 | zhaquirks.setup()
|
30 | 28 |
|
31 | 29 |
|
32 |
| -@pytest.fixture(name="device_mock") |
33 |
| -def real_device(MockAppController): |
34 |
| - """Device fixture with a single endpoint.""" |
35 |
| - ieee = sentinel.ieee |
36 |
| - nwk = 0x2233 |
37 |
| - device = Device(MockAppController, ieee, nwk) |
38 |
| - |
39 |
| - device.add_endpoint(1) |
40 |
| - device[1].profile_id = 0x0104 |
41 |
| - device[1].device_type = 0x0051 |
42 |
| - device.model = "model" |
43 |
| - device.manufacturer = "manufacturer" |
44 |
| - device[1].add_input_cluster(0x0000) |
45 |
| - device[1].add_input_cluster(0xEF00) |
46 |
| - device[1].add_output_cluster(0x000A) |
47 |
| - device[1].add_output_cluster(0x0019) |
48 |
| - return device |
49 |
| - |
50 |
| - |
51 | 30 | @pytest.mark.parametrize(
|
52 | 31 | "method_name,attr_name,exp_class",
|
53 | 32 | [
|
@@ -191,3 +170,73 @@ class ModTuyaMCUCluster(TuyaMCUCluster):
|
191 | 170 |
|
192 | 171 | assert tuya_listener.attribute_updates[0][0] == 0xEF0A
|
193 | 172 | assert tuya_listener.attribute_updates[0][1] == TestEnum.B
|
| 173 | + |
| 174 | + |
| 175 | +@pytest.mark.parametrize( |
| 176 | + "read_attr_spell,data_query_spell", |
| 177 | + [ |
| 178 | + (True, False), |
| 179 | + (False, True), |
| 180 | + (True, True), |
| 181 | + (False, False), |
| 182 | + ], |
| 183 | +) |
| 184 | +async def test_tuya_spell(device_mock, read_attr_spell, data_query_spell): |
| 185 | + """Test that enchanted Tuya devices have their spells applied during configuration.""" |
| 186 | + registry = DeviceRegistry() |
| 187 | + |
| 188 | + entry = ( |
| 189 | + TuyaQuirkBuilder(device_mock.manufacturer, device_mock.model, registry=registry) |
| 190 | + .tuya_battery(dp_id=1) |
| 191 | + .tuya_onoff(dp_id=3) |
| 192 | + .tuya_enchantment( |
| 193 | + read_attr_spell=read_attr_spell, data_query_spell=data_query_spell |
| 194 | + ) |
| 195 | + .skip_configuration() |
| 196 | + .add_to_registry() |
| 197 | + ) |
| 198 | + |
| 199 | + # coverage for overridden __eq__ method |
| 200 | + assert entry.adds_metadata[0] != entry.adds_metadata[1] |
| 201 | + assert entry.adds_metadata[0] != entry |
| 202 | + |
| 203 | + quirked = registry.get_device(device_mock) |
| 204 | + |
| 205 | + assert isinstance(quirked, CustomDeviceV2) |
| 206 | + assert quirked in registry |
| 207 | + |
| 208 | + request_patch = mock.patch("zigpy.zcl.Cluster.request", mock.AsyncMock()) |
| 209 | + with request_patch as request_mock: |
| 210 | + request_mock.return_value = (foundation.Status.SUCCESS, "done") |
| 211 | + |
| 212 | + # call apply_custom_configuration() on each EnchantedDevice |
| 213 | + # ZHA does this during device configuration normally |
| 214 | + await quirked.apply_custom_configuration() |
| 215 | + |
| 216 | + # the number of Tuya spells that are allowed to be cast, so the sum of enabled Tuya spells |
| 217 | + enabled_tuya_spells_num = ( |
| 218 | + quirked.tuya_spell_read_attributes + quirked.tuya_spell_data_query |
| 219 | + ) |
| 220 | + |
| 221 | + # verify request was called the correct number of times |
| 222 | + assert request_mock.call_count == enabled_tuya_spells_num |
| 223 | + |
| 224 | + # used to check list of mock calls below |
| 225 | + messages = 0 |
| 226 | + |
| 227 | + # check 'attribute read spell' was cast correctly (if enabled) |
| 228 | + if quirked.tuya_spell_read_attributes: |
| 229 | + assert ( |
| 230 | + request_mock.mock_calls[messages][1][1] |
| 231 | + == foundation.GeneralCommand.Read_Attributes |
| 232 | + ) |
| 233 | + assert request_mock.mock_calls[messages][1][3] == [4, 0, 1, 5, 7, 65534] |
| 234 | + messages += 1 |
| 235 | + |
| 236 | + # check 'query data spell' was cast correctly (if enabled) |
| 237 | + if quirked.tuya_spell_data_query: |
| 238 | + assert not request_mock.mock_calls[messages][1][0] |
| 239 | + assert request_mock.mock_calls[messages][1][1] == TUYA_QUERY_DATA |
| 240 | + messages += 1 |
| 241 | + |
| 242 | + request_mock.reset_mock() |
0 commit comments