Add diagnostics support in Minecraft Server (#101787)

* Add diagnostics support

* Return diagnostics dict directly

* Use syrupy snapshots for assertions in diagnostics test

* Use parametrize for testing diagnostics

* Remove unnecessary side_effect in patch
pull/101943/head
elmurato 2023-10-13 15:40:50 +02:00 committed by GitHub
parent 2609394b9f
commit 370e3166ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 192 additions and 2 deletions

View File

@ -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),
}

View File

@ -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,
)

View File

@ -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",

View File

@ -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',
}),
})
# ---

View File

@ -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
)