diff --git a/homeassistant/components/minecraft_server/__init__.py b/homeassistant/components/minecraft_server/__init__.py index 4e5ab9290f0b00..0e2debda33ec80 100644 --- a/homeassistant/components/minecraft_server/__init__.py +++ b/homeassistant/components/minecraft_server/__init__.py @@ -30,13 +30,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Minecraft Server from a config entry.""" - # Check and create API instance. + # Create API instance. + api = MinecraftServer( + hass, + entry.data.get(CONF_TYPE, MinecraftServerType.JAVA_EDITION), + entry.data[CONF_ADDRESS], + ) + + # Initialize API instance. try: - api = await hass.async_add_executor_job( - MinecraftServer, - entry.data.get(CONF_TYPE, MinecraftServerType.JAVA_EDITION), - entry.data[CONF_ADDRESS], - ) + await api.async_initialize() except MinecraftServerAddressError as error: raise ConfigEntryError( f"Server address in configuration entry is invalid: {error}" @@ -102,9 +105,11 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> config_data = config_entry.data # Migrate config entry. + address = config_data[CONF_HOST] + api = MinecraftServer(hass, MinecraftServerType.JAVA_EDITION, address) + try: - address = config_data[CONF_HOST] - MinecraftServer(MinecraftServerType.JAVA_EDITION, address) + await api.async_initialize() host_only_lookup_success = True except MinecraftServerAddressError as error: host_only_lookup_success = False @@ -114,9 +119,11 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> ) if not host_only_lookup_success: + address = f"{config_data[CONF_HOST]}:{config_data[CONF_PORT]}" + api = MinecraftServer(hass, MinecraftServerType.JAVA_EDITION, address) + try: - address = f"{config_data[CONF_HOST]}:{config_data[CONF_PORT]}" - MinecraftServer(MinecraftServerType.JAVA_EDITION, address) + await api.async_initialize() except MinecraftServerAddressError as error: _LOGGER.exception( "Can't migrate configuration entry due to error while parsing server address, try again later: %s", diff --git a/homeassistant/components/minecraft_server/api.py b/homeassistant/components/minecraft_server/api.py index 4ab7865f369a0d..fc872d37bdef33 100644 --- a/homeassistant/components/minecraft_server/api.py +++ b/homeassistant/components/minecraft_server/api.py @@ -9,6 +9,8 @@ from mcstatus import BedrockServer, JavaServer from mcstatus.status_response import BedrockStatusResponse, JavaStatusResponse +from homeassistant.core import HomeAssistant + _LOGGER = logging.getLogger(__name__) LOOKUP_TIMEOUT: float = 10 @@ -52,35 +54,51 @@ class MinecraftServerConnectionError(Exception): """Raised when no data can be fechted from the server.""" +class MinecraftServerNotInitializedError(Exception): + """Raised when APIs are used although server instance is not initialized yet.""" + + class MinecraftServer: """Minecraft Server wrapper class for 3rd party library mcstatus.""" - _server: BedrockServer | JavaServer + _server: BedrockServer | JavaServer | None - def __init__(self, server_type: MinecraftServerType, address: str) -> None: + def __init__( + self, hass: HomeAssistant, server_type: MinecraftServerType, address: str + ) -> None: """Initialize server instance.""" + self._server = None + self._hass = hass + self._server_type = server_type + self._address = address + + async def async_initialize(self) -> None: + """Perform async initialization of server instance.""" try: - if server_type == MinecraftServerType.JAVA_EDITION: - self._server = JavaServer.lookup(address, timeout=LOOKUP_TIMEOUT) + if self._server_type == MinecraftServerType.JAVA_EDITION: + self._server = await JavaServer.async_lookup(self._address) else: - self._server = BedrockServer.lookup(address, timeout=LOOKUP_TIMEOUT) + self._server = await self._hass.async_add_executor_job( + BedrockServer.lookup, self._address + ) except (ValueError, LifetimeTimeout) as error: raise MinecraftServerAddressError( - f"Lookup of '{address}' failed: {self._get_error_message(error)}" + f"Lookup of '{self._address}' failed: {self._get_error_message(error)}" ) from error self._server.timeout = DATA_UPDATE_TIMEOUT - self._address = address _LOGGER.debug( - "%s server instance created with address '%s'", server_type, address + "%s server instance created with address '%s'", + self._server_type, + self._address, ) async def async_is_online(self) -> bool: """Check if the server is online, supporting both Java and Bedrock Edition servers.""" try: await self.async_get_data() - except MinecraftServerConnectionError: + except (MinecraftServerConnectionError, MinecraftServerNotInitializedError): return False return True @@ -89,6 +107,9 @@ async def async_get_data(self) -> MinecraftServerData: """Get updated data from the server, supporting both Java and Bedrock Edition servers.""" status_response: BedrockStatusResponse | JavaStatusResponse + if self._server is None: + raise MinecraftServerNotInitializedError() + try: status_response = await self._server.async_status(tries=DATA_UPDATE_RETRIES) except OSError as error: diff --git a/homeassistant/components/minecraft_server/config_flow.py b/homeassistant/components/minecraft_server/config_flow.py index f064a4ac1ef4bf..045133421fba89 100644 --- a/homeassistant/components/minecraft_server/config_flow.py +++ b/homeassistant/components/minecraft_server/config_flow.py @@ -35,10 +35,10 @@ async def async_step_user(self, user_input=None) -> FlowResult: # Some Bedrock Edition servers mimic a Java Edition server, therefore check for a Bedrock Edition server first. for server_type in MinecraftServerType: + api = MinecraftServer(self.hass, server_type, address) + try: - api = await self.hass.async_add_executor_job( - MinecraftServer, server_type, address - ) + await api.async_initialize() except MinecraftServerAddressError: pass else: diff --git a/homeassistant/components/minecraft_server/coordinator.py b/homeassistant/components/minecraft_server/coordinator.py index f7a60318c64f41..e498375cafc17a 100644 --- a/homeassistant/components/minecraft_server/coordinator.py +++ b/homeassistant/components/minecraft_server/coordinator.py @@ -7,7 +7,12 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed -from .api import MinecraftServer, MinecraftServerConnectionError, MinecraftServerData +from .api import ( + MinecraftServer, + MinecraftServerConnectionError, + MinecraftServerData, + MinecraftServerNotInitializedError, +) SCAN_INTERVAL = timedelta(seconds=60) @@ -32,5 +37,8 @@ async def _async_update_data(self) -> MinecraftServerData: """Get updated data from the server.""" try: return await self._api.async_get_data() - except MinecraftServerConnectionError as error: + except ( + MinecraftServerConnectionError, + MinecraftServerNotInitializedError, + ) as error: raise UpdateFailed(error) from error diff --git a/tests/components/minecraft_server/snapshots/test_binary_sensor.ambr b/tests/components/minecraft_server/snapshots/test_binary_sensor.ambr index ef03e36343b930..2a62fea7f357dc 100644 --- a/tests/components/minecraft_server/snapshots/test_binary_sensor.ambr +++ b/tests/components/minecraft_server/snapshots/test_binary_sensor.ambr @@ -1,5 +1,5 @@ # serializer version: 1 -# name: test_binary_sensor[bedrock_mock_config_entry-BedrockServer-status_response1] +# name: test_binary_sensor[bedrock_mock_config_entry-BedrockServer-lookup-status_response1] StateSnapshot({ 'attributes': ReadOnlyDict({ 'device_class': 'connectivity', @@ -13,7 +13,7 @@ 'state': 'on', }) # --- -# name: test_binary_sensor[java_mock_config_entry-JavaServer-status_response0] +# name: test_binary_sensor[java_mock_config_entry-JavaServer-async_lookup-status_response0] StateSnapshot({ 'attributes': ReadOnlyDict({ 'device_class': 'connectivity', @@ -27,7 +27,7 @@ 'state': 'on', }) # --- -# name: test_binary_sensor_update[bedrock_mock_config_entry-BedrockServer-status_response1] +# name: test_binary_sensor_update[bedrock_mock_config_entry-BedrockServer-lookup-status_response1] StateSnapshot({ 'attributes': ReadOnlyDict({ 'device_class': 'connectivity', @@ -41,7 +41,7 @@ 'state': 'on', }) # --- -# name: test_binary_sensor_update[java_mock_config_entry-JavaServer-status_response0] +# name: test_binary_sensor_update[java_mock_config_entry-JavaServer-async_lookup-status_response0] StateSnapshot({ 'attributes': ReadOnlyDict({ 'device_class': 'connectivity', diff --git a/tests/components/minecraft_server/snapshots/test_sensor.ambr b/tests/components/minecraft_server/snapshots/test_sensor.ambr index fed0ae93c6669b..b0f77f27b80b0c 100644 --- a/tests/components/minecraft_server/snapshots/test_sensor.ambr +++ b/tests/components/minecraft_server/snapshots/test_sensor.ambr @@ -1,5 +1,5 @@ # serializer version: 1 -# name: test_sensor[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1] +# name: test_sensor[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1] StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Latency', @@ -13,7 +13,7 @@ 'state': '5', }) # --- -# name: test_sensor[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].1 +# name: test_sensor[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].1 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Players online', @@ -27,7 +27,7 @@ 'state': '3', }) # --- -# name: test_sensor[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].2 +# name: test_sensor[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].2 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Players max', @@ -41,7 +41,7 @@ 'state': '10', }) # --- -# name: test_sensor[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].3 +# name: test_sensor[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].3 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server World message', @@ -54,7 +54,7 @@ 'state': 'Dummy MOTD', }) # --- -# name: test_sensor[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].4 +# name: test_sensor[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].4 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Version', @@ -67,7 +67,7 @@ 'state': 'Dummy Version', }) # --- -# name: test_sensor[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].5 +# name: test_sensor[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].5 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Protocol version', @@ -80,7 +80,7 @@ 'state': '123', }) # --- -# name: test_sensor[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].6 +# name: test_sensor[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].6 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Map name', @@ -93,7 +93,7 @@ 'state': 'Dummy Map Name', }) # --- -# name: test_sensor[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].7 +# name: test_sensor[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].7 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Game mode', @@ -106,7 +106,7 @@ 'state': 'Dummy Game Mode', }) # --- -# name: test_sensor[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].8 +# name: test_sensor[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].8 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Edition', @@ -119,7 +119,7 @@ 'state': 'MCPE', }) # --- -# name: test_sensor[java_mock_config_entry-JavaServer-status_response0-entity_ids0] +# name: test_sensor[java_mock_config_entry-JavaServer-async_lookup-status_response0-entity_ids0] StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Latency', @@ -133,7 +133,7 @@ 'state': '5', }) # --- -# name: test_sensor[java_mock_config_entry-JavaServer-status_response0-entity_ids0].1 +# name: test_sensor[java_mock_config_entry-JavaServer-async_lookup-status_response0-entity_ids0].1 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Players online', @@ -152,7 +152,7 @@ 'state': '3', }) # --- -# name: test_sensor[java_mock_config_entry-JavaServer-status_response0-entity_ids0].2 +# name: test_sensor[java_mock_config_entry-JavaServer-async_lookup-status_response0-entity_ids0].2 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Players max', @@ -166,7 +166,7 @@ 'state': '10', }) # --- -# name: test_sensor[java_mock_config_entry-JavaServer-status_response0-entity_ids0].3 +# name: test_sensor[java_mock_config_entry-JavaServer-async_lookup-status_response0-entity_ids0].3 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server World message', @@ -179,7 +179,7 @@ 'state': 'Dummy MOTD', }) # --- -# name: test_sensor[java_mock_config_entry-JavaServer-status_response0-entity_ids0].4 +# name: test_sensor[java_mock_config_entry-JavaServer-async_lookup-status_response0-entity_ids0].4 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Version', @@ -192,7 +192,7 @@ 'state': 'Dummy Version', }) # --- -# name: test_sensor[java_mock_config_entry-JavaServer-status_response0-entity_ids0].5 +# name: test_sensor[java_mock_config_entry-JavaServer-async_lookup-status_response0-entity_ids0].5 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Protocol version', @@ -205,7 +205,7 @@ 'state': '123', }) # --- -# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1] +# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1] StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Latency', @@ -219,7 +219,7 @@ 'state': '5', }) # --- -# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].1 +# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].1 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Players online', @@ -233,7 +233,7 @@ 'state': '3', }) # --- -# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].2 +# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].2 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Players max', @@ -247,7 +247,7 @@ 'state': '10', }) # --- -# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].3 +# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].3 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server World message', @@ -260,7 +260,7 @@ 'state': 'Dummy MOTD', }) # --- -# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].4 +# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].4 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Version', @@ -273,7 +273,7 @@ 'state': 'Dummy Version', }) # --- -# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].5 +# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].5 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Protocol version', @@ -286,7 +286,7 @@ 'state': '123', }) # --- -# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].6 +# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].6 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Map name', @@ -299,7 +299,7 @@ 'state': 'Dummy Map Name', }) # --- -# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].7 +# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].7 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Game mode', @@ -312,7 +312,7 @@ 'state': 'Dummy Game Mode', }) # --- -# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-status_response1-entity_ids1].8 +# name: test_sensor_update[bedrock_mock_config_entry-BedrockServer-lookup-status_response1-entity_ids1].8 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Edition', @@ -325,7 +325,7 @@ 'state': 'MCPE', }) # --- -# name: test_sensor_update[java_mock_config_entry-JavaServer-status_response0-entity_ids0] +# name: test_sensor_update[java_mock_config_entry-JavaServer-async_lookup-status_response0-entity_ids0] StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Latency', @@ -339,7 +339,7 @@ 'state': '5', }) # --- -# name: test_sensor_update[java_mock_config_entry-JavaServer-status_response0-entity_ids0].1 +# name: test_sensor_update[java_mock_config_entry-JavaServer-async_lookup-status_response0-entity_ids0].1 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Players online', @@ -358,7 +358,7 @@ 'state': '3', }) # --- -# name: test_sensor_update[java_mock_config_entry-JavaServer-status_response0-entity_ids0].2 +# name: test_sensor_update[java_mock_config_entry-JavaServer-async_lookup-status_response0-entity_ids0].2 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Players max', @@ -372,7 +372,7 @@ 'state': '10', }) # --- -# name: test_sensor_update[java_mock_config_entry-JavaServer-status_response0-entity_ids0].3 +# name: test_sensor_update[java_mock_config_entry-JavaServer-async_lookup-status_response0-entity_ids0].3 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server World message', @@ -385,7 +385,7 @@ 'state': 'Dummy MOTD', }) # --- -# name: test_sensor_update[java_mock_config_entry-JavaServer-status_response0-entity_ids0].4 +# name: test_sensor_update[java_mock_config_entry-JavaServer-async_lookup-status_response0-entity_ids0].4 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Version', @@ -398,7 +398,7 @@ 'state': 'Dummy Version', }) # --- -# name: test_sensor_update[java_mock_config_entry-JavaServer-status_response0-entity_ids0].5 +# name: test_sensor_update[java_mock_config_entry-JavaServer-async_lookup-status_response0-entity_ids0].5 StateSnapshot({ 'attributes': ReadOnlyDict({ 'friendly_name': 'Minecraft Server Protocol version', diff --git a/tests/components/minecraft_server/test_binary_sensor.py b/tests/components/minecraft_server/test_binary_sensor.py index 9fae35b113df89..4db564bc143dc3 100644 --- a/tests/components/minecraft_server/test_binary_sensor.py +++ b/tests/components/minecraft_server/test_binary_sensor.py @@ -22,16 +22,27 @@ @pytest.mark.parametrize( - ("mock_config_entry", "server", "status_response"), + ("mock_config_entry", "server", "lookup_function_name", "status_response"), [ - ("java_mock_config_entry", JavaServer, TEST_JAVA_STATUS_RESPONSE), - ("bedrock_mock_config_entry", BedrockServer, TEST_BEDROCK_STATUS_RESPONSE), + ( + "java_mock_config_entry", + JavaServer, + "async_lookup", + TEST_JAVA_STATUS_RESPONSE, + ), + ( + "bedrock_mock_config_entry", + BedrockServer, + "lookup", + TEST_BEDROCK_STATUS_RESPONSE, + ), ], ) async def test_binary_sensor( hass: HomeAssistant, mock_config_entry: str, server: JavaServer | BedrockServer, + lookup_function_name: str, status_response: JavaStatusResponse | BedrockStatusResponse, request: pytest.FixtureRequest, snapshot: SnapshotAssertion, @@ -41,7 +52,7 @@ async def test_binary_sensor( mock_config_entry.add_to_hass(hass) with patch( - f"homeassistant.components.minecraft_server.api.{server.__name__}.lookup", + f"homeassistant.components.minecraft_server.api.{server.__name__}.{lookup_function_name}", return_value=server(host=TEST_HOST, port=TEST_PORT), ), patch( f"homeassistant.components.minecraft_server.api.{server.__name__}.async_status", @@ -53,16 +64,27 @@ async def test_binary_sensor( @pytest.mark.parametrize( - ("mock_config_entry", "server", "status_response"), + ("mock_config_entry", "server", "lookup_function_name", "status_response"), [ - ("java_mock_config_entry", JavaServer, TEST_JAVA_STATUS_RESPONSE), - ("bedrock_mock_config_entry", BedrockServer, TEST_BEDROCK_STATUS_RESPONSE), + ( + "java_mock_config_entry", + JavaServer, + "async_lookup", + TEST_JAVA_STATUS_RESPONSE, + ), + ( + "bedrock_mock_config_entry", + BedrockServer, + "lookup", + TEST_BEDROCK_STATUS_RESPONSE, + ), ], ) async def test_binary_sensor_update( hass: HomeAssistant, mock_config_entry: str, server: JavaServer | BedrockServer, + lookup_function_name: str, status_response: JavaStatusResponse | BedrockStatusResponse, request: pytest.FixtureRequest, snapshot: SnapshotAssertion, @@ -73,7 +95,7 @@ async def test_binary_sensor_update( mock_config_entry.add_to_hass(hass) with patch( - f"homeassistant.components.minecraft_server.api.{server.__name__}.lookup", + f"homeassistant.components.minecraft_server.api.{server.__name__}.{lookup_function_name}", return_value=server(host=TEST_HOST, port=TEST_PORT), ), patch( f"homeassistant.components.minecraft_server.api.{server.__name__}.async_status", @@ -88,16 +110,27 @@ async def test_binary_sensor_update( @pytest.mark.parametrize( - ("mock_config_entry", "server", "status_response"), + ("mock_config_entry", "server", "lookup_function_name", "status_response"), [ - ("java_mock_config_entry", JavaServer, TEST_JAVA_STATUS_RESPONSE), - ("bedrock_mock_config_entry", BedrockServer, TEST_BEDROCK_STATUS_RESPONSE), + ( + "java_mock_config_entry", + JavaServer, + "async_lookup", + TEST_JAVA_STATUS_RESPONSE, + ), + ( + "bedrock_mock_config_entry", + BedrockServer, + "lookup", + TEST_BEDROCK_STATUS_RESPONSE, + ), ], ) async def test_binary_sensor_update_failure( hass: HomeAssistant, mock_config_entry: str, server: JavaServer | BedrockServer, + lookup_function_name: str, status_response: JavaStatusResponse | BedrockStatusResponse, request: pytest.FixtureRequest, freezer: FrozenDateTimeFactory, @@ -107,7 +140,7 @@ async def test_binary_sensor_update_failure( mock_config_entry.add_to_hass(hass) with patch( - f"homeassistant.components.minecraft_server.api.{server.__name__}.lookup", + f"homeassistant.components.minecraft_server.api.{server.__name__}.{lookup_function_name}", return_value=server(host=TEST_HOST, port=TEST_PORT), ), patch( f"homeassistant.components.minecraft_server.api.{server.__name__}.async_status", diff --git a/tests/components/minecraft_server/test_config_flow.py b/tests/components/minecraft_server/test_config_flow.py index 785905492c1088..2a0208f2251099 100644 --- a/tests/components/minecraft_server/test_config_flow.py +++ b/tests/components/minecraft_server/test_config_flow.py @@ -41,7 +41,7 @@ async def test_address_validation_failure(hass: HomeAssistant) -> None: "homeassistant.components.minecraft_server.api.BedrockServer.lookup", side_effect=ValueError, ), patch( - "homeassistant.components.minecraft_server.api.JavaServer.lookup", + "homeassistant.components.minecraft_server.api.JavaServer.async_lookup", side_effect=ValueError, ): result = await hass.config_entries.flow.async_init( @@ -58,7 +58,7 @@ async def test_java_connection_failure(hass: HomeAssistant) -> None: "homeassistant.components.minecraft_server.api.BedrockServer.lookup", side_effect=ValueError, ), patch( - "homeassistant.components.minecraft_server.api.JavaServer.lookup", + "homeassistant.components.minecraft_server.api.JavaServer.async_lookup", return_value=JavaServer(host=TEST_HOST, port=TEST_PORT), ), patch( "homeassistant.components.minecraft_server.api.JavaServer.async_status", @@ -95,7 +95,7 @@ async def test_java_connection(hass: HomeAssistant) -> None: "homeassistant.components.minecraft_server.api.BedrockServer.lookup", side_effect=ValueError, ), patch( - "homeassistant.components.minecraft_server.api.JavaServer.lookup", + "homeassistant.components.minecraft_server.api.JavaServer.async_lookup", return_value=JavaServer(host=TEST_HOST, port=TEST_PORT), ), patch( "homeassistant.components.minecraft_server.api.JavaServer.async_status", @@ -138,7 +138,7 @@ async def test_recovery(hass: HomeAssistant) -> None: "homeassistant.components.minecraft_server.api.BedrockServer.lookup", side_effect=ValueError, ), patch( - "homeassistant.components.minecraft_server.api.JavaServer.lookup", + "homeassistant.components.minecraft_server.api.JavaServer.async_lookup", side_effect=ValueError, ): result = await hass.config_entries.flow.async_init( diff --git a/tests/components/minecraft_server/test_diagnostics.py b/tests/components/minecraft_server/test_diagnostics.py index 6979325fa0c8d3..80b5c91c1fb4a1 100644 --- a/tests/components/minecraft_server/test_diagnostics.py +++ b/tests/components/minecraft_server/test_diagnostics.py @@ -42,9 +42,14 @@ async def test_config_entry_diagnostics( mock_config_entry = request.getfixturevalue(mock_config_entry) mock_config_entry.add_to_hass(hass) + if server.__name__ == "JavaServer": + lookup_function_name = "async_lookup" + else: + lookup_function_name = "lookup" + # Setup mock entry. with patch( - f"mcstatus.server.{server.__name__}.lookup", + f"mcstatus.server.{server.__name__}.{lookup_function_name}", return_value=server(host=TEST_HOST, port=TEST_PORT), ), patch( f"mcstatus.server.{server.__name__}.async_status", diff --git a/tests/components/minecraft_server/test_init.py b/tests/components/minecraft_server/test_init.py index 018fdac542e9a5..5b0d9509d692df 100644 --- a/tests/components/minecraft_server/test_init.py +++ b/tests/components/minecraft_server/test_init.py @@ -122,7 +122,7 @@ async def test_setup_and_unload_entry( java_mock_config_entry.add_to_hass(hass) with patch( - "homeassistant.components.minecraft_server.api.JavaServer.lookup", + "homeassistant.components.minecraft_server.api.JavaServer.async_lookup", return_value=JavaServer(host=TEST_HOST, port=TEST_PORT), ), patch( "homeassistant.components.minecraft_server.api.JavaServer.async_status", @@ -138,14 +138,14 @@ async def test_setup_and_unload_entry( assert java_mock_config_entry.state == ConfigEntryState.NOT_LOADED -async def test_setup_entry_failure( +async def test_setup_entry_lookup_failure( hass: HomeAssistant, java_mock_config_entry: MockConfigEntry ) -> None: - """Test failed entry setup.""" + """Test lookup failure in entry setup.""" java_mock_config_entry.add_to_hass(hass) with patch( - "homeassistant.components.minecraft_server.api.JavaServer.lookup", + "homeassistant.components.minecraft_server.api.JavaServer.async_lookup", side_effect=ValueError, ): assert not await hass.config_entries.async_setup( @@ -156,6 +156,24 @@ async def test_setup_entry_failure( assert java_mock_config_entry.state == ConfigEntryState.SETUP_ERROR +async def test_setup_entry_init_failure( + hass: HomeAssistant, java_mock_config_entry: MockConfigEntry +) -> None: + """Test init failure in entry setup.""" + java_mock_config_entry.add_to_hass(hass) + + with patch( + "homeassistant.components.minecraft_server.api.MinecraftServer.async_initialize", + side_effect=None, + ): + assert not await hass.config_entries.async_setup( + java_mock_config_entry.entry_id + ) + + await hass.async_block_till_done() + assert java_mock_config_entry.state == ConfigEntryState.SETUP_RETRY + + async def test_setup_entry_not_ready( hass: HomeAssistant, java_mock_config_entry: MockConfigEntry ) -> None: @@ -163,7 +181,7 @@ async def test_setup_entry_not_ready( java_mock_config_entry.add_to_hass(hass) with patch( - "homeassistant.components.minecraft_server.api.JavaServer.lookup", + "homeassistant.components.minecraft_server.api.JavaServer.async_lookup", return_value=JavaServer(host=TEST_HOST, port=TEST_PORT), ), patch( "homeassistant.components.minecraft_server.api.JavaServer.async_status", @@ -196,7 +214,7 @@ async def test_entry_migration( # Trigger migration. with patch( - "homeassistant.components.minecraft_server.api.JavaServer.lookup", + "homeassistant.components.minecraft_server.api.JavaServer.async_lookup", side_effect=[ ValueError, # async_migrate_entry JavaServer(host=TEST_HOST, port=TEST_PORT), # async_migrate_entry @@ -258,7 +276,7 @@ async def test_entry_migration_host_only( # Trigger migration. with patch( - "homeassistant.components.minecraft_server.api.JavaServer.lookup", + "homeassistant.components.minecraft_server.api.JavaServer.async_lookup", return_value=JavaServer(host=TEST_HOST, port=TEST_PORT), ), patch( "homeassistant.components.minecraft_server.api.JavaServer.async_status", @@ -293,7 +311,7 @@ async def test_entry_migration_v3_failure( # Trigger migration. with patch( - "homeassistant.components.minecraft_server.api.JavaServer.lookup", + "homeassistant.components.minecraft_server.api.JavaServer.async_lookup", side_effect=[ ValueError, # async_migrate_entry ValueError, # async_migrate_entry diff --git a/tests/components/minecraft_server/test_sensor.py b/tests/components/minecraft_server/test_sensor.py index 006c735e034ef7..7d599669d71e27 100644 --- a/tests/components/minecraft_server/test_sensor.py +++ b/tests/components/minecraft_server/test_sensor.py @@ -55,17 +55,25 @@ @pytest.mark.usefixtures("entity_registry_enabled_by_default") @pytest.mark.parametrize( - ("mock_config_entry", "server", "status_response", "entity_ids"), + ( + "mock_config_entry", + "server", + "lookup_function_name", + "status_response", + "entity_ids", + ), [ ( "java_mock_config_entry", JavaServer, + "async_lookup", TEST_JAVA_STATUS_RESPONSE, JAVA_SENSOR_ENTITIES, ), ( "bedrock_mock_config_entry", BedrockServer, + "lookup", TEST_BEDROCK_STATUS_RESPONSE, BEDROCK_SENSOR_ENTITIES, ), @@ -75,6 +83,7 @@ async def test_sensor( hass: HomeAssistant, mock_config_entry: str, server: JavaServer | BedrockServer, + lookup_function_name: str, status_response: JavaStatusResponse | BedrockStatusResponse, entity_ids: list[str], request: pytest.FixtureRequest, @@ -85,7 +94,7 @@ async def test_sensor( mock_config_entry.add_to_hass(hass) with patch( - f"homeassistant.components.minecraft_server.api.{server.__name__}.lookup", + f"homeassistant.components.minecraft_server.api.{server.__name__}.{lookup_function_name}", return_value=server(host=TEST_HOST, port=TEST_PORT), ), patch( f"homeassistant.components.minecraft_server.api.{server.__name__}.async_status", @@ -98,17 +107,25 @@ async def test_sensor( @pytest.mark.parametrize( - ("mock_config_entry", "server", "status_response", "entity_ids"), + ( + "mock_config_entry", + "server", + "lookup_function_name", + "status_response", + "entity_ids", + ), [ ( "java_mock_config_entry", JavaServer, + "async_lookup", TEST_JAVA_STATUS_RESPONSE, JAVA_SENSOR_ENTITIES_DISABLED_BY_DEFAULT, ), ( "bedrock_mock_config_entry", BedrockServer, + "lookup", TEST_BEDROCK_STATUS_RESPONSE, BEDROCK_SENSOR_ENTITIES_DISABLED_BY_DEFAULT, ), @@ -118,6 +135,7 @@ async def test_sensor_disabled_by_default( hass: HomeAssistant, mock_config_entry: str, server: JavaServer | BedrockServer, + lookup_function_name: str, status_response: JavaStatusResponse | BedrockStatusResponse, entity_ids: list[str], request: pytest.FixtureRequest, @@ -127,7 +145,7 @@ async def test_sensor_disabled_by_default( mock_config_entry.add_to_hass(hass) with patch( - f"homeassistant.components.minecraft_server.api.{server.__name__}.lookup", + f"homeassistant.components.minecraft_server.api.{server.__name__}.{lookup_function_name}", return_value=server(host=TEST_HOST, port=TEST_PORT), ), patch( f"homeassistant.components.minecraft_server.api.{server.__name__}.async_status", @@ -141,17 +159,25 @@ async def test_sensor_disabled_by_default( @pytest.mark.usefixtures("entity_registry_enabled_by_default") @pytest.mark.parametrize( - ("mock_config_entry", "server", "status_response", "entity_ids"), + ( + "mock_config_entry", + "server", + "lookup_function_name", + "status_response", + "entity_ids", + ), [ ( "java_mock_config_entry", JavaServer, + "async_lookup", TEST_JAVA_STATUS_RESPONSE, JAVA_SENSOR_ENTITIES, ), ( "bedrock_mock_config_entry", BedrockServer, + "lookup", TEST_BEDROCK_STATUS_RESPONSE, BEDROCK_SENSOR_ENTITIES, ), @@ -161,6 +187,7 @@ async def test_sensor_update( hass: HomeAssistant, mock_config_entry: str, server: JavaServer | BedrockServer, + lookup_function_name: str, status_response: JavaStatusResponse | BedrockStatusResponse, entity_ids: list[str], request: pytest.FixtureRequest, @@ -172,7 +199,7 @@ async def test_sensor_update( mock_config_entry.add_to_hass(hass) with patch( - f"homeassistant.components.minecraft_server.api.{server.__name__}.lookup", + f"homeassistant.components.minecraft_server.api.{server.__name__}.{lookup_function_name}", return_value=server(host=TEST_HOST, port=TEST_PORT), ), patch( f"homeassistant.components.minecraft_server.api.{server.__name__}.async_status", @@ -189,17 +216,25 @@ async def test_sensor_update( @pytest.mark.usefixtures("entity_registry_enabled_by_default") @pytest.mark.parametrize( - ("mock_config_entry", "server", "status_response", "entity_ids"), + ( + "mock_config_entry", + "server", + "lookup_function_name", + "status_response", + "entity_ids", + ), [ ( "java_mock_config_entry", JavaServer, + "async_lookup", TEST_JAVA_STATUS_RESPONSE, JAVA_SENSOR_ENTITIES, ), ( "bedrock_mock_config_entry", BedrockServer, + "lookup", TEST_BEDROCK_STATUS_RESPONSE, BEDROCK_SENSOR_ENTITIES, ), @@ -209,6 +244,7 @@ async def test_sensor_update_failure( hass: HomeAssistant, mock_config_entry: str, server: JavaServer | BedrockServer, + lookup_function_name: str, status_response: JavaStatusResponse | BedrockStatusResponse, entity_ids: list[str], request: pytest.FixtureRequest, @@ -219,7 +255,7 @@ async def test_sensor_update_failure( mock_config_entry.add_to_hass(hass) with patch( - f"homeassistant.components.minecraft_server.api.{server.__name__}.lookup", + f"homeassistant.components.minecraft_server.api.{server.__name__}.{lookup_function_name}", return_value=server(host=TEST_HOST, port=TEST_PORT), ), patch( f"homeassistant.components.minecraft_server.api.{server.__name__}.async_status",