1
0

test_ceiling_light.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. from unittest.mock import AsyncMock, MagicMock, patch
  2. import pytest
  3. from bleak.backends.device import BLEDevice
  4. from switchbot import SwitchBotAdvertisement, SwitchbotModel
  5. from switchbot.const.light import ColorMode
  6. from switchbot.devices import ceiling_light
  7. from .test_adv_parser import generate_ble_device
  8. def create_device_for_command_testing(
  9. init_data: dict | None = None, model: SwitchbotModel = SwitchbotModel.CEILING_LIGHT
  10. ):
  11. ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
  12. device = ceiling_light.SwitchbotCeilingLight(ble_device, model=model)
  13. device.update_from_advertisement(make_advertisement_data(ble_device, init_data))
  14. device._send_command = AsyncMock()
  15. device._check_command_result = MagicMock()
  16. device.update = AsyncMock()
  17. return device
  18. def make_advertisement_data(ble_device: BLEDevice, init_data: dict | None = None):
  19. """Set advertisement data with defaults."""
  20. if init_data is None:
  21. init_data = {}
  22. return SwitchBotAdvertisement(
  23. address="aa:bb:cc:dd:ee:ff",
  24. data={
  25. "rawAdvData": b"q\x00",
  26. "data": {
  27. "brightness": 1,
  28. "color_mode": 1,
  29. "cw": 6387,
  30. "isOn": False,
  31. "sequence_number": 10,
  32. }
  33. | init_data,
  34. "isEncrypted": False,
  35. "model": b"q\x00",
  36. "modelFriendlyName": "Ceiling Light",
  37. "modelName": SwitchbotModel.CEILING_LIGHT,
  38. },
  39. device=ble_device,
  40. rssi=-80,
  41. active=True,
  42. )
  43. @pytest.mark.asyncio
  44. async def test_default_info():
  45. """Test default initialization of the ceiling light."""
  46. device = create_device_for_command_testing()
  47. assert device.rgb is None
  48. device._state = {"cw": 3200}
  49. assert device.is_on() is False
  50. assert device.on is False
  51. assert device.color_mode == ColorMode.COLOR_TEMP
  52. assert device.color_modes == {ColorMode.COLOR_TEMP}
  53. assert device.color_temp == 3200
  54. assert device.brightness == 1
  55. assert device.min_temp == 2700
  56. assert device.max_temp == 6500
  57. assert device.get_effect_list is None
  58. @pytest.mark.asyncio
  59. @pytest.mark.parametrize(
  60. ("basic_info", "version_info"), [(True, False), (False, True), (False, False)]
  61. )
  62. async def test_get_basic_info_returns_none(basic_info, version_info):
  63. device = create_device_for_command_testing()
  64. device._send_command = AsyncMock(side_effect=[version_info, basic_info])
  65. device._check_command_result = MagicMock(
  66. side_effect=[bool(version_info), bool(basic_info)]
  67. )
  68. assert await device.get_basic_info() is None
  69. @pytest.mark.asyncio
  70. @pytest.mark.parametrize(
  71. ("info_data", "result"),
  72. [
  73. (
  74. {
  75. "basic_info": b"\x01\x80=\x0f\xa1\x00\x01",
  76. "version_info": b"\x01d\x15\x0f\x00\x00\x00\x00\x00\x00\x00\n\x00",
  77. },
  78. [True, 61, 4001, 0, 2.1],
  79. ),
  80. (
  81. {
  82. "basic_info": b"\x01\x80\x0e\x12B\x00\x01",
  83. "version_info": b"\x01d\x15\x0f\x00\x00\x00\x00\x00\x00\x00\n\x00",
  84. },
  85. [True, 14, 4674, 0, 2.1],
  86. ),
  87. (
  88. {
  89. "basic_info": b"\x01\x00\x0e\x10\x96\x00\x01",
  90. "version_info": b"\x01d\x15\x0f\x00\x00\x00\x00\x00\x00\x00\n\x00",
  91. },
  92. [False, 14, 4246, 0, 2.1],
  93. ),
  94. ],
  95. )
  96. async def test_get_basic_info(info_data, result):
  97. """Test getting basic info from the ceiling light."""
  98. device = create_device_for_command_testing()
  99. device._send_command = AsyncMock(
  100. side_effect=[info_data["version_info"], info_data["basic_info"]]
  101. )
  102. device._check_command_result = MagicMock(side_effect=[True, True])
  103. info = await device.get_basic_info()
  104. assert info["isOn"] is result[0]
  105. assert info["brightness"] == result[1]
  106. assert info["cw"] == result[2]
  107. assert info["color_mode"] == result[3]
  108. assert info["firmware"] == result[4]
  109. @pytest.mark.asyncio
  110. async def test_set_color_temp():
  111. """Test setting color temperature."""
  112. device = create_device_for_command_testing()
  113. await device.set_color_temp(50, 3000)
  114. device._send_command.assert_called_with(
  115. device._set_color_temp_command.format("320BB8")
  116. )
  117. @pytest.mark.asyncio
  118. async def test_turn_on():
  119. """Test turning on the ceiling light."""
  120. device = create_device_for_command_testing({"isOn": True})
  121. await device.turn_on()
  122. device._send_command.assert_called_with(device._turn_on_command)
  123. assert device.is_on() is True
  124. @pytest.mark.asyncio
  125. async def test_turn_off():
  126. """Test turning off the ceiling light."""
  127. device = create_device_for_command_testing({"isOn": False})
  128. await device.turn_off()
  129. device._send_command.assert_called_with(device._turn_off_command)
  130. assert device.is_on() is False
  131. @pytest.mark.asyncio
  132. async def test_set_brightness():
  133. """Test setting brightness."""
  134. device = create_device_for_command_testing()
  135. await device.set_brightness(75)
  136. device._send_command.assert_called_with(
  137. device._set_brightness_command.format("4B0FA1")
  138. )
  139. @pytest.mark.asyncio
  140. @pytest.mark.parametrize(
  141. ("adv_value", "expected_color_mode"),
  142. [
  143. (0, ColorMode.COLOR_TEMP),
  144. (1, ColorMode.COLOR_TEMP),
  145. (4, ColorMode.EFFECT),
  146. (10, ColorMode.OFF),
  147. (None, ColorMode.OFF),
  148. ],
  149. )
  150. async def test_get_color_mode(adv_value, expected_color_mode):
  151. """Test getting color mode."""
  152. device = create_device_for_command_testing()
  153. with patch.object(device, "_get_adv_value", return_value=adv_value):
  154. assert device.color_mode == expected_color_mode