inital commit
This commit is contained in:
@@ -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()
|
||||
Reference in New Issue
Block a user