Add LED BLE integration (#77489)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
parent
af9910d143
commit
8e0c26bf86
18 changed files with 796 additions and 0 deletions
51
tests/components/led_ble/__init__.py
Normal file
51
tests/components/led_ble/__init__.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
"""Tests for the LED BLE Bluetooth integration."""
|
||||
from bleak.backends.device import BLEDevice
|
||||
from bleak.backends.scanner import AdvertisementData
|
||||
|
||||
from homeassistant.components.bluetooth import BluetoothServiceInfoBleak
|
||||
|
||||
LED_BLE_DISCOVERY_INFO = BluetoothServiceInfoBleak(
|
||||
name="Triones:F30200000152C",
|
||||
address="AA:BB:CC:DD:EE:FF",
|
||||
rssi=-60,
|
||||
manufacturer_data={},
|
||||
service_uuids=[],
|
||||
service_data={},
|
||||
source="local",
|
||||
device=BLEDevice(address="AA:BB:CC:DD:EE:FF", name="Triones:F30200000152C"),
|
||||
advertisement=AdvertisementData(),
|
||||
time=0,
|
||||
connectable=True,
|
||||
)
|
||||
|
||||
UNSUPPORTED_LED_BLE_DISCOVERY_INFO = BluetoothServiceInfoBleak(
|
||||
name="LEDnetWFF30200000152C",
|
||||
address="AA:BB:CC:DD:EE:FF",
|
||||
rssi=-60,
|
||||
manufacturer_data={},
|
||||
service_uuids=[],
|
||||
service_data={},
|
||||
source="local",
|
||||
device=BLEDevice(address="AA:BB:CC:DD:EE:FF", name="LEDnetWFF30200000152C"),
|
||||
advertisement=AdvertisementData(),
|
||||
time=0,
|
||||
connectable=True,
|
||||
)
|
||||
|
||||
|
||||
NOT_LED_BLE_DISCOVERY_INFO = BluetoothServiceInfoBleak(
|
||||
name="Not",
|
||||
address="AA:BB:CC:DD:EE:FF",
|
||||
rssi=-60,
|
||||
manufacturer_data={
|
||||
33: b"\x00\x00\xd1\xf0b;\xd8\x1dE\xd6\xba\xeeL\xdd]\xf5\xb2\xe9",
|
||||
21: b"\x061\x00Z\x8f\x93\xb2\xec\x85\x06\x00i\x00\x02\x02Q\xed\x1d\xf0",
|
||||
},
|
||||
service_uuids=[],
|
||||
service_data={},
|
||||
source="local",
|
||||
device=BLEDevice(address="AA:BB:CC:DD:EE:FF", name="Aug"),
|
||||
advertisement=AdvertisementData(),
|
||||
time=0,
|
||||
connectable=True,
|
||||
)
|
8
tests/components/led_ble/conftest.py
Normal file
8
tests/components/led_ble/conftest.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
"""led_ble session fixtures."""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_bluetooth(enable_bluetooth):
|
||||
"""Auto mock bluetooth."""
|
229
tests/components/led_ble/test_config_flow.py
Normal file
229
tests/components/led_ble/test_config_flow.py
Normal file
|
@ -0,0 +1,229 @@
|
|||
"""Test the LED BLE Bluetooth config flow."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from bleak import BleakError
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.led_ble.const import DOMAIN
|
||||
from homeassistant.const import CONF_ADDRESS
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
|
||||
from . import (
|
||||
LED_BLE_DISCOVERY_INFO,
|
||||
NOT_LED_BLE_DISCOVERY_INFO,
|
||||
UNSUPPORTED_LED_BLE_DISCOVERY_INFO,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_user_step_success(hass: HomeAssistant) -> None:
|
||||
"""Test user step success path."""
|
||||
with patch(
|
||||
"homeassistant.components.led_ble.config_flow.async_discovered_service_info",
|
||||
return_value=[NOT_LED_BLE_DISCOVERY_INFO, LED_BLE_DISCOVERY_INFO],
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {}
|
||||
|
||||
with patch("homeassistant.components.led_ble.config_flow.LEDBLE.update",), patch(
|
||||
"homeassistant.components.led_ble.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_ADDRESS: LED_BLE_DISCOVERY_INFO.address,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == LED_BLE_DISCOVERY_INFO.name
|
||||
assert result2["data"] == {
|
||||
CONF_ADDRESS: LED_BLE_DISCOVERY_INFO.address,
|
||||
}
|
||||
assert result2["result"].unique_id == LED_BLE_DISCOVERY_INFO.address
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_user_step_no_devices_found(hass: HomeAssistant) -> None:
|
||||
"""Test user step with no devices found."""
|
||||
with patch(
|
||||
"homeassistant.components.led_ble.config_flow.async_discovered_service_info",
|
||||
return_value=[NOT_LED_BLE_DISCOVERY_INFO],
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.ABORT
|
||||
assert result["reason"] == "no_unconfigured_devices"
|
||||
|
||||
|
||||
async def test_user_step_no_new_devices_found(hass: HomeAssistant) -> None:
|
||||
"""Test user step with only existing devices found."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data={
|
||||
CONF_ADDRESS: LED_BLE_DISCOVERY_INFO.address,
|
||||
},
|
||||
unique_id=LED_BLE_DISCOVERY_INFO.address,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
with patch(
|
||||
"homeassistant.components.led_ble.config_flow.async_discovered_service_info",
|
||||
return_value=[LED_BLE_DISCOVERY_INFO],
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.ABORT
|
||||
assert result["reason"] == "no_unconfigured_devices"
|
||||
|
||||
|
||||
async def test_user_step_cannot_connect(hass: HomeAssistant) -> None:
|
||||
"""Test user step and we cannot connect."""
|
||||
with patch(
|
||||
"homeassistant.components.led_ble.config_flow.async_discovered_service_info",
|
||||
return_value=[LED_BLE_DISCOVERY_INFO],
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {}
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.led_ble.config_flow.LEDBLE.update",
|
||||
side_effect=BleakError,
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_ADDRESS: LED_BLE_DISCOVERY_INFO.address,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] == FlowResultType.FORM
|
||||
assert result2["step_id"] == "user"
|
||||
assert result2["errors"] == {"base": "cannot_connect"}
|
||||
|
||||
with patch("homeassistant.components.led_ble.config_flow.LEDBLE.update",), patch(
|
||||
"homeassistant.components.led_ble.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
result2["flow_id"],
|
||||
{
|
||||
CONF_ADDRESS: LED_BLE_DISCOVERY_INFO.address,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result3["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result3["title"] == LED_BLE_DISCOVERY_INFO.name
|
||||
assert result3["data"] == {
|
||||
CONF_ADDRESS: LED_BLE_DISCOVERY_INFO.address,
|
||||
}
|
||||
assert result3["result"].unique_id == LED_BLE_DISCOVERY_INFO.address
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_user_step_unknown_exception(hass: HomeAssistant) -> None:
|
||||
"""Test user step with an unknown exception."""
|
||||
with patch(
|
||||
"homeassistant.components.led_ble.config_flow.async_discovered_service_info",
|
||||
return_value=[NOT_LED_BLE_DISCOVERY_INFO, LED_BLE_DISCOVERY_INFO],
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {}
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.led_ble.config_flow.LEDBLE.update",
|
||||
side_effect=RuntimeError,
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_ADDRESS: LED_BLE_DISCOVERY_INFO.address,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] == FlowResultType.FORM
|
||||
assert result2["step_id"] == "user"
|
||||
assert result2["errors"] == {"base": "unknown"}
|
||||
|
||||
with patch("homeassistant.components.led_ble.config_flow.LEDBLE.update",), patch(
|
||||
"homeassistant.components.led_ble.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
result2["flow_id"],
|
||||
{
|
||||
CONF_ADDRESS: LED_BLE_DISCOVERY_INFO.address,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result3["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result3["title"] == LED_BLE_DISCOVERY_INFO.name
|
||||
assert result3["data"] == {
|
||||
CONF_ADDRESS: LED_BLE_DISCOVERY_INFO.address,
|
||||
}
|
||||
assert result3["result"].unique_id == LED_BLE_DISCOVERY_INFO.address
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_bluetooth_step_success(hass: HomeAssistant) -> None:
|
||||
"""Test bluetooth step success path."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_BLUETOOTH},
|
||||
data=LED_BLE_DISCOVERY_INFO,
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {}
|
||||
|
||||
with patch("homeassistant.components.led_ble.config_flow.LEDBLE.update",), patch(
|
||||
"homeassistant.components.led_ble.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_ADDRESS: LED_BLE_DISCOVERY_INFO.address,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == LED_BLE_DISCOVERY_INFO.name
|
||||
assert result2["data"] == {
|
||||
CONF_ADDRESS: LED_BLE_DISCOVERY_INFO.address,
|
||||
}
|
||||
assert result2["result"].unique_id == LED_BLE_DISCOVERY_INFO.address
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_bluetooth_unsupported_model(hass: HomeAssistant) -> None:
|
||||
"""Test bluetooth step with an unsupported model path."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_BLUETOOTH},
|
||||
data=UNSUPPORTED_LED_BLE_DISCOVERY_INFO,
|
||||
)
|
||||
assert result["type"] == FlowResultType.ABORT
|
||||
assert result["reason"] == "not_supported"
|
Loading…
Add table
Add a link
Reference in a new issue