diff --git a/homeassistant/components/minecraft_server/diagnostics.py b/homeassistant/components/minecraft_server/diagnostics.py new file mode 100644 index 00000000000..62e507ef09f --- /dev/null +++ b/homeassistant/components/minecraft_server/diagnostics.py @@ -0,0 +1,31 @@ +"""Diagnostics for the Minecraft Server integration.""" +from collections.abc import Iterable +from dataclasses import asdict +from typing import Any + +from homeassistant.components.diagnostics.util import async_redact_data +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import CONF_ADDRESS, CONF_NAME +from homeassistant.core import HomeAssistant + +from .const import DOMAIN + +TO_REDACT: Iterable[Any] = {CONF_ADDRESS, CONF_NAME, "players_list"} + + +async def async_get_config_entry_diagnostics( + hass: HomeAssistant, config_entry: ConfigEntry +) -> dict[str, Any]: + """Return diagnostics for a config entry.""" + coordinator = hass.data[DOMAIN][config_entry.entry_id] + + return { + "config_entry": { + "version": config_entry.version, + "unique_id": config_entry.unique_id, + "entry_id": config_entry.entry_id, + }, + "config_entry_data": async_redact_data(config_entry.data, TO_REDACT), + "config_entry_options": async_redact_data(config_entry.options, TO_REDACT), + "server_data": async_redact_data(asdict(coordinator.data), TO_REDACT), + } diff --git a/tests/components/minecraft_server/conftest.py b/tests/components/minecraft_server/conftest.py new file mode 100644 index 00000000000..8e166fbb2da --- /dev/null +++ b/tests/components/minecraft_server/conftest.py @@ -0,0 +1,42 @@ +"""Fixtures for Minecraft Server integration tests.""" +import pytest + +from homeassistant.components.minecraft_server.api import MinecraftServerType +from homeassistant.components.minecraft_server.const import DEFAULT_NAME, DOMAIN +from homeassistant.const import CONF_ADDRESS, CONF_NAME, CONF_TYPE + +from .const import TEST_ADDRESS + +from tests.common import MockConfigEntry + + +@pytest.fixture +def java_mock_config_entry() -> MockConfigEntry: + """Create YouTube entry in Home Assistant.""" + return MockConfigEntry( + domain=DOMAIN, + unique_id=None, + entry_id="01234567890123456789012345678901", + data={ + CONF_NAME: DEFAULT_NAME, + CONF_ADDRESS: TEST_ADDRESS, + CONF_TYPE: MinecraftServerType.JAVA_EDITION, + }, + version=3, + ) + + +@pytest.fixture +def bedrock_mock_config_entry() -> MockConfigEntry: + """Create YouTube entry in Home Assistant.""" + return MockConfigEntry( + domain=DOMAIN, + unique_id=None, + entry_id="01234567890123456789012345678901", + data={ + CONF_NAME: DEFAULT_NAME, + CONF_ADDRESS: TEST_ADDRESS, + CONF_TYPE: MinecraftServerType.BEDROCK_EDITION, + }, + version=3, + ) diff --git a/tests/components/minecraft_server/const.py b/tests/components/minecraft_server/const.py index c579461611e..f299dd8efb8 100644 --- a/tests/components/minecraft_server/const.py +++ b/tests/components/minecraft_server/const.py @@ -16,7 +16,7 @@ TEST_PORT = 25566 TEST_ADDRESS = f"{TEST_HOST}:{TEST_PORT}" TEST_JAVA_STATUS_RESPONSE_RAW = { - "description": {"text": "Dummy Description"}, + "description": {"text": "Dummy MOTD"}, "version": {"name": "Dummy Version", "protocol": 123}, "players": { "online": 3, @@ -54,7 +54,7 @@ TEST_JAVA_DATA = MinecraftServerData( TEST_BEDROCK_STATUS_RESPONSE = BedrockStatusResponse( players=BedrockStatusPlayers(online=3, max=10), version=BedrockStatusVersion(brand="MCPE", name="Dummy Version", protocol=123), - motd=Motd.parse("Dummy Description", bedrock=True), + motd=Motd.parse("Dummy MOTD", bedrock=True), latency=5, gamemode="Dummy Game Mode", map_name="Dummy Map Name", diff --git a/tests/components/minecraft_server/snapshots/test_diagnostics.ambr b/tests/components/minecraft_server/snapshots/test_diagnostics.ambr new file mode 100644 index 00000000000..72d79795c6a --- /dev/null +++ b/tests/components/minecraft_server/snapshots/test_diagnostics.ambr @@ -0,0 +1,57 @@ +# serializer version: 1 +# name: test_config_entry_diagnostics[bedrock_mock_config_entry-BedrockServer-status_response1] + dict({ + 'config_entry': dict({ + 'entry_id': '01234567890123456789012345678901', + 'unique_id': None, + 'version': 3, + }), + 'config_entry_data': dict({ + 'address': '**REDACTED**', + 'name': '**REDACTED**', + 'type': 'Bedrock Edition', + }), + 'config_entry_options': dict({ + }), + 'server_data': dict({ + 'edition': 'MCPE', + 'game_mode': 'Dummy Game Mode', + 'latency': 5, + 'map_name': 'Dummy Map Name', + 'motd': 'Dummy MOTD', + 'players_list': None, + 'players_max': 10, + 'players_online': 3, + 'protocol_version': 123, + 'version': 'Dummy Version', + }), + }) +# --- +# name: test_config_entry_diagnostics[java_mock_config_entry-JavaServer-status_response0] + dict({ + 'config_entry': dict({ + 'entry_id': '01234567890123456789012345678901', + 'unique_id': None, + 'version': 3, + }), + 'config_entry_data': dict({ + 'address': '**REDACTED**', + 'name': '**REDACTED**', + 'type': 'Java Edition', + }), + 'config_entry_options': dict({ + }), + 'server_data': dict({ + 'edition': None, + 'game_mode': None, + 'latency': 5, + 'map_name': None, + 'motd': 'Dummy MOTD', + 'players_list': '**REDACTED**', + 'players_max': 10, + 'players_online': 3, + 'protocol_version': 123, + 'version': 'Dummy Version', + }), + }) +# --- diff --git a/tests/components/minecraft_server/test_diagnostics.py b/tests/components/minecraft_server/test_diagnostics.py new file mode 100644 index 00000000000..6979325fa0c --- /dev/null +++ b/tests/components/minecraft_server/test_diagnostics.py @@ -0,0 +1,60 @@ +"""Tests for Minecraft Server diagnostics.""" +from unittest.mock import patch + +from mcstatus import BedrockServer, JavaServer +from mcstatus.status_response import BedrockStatusResponse, JavaStatusResponse +import pytest +from syrupy import SnapshotAssertion + +from homeassistant.core import HomeAssistant + +from .const import ( + TEST_BEDROCK_STATUS_RESPONSE, + TEST_HOST, + TEST_JAVA_STATUS_RESPONSE, + TEST_PORT, +) + +from tests.common import MockConfigEntry +from tests.components.diagnostics import get_diagnostics_for_config_entry +from tests.typing import ClientSessionGenerator + + +@pytest.mark.parametrize( + ("mock_config_entry", "server", "status_response"), + [ + ("java_mock_config_entry", JavaServer, TEST_JAVA_STATUS_RESPONSE), + ("bedrock_mock_config_entry", BedrockServer, TEST_BEDROCK_STATUS_RESPONSE), + ], +) +async def test_config_entry_diagnostics( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + mock_config_entry: MockConfigEntry, + server: JavaServer | BedrockServer, + status_response: JavaStatusResponse | BedrockStatusResponse, + request: pytest.FixtureRequest, + snapshot: SnapshotAssertion, +) -> None: + """Test fetching of the config entry diagnostics.""" + + # Use 'request' fixture to access 'mock_config_entry' fixture, as it cannot be used directly in 'parametrize'. + mock_config_entry = request.getfixturevalue(mock_config_entry) + mock_config_entry.add_to_hass(hass) + + # Setup mock entry. + with patch( + f"mcstatus.server.{server.__name__}.lookup", + return_value=server(host=TEST_HOST, port=TEST_PORT), + ), patch( + f"mcstatus.server.{server.__name__}.async_status", + return_value=status_response, + ): + assert await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + # Test diagnostics. + assert ( + await get_diagnostics_for_config_entry(hass, hass_client, mock_config_entry) + == snapshot + )