Coverage for tests/tests/test_apis_binding.py: 0%

39 statements  

« prev     ^ index     » next       coverage.py v7.11.3, created at 2026-01-05 21:46 +0100

1#!/usr/bin/env python3 

2"""RAMSES RF - Test the wait_for_binding_request, initiate_binding_process APIs.""" 

3 

4import unittest.mock 

5from types import SimpleNamespace 

6from typing import TypeVar 

7 

8import pytest 

9 

10from ramses_rf.database import MessageIndex 

11from ramses_rf.device.base import Fakeable # initiate_binding_, wait_for_binding_ 

12from ramses_rf.device.heat import DhwSensor, Thermostat # initiate_binding_process 

13from ramses_rf.device.hvac import ( # initiate_binding_process 

14 HvacCarbonDioxideSensor, 

15 HvacDisplayRemote, 

16 HvacRemote, 

17) 

18from ramses_tx.address import Address 

19from ramses_tx.const import Code 

20 

21_FakeableDeviceT = TypeVar("_FakeableDeviceT", bound=Fakeable) 

22 

23 

24# ### TEST SUITE ###################################################################### 

25ADDR_CLASS_LOOKUP: dict[str, type[Fakeable]] = { 

26 "07:123456": DhwSensor, 

27 "03:123456": Thermostat, 

28 # "09:123456": OutSensor, 

29 "31:123456": HvacCarbonDioxideSensor, 

30 "32:123456": HvacDisplayRemote, 

31 "33:123456": HvacRemote, 

32} 

33ADDR_CLASS_MAP = {v: k for k, v in ADDR_CLASS_LOOKUP.items()} 

34 

35CLASS_CODES_MAP: dict[type[Fakeable], Code | tuple[Code, ...]] = { 

36 DhwSensor: Code._1260, 

37 Thermostat: (Code._2309, Code._30C9, Code._0008), 

38 HvacCarbonDioxideSensor: (Code._31E0, Code._1298, Code._2E10), 

39 HvacRemote: (Code._22F1, Code._22F3), 

40} 

41 

42 

43class GatewayStub: 

44 config = SimpleNamespace(**{"disable_discovery": True}) 

45 

46 device_by_id: dict[str, Fakeable] = {} 

47 devices: list[Fakeable] = [] 

48 

49 _include: dict[str] = {} 

50 msg_db = MessageIndex(maintain=False) 

51 

52 def _add_device(self, dev: Fakeable) -> None: 

53 self.device_by_id[dev.id] = dev 

54 self.devices.append(dev) 

55 

56 

57# ### FIXTURES ######################################################################## 

58 

59 

60def pytest_generate_tests(metafunc: pytest.Metafunc) -> None: 

61 def id_fnc(dev_class: type[Fakeable]) -> str: 

62 return dev_class._SLUG 

63 

64 metafunc.parametrize("dev_class", ADDR_CLASS_MAP.keys(), ids=id_fnc) 

65 

66 

67# ### TESTS ########################################################################### 

68 

69 

70async def test_initiate_binding_process(dev_class: type[Fakeable]) -> None: 

71 assert issubclass(dev_class, Fakeable) 

72 

73 gwy = GatewayStub() 

74 dev_addr = Address(ADDR_CLASS_MAP[dev_class]) 

75 

76 with unittest.mock.patch.object( 

77 Fakeable, "_initiate_binding_process", return_value=None 

78 ) as mocked_method: 

79 gwy._include[dev_addr.id] = {} # this shouldn't be needed? a BUG? 

80 

81 dev = dev_class(gwy, dev_addr) 

82 dev._make_fake() 

83 

84 _ = await dev.initiate_binding_process() 

85 

86 if codes := CLASS_CODES_MAP.get(dev_class): 

87 mocked_method.assert_called_once_with(codes) 

88 else: 

89 mocked_method.assert_called_once()