mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Fix mysensors mqtt integration setup guard (#49423)
This commit is contained in:
parent
20ead7902a
commit
410f0e3604
@ -14,7 +14,11 @@ from awesomeversion import (
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components.mqtt import valid_publish_topic, valid_subscribe_topic
|
from homeassistant.components.mqtt import (
|
||||||
|
DOMAIN as MQTT_DOMAIN,
|
||||||
|
valid_publish_topic,
|
||||||
|
valid_subscribe_topic,
|
||||||
|
)
|
||||||
from homeassistant.components.mysensors import (
|
from homeassistant.components.mysensors import (
|
||||||
CONF_DEVICE,
|
CONF_DEVICE,
|
||||||
DEFAULT_BAUD_RATE,
|
DEFAULT_BAUD_RATE,
|
||||||
@ -135,18 +139,23 @@ class MySensorsConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
"""Create a config entry from frontend user input."""
|
"""Create a config entry from frontend user input."""
|
||||||
schema = {vol.Required(CONF_GATEWAY_TYPE): vol.In(CONF_GATEWAY_TYPE_ALL)}
|
schema = {vol.Required(CONF_GATEWAY_TYPE): vol.In(CONF_GATEWAY_TYPE_ALL)}
|
||||||
schema = vol.Schema(schema)
|
schema = vol.Schema(schema)
|
||||||
|
errors = {}
|
||||||
|
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
gw_type = self._gw_type = user_input[CONF_GATEWAY_TYPE]
|
gw_type = self._gw_type = user_input[CONF_GATEWAY_TYPE]
|
||||||
input_pass = user_input if CONF_DEVICE in user_input else None
|
input_pass = user_input if CONF_DEVICE in user_input else None
|
||||||
if gw_type == CONF_GATEWAY_TYPE_MQTT:
|
if gw_type == CONF_GATEWAY_TYPE_MQTT:
|
||||||
return await self.async_step_gw_mqtt(input_pass)
|
# Naive check that doesn't consider config entry state.
|
||||||
|
if MQTT_DOMAIN in self.hass.config.components:
|
||||||
|
return await self.async_step_gw_mqtt(input_pass)
|
||||||
|
|
||||||
|
errors["base"] = "mqtt_required"
|
||||||
if gw_type == CONF_GATEWAY_TYPE_TCP:
|
if gw_type == CONF_GATEWAY_TYPE_TCP:
|
||||||
return await self.async_step_gw_tcp(input_pass)
|
return await self.async_step_gw_tcp(input_pass)
|
||||||
if gw_type == CONF_GATEWAY_TYPE_SERIAL:
|
if gw_type == CONF_GATEWAY_TYPE_SERIAL:
|
||||||
return await self.async_step_gw_serial(input_pass)
|
return await self.async_step_gw_serial(input_pass)
|
||||||
|
|
||||||
return self.async_show_form(step_id="user", data_schema=schema)
|
return self.async_show_form(step_id="user", data_schema=schema, errors=errors)
|
||||||
|
|
||||||
async def async_step_gw_serial(self, user_input: dict[str, str] | None = None):
|
async def async_step_gw_serial(self, user_input: dict[str, str] | None = None):
|
||||||
"""Create config entry for a serial gateway."""
|
"""Create config entry for a serial gateway."""
|
||||||
|
@ -29,7 +29,6 @@ CONF_GATEWAY_TYPE_ALL: list[str] = [
|
|||||||
CONF_GATEWAY_TYPE_TCP,
|
CONF_GATEWAY_TYPE_TCP,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
DOMAIN: str = "mysensors"
|
DOMAIN: str = "mysensors"
|
||||||
MYSENSORS_GATEWAY_START_TASK: str = "mysensors_gateway_start_task_{}"
|
MYSENSORS_GATEWAY_START_TASK: str = "mysensors_gateway_start_task_{}"
|
||||||
MYSENSORS_GATEWAYS: str = "mysensors_gateways"
|
MYSENSORS_GATEWAYS: str = "mysensors_gateways"
|
||||||
|
@ -13,6 +13,7 @@ import async_timeout
|
|||||||
from mysensors import BaseAsyncGateway, Message, Sensor, mysensors
|
from mysensors import BaseAsyncGateway, Message, Sensor, mysensors
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant.components.mqtt import DOMAIN as MQTT_DOMAIN
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||||
from homeassistant.core import Event, callback
|
from homeassistant.core import Event, callback
|
||||||
@ -163,9 +164,10 @@ async def _get_gateway(
|
|||||||
persistence_file = hass.config.path(persistence_file)
|
persistence_file = hass.config.path(persistence_file)
|
||||||
|
|
||||||
if device == MQTT_COMPONENT:
|
if device == MQTT_COMPONENT:
|
||||||
# what is the purpose of this?
|
# Make sure the mqtt integration is set up.
|
||||||
# if not await async_setup_component(hass, MQTT_COMPONENT, entry):
|
# Naive check that doesn't consider config entry state.
|
||||||
# return None
|
if MQTT_DOMAIN not in hass.config.components:
|
||||||
|
return None
|
||||||
mqtt = hass.components.mqtt
|
mqtt = hass.components.mqtt
|
||||||
|
|
||||||
def pub_callback(topic, payload, qos, retain):
|
def pub_callback(topic, payload, qos, retain):
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
||||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
||||||
"invalid_subscribe_topic": "Invalid subscribe topic",
|
"invalid_subscribe_topic": "Invalid subscribe topic",
|
||||||
"invalid_publish_topic": "Invalid publish topic",
|
"invalid_publish_topic": "Invalid publish topic",
|
||||||
"duplicate_topic": "Topic already in use",
|
"duplicate_topic": "Topic already in use",
|
||||||
"same_topic": "Subscribe and publish topics are the same",
|
"same_topic": "Subscribe and publish topics are the same",
|
||||||
@ -52,6 +52,7 @@
|
|||||||
"invalid_serial": "Invalid serial port",
|
"invalid_serial": "Invalid serial port",
|
||||||
"invalid_device": "Invalid device",
|
"invalid_device": "Invalid device",
|
||||||
"invalid_version": "Invalid MySensors version",
|
"invalid_version": "Invalid MySensors version",
|
||||||
|
"mqtt_required": "The MQTT integration is not set up",
|
||||||
"not_a_number": "Please enter a number",
|
"not_a_number": "Please enter a number",
|
||||||
"port_out_of_range": "Port number must be at least 1 and at most 65535",
|
"port_out_of_range": "Port number must be at least 1 and at most 65535",
|
||||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||||
@ -60,7 +61,7 @@
|
|||||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
||||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
||||||
"invalid_subscribe_topic": "Invalid subscribe topic",
|
"invalid_subscribe_topic": "Invalid subscribe topic",
|
||||||
"invalid_publish_topic": "Invalid publish topic",
|
"invalid_publish_topic": "Invalid publish topic",
|
||||||
"duplicate_topic": "Topic already in use",
|
"duplicate_topic": "Topic already in use",
|
||||||
"same_topic": "Subscribe and publish topics are the same",
|
"same_topic": "Subscribe and publish topics are the same",
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
"invalid_serial": "Invalid serial port",
|
"invalid_serial": "Invalid serial port",
|
||||||
"invalid_subscribe_topic": "Invalid subscribe topic",
|
"invalid_subscribe_topic": "Invalid subscribe topic",
|
||||||
"invalid_version": "Invalid MySensors version",
|
"invalid_version": "Invalid MySensors version",
|
||||||
|
"mqtt_required": "The MQTT integration is not set up",
|
||||||
"not_a_number": "Please enter a number",
|
"not_a_number": "Please enter a number",
|
||||||
"port_out_of_range": "Port number must be at least 1 and at most 65535",
|
"port_out_of_range": "Port number must be at least 1 and at most 65535",
|
||||||
"same_topic": "Subscribe and publish topics are the same",
|
"same_topic": "Subscribe and publish topics are the same",
|
||||||
|
10
tests/components/mysensors/conftest.py
Normal file
10
tests/components/mysensors/conftest.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
"""Provide common mysensors fixtures."""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.mqtt import DOMAIN as MQTT_DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="mqtt")
|
||||||
|
async def mock_mqtt_fixture(hass):
|
||||||
|
"""Mock the MQTT integration."""
|
||||||
|
hass.config.components.add(MQTT_DOMAIN)
|
@ -50,7 +50,7 @@ async def get_form(
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
async def test_config_mqtt(hass: HomeAssistantType):
|
async def test_config_mqtt(hass: HomeAssistantType, mqtt: None) -> None:
|
||||||
"""Test configuring a mqtt gateway."""
|
"""Test configuring a mqtt gateway."""
|
||||||
step = await get_form(hass, CONF_GATEWAY_TYPE_MQTT, "gw_mqtt")
|
step = await get_form(hass, CONF_GATEWAY_TYPE_MQTT, "gw_mqtt")
|
||||||
flow_id = step["flow_id"]
|
flow_id = step["flow_id"]
|
||||||
@ -88,6 +88,24 @@ async def test_config_mqtt(hass: HomeAssistantType):
|
|||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_missing_mqtt(hass: HomeAssistantType) -> None:
|
||||||
|
"""Test configuring a mqtt gateway without mqtt integration setup."""
|
||||||
|
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
assert result["type"] == "form"
|
||||||
|
assert not result["errors"]
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT},
|
||||||
|
)
|
||||||
|
assert result["step_id"] == "user"
|
||||||
|
assert result["type"] == "form"
|
||||||
|
assert result["errors"] == {"base": "mqtt_required"}
|
||||||
|
|
||||||
|
|
||||||
async def test_config_serial(hass: HomeAssistantType):
|
async def test_config_serial(hass: HomeAssistantType):
|
||||||
"""Test configuring a gateway via serial."""
|
"""Test configuring a gateway via serial."""
|
||||||
step = await get_form(hass, CONF_GATEWAY_TYPE_SERIAL, "gw_serial")
|
step = await get_form(hass, CONF_GATEWAY_TYPE_SERIAL, "gw_serial")
|
||||||
@ -348,12 +366,13 @@ async def test_fail_to_connect(hass: HomeAssistantType):
|
|||||||
)
|
)
|
||||||
async def test_config_invalid(
|
async def test_config_invalid(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
|
mqtt: config_entries.ConfigEntry,
|
||||||
gateway_type: ConfGatewayType,
|
gateway_type: ConfGatewayType,
|
||||||
expected_step_id: str,
|
expected_step_id: str,
|
||||||
user_input: dict[str, any],
|
user_input: dict[str, any],
|
||||||
err_field,
|
err_field,
|
||||||
err_string,
|
err_string,
|
||||||
):
|
) -> None:
|
||||||
"""Perform a test that is expected to generate an error."""
|
"""Perform a test that is expected to generate an error."""
|
||||||
step = await get_form(hass, gateway_type, expected_step_id)
|
step = await get_form(hass, gateway_type, expected_step_id)
|
||||||
flow_id = step["flow_id"]
|
flow_id = step["flow_id"]
|
||||||
@ -421,7 +440,7 @@ async def test_config_invalid(
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_import(hass: HomeAssistantType, user_input: dict):
|
async def test_import(hass: HomeAssistantType, mqtt: None, user_input: dict) -> None:
|
||||||
"""Test importing a gateway."""
|
"""Test importing a gateway."""
|
||||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||||
|
|
||||||
@ -713,10 +732,11 @@ async def test_import(hass: HomeAssistantType, user_input: dict):
|
|||||||
)
|
)
|
||||||
async def test_duplicate(
|
async def test_duplicate(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
|
mqtt: None,
|
||||||
first_input: dict,
|
first_input: dict,
|
||||||
second_input: dict,
|
second_input: dict,
|
||||||
expected_result: tuple[str, str] | None,
|
expected_result: tuple[str, str] | None,
|
||||||
):
|
) -> None:
|
||||||
"""Test duplicate detection."""
|
"""Test duplicate detection."""
|
||||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||||
|
|
||||||
|
@ -227,12 +227,14 @@ from homeassistant.setup import async_setup_component
|
|||||||
)
|
)
|
||||||
async def test_import(
|
async def test_import(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
|
mqtt: None,
|
||||||
config: ConfigType,
|
config: ConfigType,
|
||||||
expected_calls: int,
|
expected_calls: int,
|
||||||
expected_to_succeed: bool,
|
expected_to_succeed: bool,
|
||||||
expected_config_flow_user_input: dict[str, any],
|
expected_config_flow_user_input: dict[str, any],
|
||||||
):
|
) -> None:
|
||||||
"""Test importing a gateway."""
|
"""Test importing a gateway."""
|
||||||
|
await async_setup_component(hass, "persistent_notification", {})
|
||||||
with patch("sys.platform", "win32"), patch(
|
with patch("sys.platform", "win32"), patch(
|
||||||
"homeassistant.components.mysensors.config_flow.try_connect", return_value=True
|
"homeassistant.components.mysensors.config_flow.try_connect", return_value=True
|
||||||
), patch(
|
), patch(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user