Add additional method of retrieving UUID for LG soundbar configuration (#77856)

This commit is contained in:
Chris McCurdy 2022-09-07 11:43:05 -04:00 committed by GitHub
parent cd5967c4c6
commit 52c8c80f91
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 182 additions and 5 deletions

View file

@ -1,5 +1,5 @@
"""Config flow to configure the LG Soundbar integration.""" """Config flow to configure the LG Soundbar integration."""
from queue import Queue from queue import Full, Queue
import socket import socket
import temescal import temescal
@ -20,18 +20,29 @@ def test_connect(host, port):
uuid_q = Queue(maxsize=1) uuid_q = Queue(maxsize=1)
name_q = Queue(maxsize=1) name_q = Queue(maxsize=1)
def queue_add(attr_q, data):
try:
attr_q.put_nowait(data)
except Full:
pass
def msg_callback(response): def msg_callback(response):
if response["msg"] == "MAC_INFO_DEV" and "s_uuid" in response["data"]: if (
uuid_q.put_nowait(response["data"]["s_uuid"]) response["msg"] in ["MAC_INFO_DEV", "PRODUCT_INFO"]
and "s_uuid" in response["data"]
):
queue_add(uuid_q, response["data"]["s_uuid"])
if ( if (
response["msg"] == "SPK_LIST_VIEW_INFO" response["msg"] == "SPK_LIST_VIEW_INFO"
and "s_user_name" in response["data"] and "s_user_name" in response["data"]
): ):
name_q.put_nowait(response["data"]["s_user_name"]) queue_add(name_q, response["data"]["s_user_name"])
try: try:
connection = temescal.temescal(host, port=port, callback=msg_callback) connection = temescal.temescal(host, port=port, callback=msg_callback)
connection.get_mac_info() connection.get_mac_info()
if uuid_q.empty():
connection.get_product_info()
connection.get_info() connection.get_info()
details = {"name": name_q.get(timeout=10), "uuid": uuid_q.get(timeout=10)} details = {"name": name_q.get(timeout=10), "uuid": uuid_q.get(timeout=10)}
return details return details

View file

@ -1,5 +1,5 @@
"""Test the lg_soundbar config flow.""" """Test the lg_soundbar config flow."""
from unittest.mock import MagicMock, patch from unittest.mock import DEFAULT, MagicMock, Mock, call, patch
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.lg_soundbar.const import DEFAULT_PORT, DOMAIN from homeassistant.components.lg_soundbar.const import DEFAULT_PORT, DOMAIN
@ -43,6 +43,172 @@ async def test_form(hass):
assert len(mock_setup_entry.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1
async def test_form_uuid_missing_from_mac_info(hass):
"""Test we get the form, but uuid is missing from the initial get_mac_info function call."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == "form"
assert result["errors"] == {}
with patch(
"homeassistant.components.lg_soundbar.config_flow.temescal", return_value=Mock()
) as mock_temescal, patch(
"homeassistant.components.lg_soundbar.async_setup_entry", return_value=True
) as mock_setup_entry:
tmock = mock_temescal.temescal
tmock.return_value = Mock()
instance = tmock.return_value
def temescal_side_effect(addr, port, callback):
product_info = {"msg": "PRODUCT_INFO", "data": {"s_uuid": "uuid"}}
instance.get_product_info.side_effect = lambda: callback(product_info)
info = {"msg": "SPK_LIST_VIEW_INFO", "data": {"s_user_name": "name"}}
instance.get_info.side_effect = lambda: callback(info)
return DEFAULT
tmock.side_effect = temescal_side_effect
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_HOST: "1.1.1.1",
},
)
await hass.async_block_till_done()
assert result2["type"] == "create_entry"
assert result2["title"] == "name"
assert result2["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: DEFAULT_PORT,
}
assert len(mock_setup_entry.mock_calls) == 1
async def test_form_uuid_present_in_both_functions_uuid_q_empty(hass):
"""Get the form, uuid present in both get_mac_info and get_product_info calls.
Value from get_mac_info is not added to uuid_q before get_product_info is run.
"""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == "form"
assert result["errors"] == {}
mock_uuid_q = MagicMock()
mock_name_q = MagicMock()
with patch(
"homeassistant.components.lg_soundbar.config_flow.temescal", return_value=Mock()
) as mock_temescal, patch(
"homeassistant.components.lg_soundbar.config_flow.Queue",
return_value=MagicMock(),
) as mock_q, patch(
"homeassistant.components.lg_soundbar.async_setup_entry", return_value=True
) as mock_setup_entry:
mock_q.side_effect = [mock_uuid_q, mock_name_q]
mock_uuid_q.empty.return_value = True
mock_uuid_q.get.return_value = "uuid"
mock_name_q.get.return_value = "name"
tmock = mock_temescal.temescal
tmock.return_value = Mock()
instance = tmock.return_value
def temescal_side_effect(addr, port, callback):
mac_info = {"msg": "MAC_INFO_DEV", "data": {"s_uuid": "uuid"}}
instance.get_mac_info.side_effect = lambda: callback(mac_info)
product_info = {"msg": "PRODUCT_INFO", "data": {"s_uuid": "uuid"}}
instance.get_product_info.side_effect = lambda: callback(product_info)
info = {"msg": "SPK_LIST_VIEW_INFO", "data": {"s_user_name": "name"}}
instance.get_info.side_effect = lambda: callback(info)
return DEFAULT
tmock.side_effect = temescal_side_effect
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_HOST: "1.1.1.1",
},
)
await hass.async_block_till_done()
assert result2["type"] == "create_entry"
assert result2["title"] == "name"
assert result2["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: DEFAULT_PORT,
}
assert len(mock_setup_entry.mock_calls) == 1
mock_uuid_q.empty.assert_called_once()
mock_uuid_q.put_nowait.has_calls([call("uuid"), call("uuid")])
mock_uuid_q.get.assert_called_once()
async def test_form_uuid_present_in_both_functions_uuid_q_not_empty(hass):
"""Get the form, uuid present in both get_mac_info and get_product_info calls.
Value from get_mac_info is added to uuid_q before get_product_info is run.
"""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == "form"
assert result["errors"] == {}
mock_uuid_q = MagicMock()
mock_name_q = MagicMock()
with patch(
"homeassistant.components.lg_soundbar.config_flow.temescal", return_value=Mock()
) as mock_temescal, patch(
"homeassistant.components.lg_soundbar.config_flow.Queue",
return_value=MagicMock(),
) as mock_q, patch(
"homeassistant.components.lg_soundbar.async_setup_entry", return_value=True
) as mock_setup_entry:
mock_q.side_effect = [mock_uuid_q, mock_name_q]
mock_uuid_q.empty.return_value = False
mock_uuid_q.get.return_value = "uuid"
mock_name_q.get.return_value = "name"
tmock = mock_temescal.temescal
tmock.return_value = Mock()
instance = tmock.return_value
def temescal_side_effect(addr, port, callback):
mac_info = {"msg": "MAC_INFO_DEV", "data": {"s_uuid": "uuid"}}
instance.get_mac_info.side_effect = lambda: callback(mac_info)
info = {"msg": "SPK_LIST_VIEW_INFO", "data": {"s_user_name": "name"}}
instance.get_info.side_effect = lambda: callback(info)
return DEFAULT
tmock.side_effect = temescal_side_effect
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_HOST: "1.1.1.1",
},
)
await hass.async_block_till_done()
assert result2["type"] == "create_entry"
assert result2["title"] == "name"
assert result2["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: DEFAULT_PORT,
}
assert len(mock_setup_entry.mock_calls) == 1
mock_uuid_q.empty.assert_called_once()
mock_uuid_q.put_nowait.assert_called_once()
mock_uuid_q.get.assert_called_once()
async def test_form_cannot_connect(hass): async def test_form_cannot_connect(hass):
"""Test we handle cannot connect error.""" """Test we handle cannot connect error."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(