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

1#!/usr/bin/env python3

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

3

4 import unittest.mock

5 from types import SimpleNamespace

6 from typing import TypeVar

7

8 import pytest

9

10 from ramses_rf.database import MessageIndex

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

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

13 from ramses_rf.device.hvac import ( # initiate_binding_process

14 HvacCarbonDioxideSensor,

15 HvacDisplayRemote,

16 HvacRemote,

17)

18 from ramses_tx.address import Address

19 from ramses_tx.const import Code

20

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

22

23

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

25 ADDR_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}

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

34

35 CLASS_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

43 class 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

60 def 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

70 async 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()