inital commit

This commit is contained in:
Rene Nulsch
2025-11-21 22:38:55 +01:00
commit 4e66d2563b
28 changed files with 2694 additions and 0 deletions
@@ -0,0 +1,162 @@
"""Test the MySmartBike BLE switch."""
from unittest.mock import AsyncMock, patch
import pytest
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
def get_connection_switch_id(hass: HomeAssistant) -> str:
"""Get the connection switch entity ID."""
entity_registry = er.async_get(hass)
for entity in entity_registry.entities.values():
if entity.unique_id.endswith("_connection"):
return entity.entity_id
raise ValueError("Connection switch not found")
async def test_switch_setup(hass: HomeAssistant, init_integration) -> None:
"""Test switch setup."""
entity_id = get_connection_switch_id(hass)
entity_registry = er.async_get(hass)
# Check if the connection switch entity exists
entry = entity_registry.async_get(entity_id)
assert entry
assert entry.unique_id.endswith("_connection")
async def test_switch_initial_state(hass: HomeAssistant, init_integration) -> None:
"""Test switch initial state is on (connected)."""
entity_id = get_connection_switch_id(hass)
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_ON
async def test_switch_turn_off(hass: HomeAssistant, init_integration) -> None:
"""Test turning off the switch disconnects from bike."""
entity_id = get_connection_switch_id(hass)
coordinator = init_integration.runtime_data
# Mock the disconnect method
with patch.object(coordinator, "async_disconnect", new_callable=AsyncMock) as mock_disconnect:
# Turn off the switch
await hass.services.async_call(
SWITCH_DOMAIN,
"turn_off",
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
await hass.async_block_till_done()
# Verify disconnect was called
mock_disconnect.assert_called_once()
async def test_switch_turn_on(hass: HomeAssistant, init_integration) -> None:
"""Test turning on the switch reconnects to bike."""
entity_id = get_connection_switch_id(hass)
coordinator = init_integration.runtime_data
# Mock the reconnect method
with patch.object(coordinator, "async_reconnect", new_callable=AsyncMock) as mock_reconnect:
# Turn on the switch
await hass.services.async_call(
SWITCH_DOMAIN,
"turn_on",
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
await hass.async_block_till_done()
# Verify reconnect was called
mock_reconnect.assert_called_once()
async def test_switch_icon(hass: HomeAssistant, init_integration) -> None:
"""Test switch icon is correct for connected state."""
entity_id = get_connection_switch_id(hass)
state = hass.states.get(entity_id)
assert state is not None
assert state.attributes.get("icon") == "mdi:bluetooth-connect"
async def test_switch_turn_off_error_handling(
hass: HomeAssistant, init_integration
) -> None:
"""Test error handling when turning off switch fails."""
entity_id = get_connection_switch_id(hass)
coordinator = init_integration.runtime_data
# Mock disconnect to raise an exception
with patch.object(
coordinator, "async_disconnect", side_effect=Exception("Disconnect failed")
):
# Turn off should not raise, but log error
await hass.services.async_call(
SWITCH_DOMAIN,
"turn_off",
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
# Entity should still exist
state = hass.states.get(entity_id)
assert state is not None
async def test_switch_turn_on_error_handling(
hass: HomeAssistant, init_integration
) -> None:
"""Test error handling when turning on switch fails."""
entity_id = get_connection_switch_id(hass)
coordinator = init_integration.runtime_data
# Mock reconnect to raise an exception
with patch.object(
coordinator, "async_reconnect", side_effect=Exception("Reconnect failed")
):
# Turn on should not raise, but log error
await hass.services.async_call(
SWITCH_DOMAIN,
"turn_on",
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
# Entity should still exist
state = hass.states.get(entity_id)
assert state is not None
async def test_no_auto_reconnect_when_manually_disconnected(
hass: HomeAssistant, init_integration
) -> None:
"""Test that coordinator doesn't auto-reconnect after manual disconnect."""
entity_id = get_connection_switch_id(hass)
coordinator = init_integration.runtime_data
# Turn off the switch (manual disconnect)
with patch.object(coordinator, "async_disconnect", wraps=coordinator.async_disconnect) as mock_disconnect:
await hass.services.async_call(
SWITCH_DOMAIN,
"turn_off",
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
await hass.async_block_till_done()
mock_disconnect.assert_called_once()
# Verify manual disconnect flag is set
assert coordinator._manual_disconnect is True
# Trigger an update - should NOT attempt to reconnect
with patch.object(coordinator, "_connect", new_callable=AsyncMock) as mock_connect:
await coordinator.async_refresh()
await hass.async_block_till_done()
# _connect should NOT have been called
mock_connect.assert_not_called()