diff --git a/homeassistant/components/nextdns/__init__.py b/homeassistant/components/nextdns/__init__.py index 7df172da8ab..f9cb1f60cd1 100644 --- a/homeassistant/components/nextdns/__init__.py +++ b/homeassistant/components/nextdns/__init__.py @@ -20,7 +20,7 @@ from nextdns import ( from nextdns.model import NextDnsData from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_API_KEY +from homeassistant.const import CONF_API_KEY, Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers.aiohttp_client import async_get_clientsession @@ -131,7 +131,7 @@ class NextDnsProtocolsUpdateCoordinator(NextDnsUpdateCoordinator): _LOGGER = logging.getLogger(__name__) -PLATFORMS = ["sensor"] +PLATFORMS = [Platform.BUTTON, Platform.SENSOR] COORDINATORS = [ (ATTR_DNSSEC, NextDnsDnssecUpdateCoordinator, UPDATE_INTERVAL_ANALYTICS), (ATTR_ENCRYPTION, NextDnsEncryptionUpdateCoordinator, UPDATE_INTERVAL_ANALYTICS), diff --git a/homeassistant/components/nextdns/button.py b/homeassistant/components/nextdns/button.py new file mode 100644 index 00000000000..efe742a6113 --- /dev/null +++ b/homeassistant/components/nextdns/button.py @@ -0,0 +1,58 @@ +"""Support for the NextDNS service.""" +from __future__ import annotations + +from typing import cast + +from homeassistant.components.button import ButtonEntity, ButtonEntityDescription +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import EntityCategory +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.update_coordinator import CoordinatorEntity + +from . import NextDnsStatusUpdateCoordinator +from .const import ATTR_STATUS, DOMAIN + +PARALLEL_UPDATES = 1 + +CLEAR_LOGS_BUTTON = ButtonEntityDescription( + key="clear_logs", + name="{profile_name} Clear Logs", + entity_category=EntityCategory.CONFIG, +) + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Add aNextDNS entities from a config_entry.""" + coordinator: NextDnsStatusUpdateCoordinator = hass.data[DOMAIN][entry.entry_id][ + ATTR_STATUS + ] + + buttons: list[NextDnsButton] = [] + buttons.append(NextDnsButton(coordinator, CLEAR_LOGS_BUTTON)) + + async_add_entities(buttons) + + +class NextDnsButton(CoordinatorEntity[NextDnsStatusUpdateCoordinator], ButtonEntity): + """Define an NextDNS button.""" + + def __init__( + self, + coordinator: NextDnsStatusUpdateCoordinator, + description: ButtonEntityDescription, + ) -> None: + """Initialize.""" + super().__init__(coordinator) + self._attr_device_info = coordinator.device_info + self._attr_unique_id = f"{coordinator.profile_id}_{description.key}" + self._attr_name = cast(str, description.name).format( + profile_name=coordinator.profile_name + ) + self.entity_description = description + + async def async_press(self) -> None: + """Trigger cleaning logs.""" + await self.coordinator.nextdns.clear_logs(self.coordinator.profile_id) diff --git a/tests/components/nextdns/test_button.py b/tests/components/nextdns/test_button.py new file mode 100644 index 00000000000..39201a668a4 --- /dev/null +++ b/tests/components/nextdns/test_button.py @@ -0,0 +1,47 @@ +"""Test button of NextDNS integration.""" +from unittest.mock import patch + +from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN +from homeassistant.const import ATTR_ENTITY_ID, STATE_UNKNOWN +from homeassistant.helpers import entity_registry as er +from homeassistant.util import dt as dt_util + +from . import init_integration + + +async def test_button(hass): + """Test states of the button.""" + registry = er.async_get(hass) + + await init_integration(hass) + + state = hass.states.get("button.fake_profile_clear_logs") + assert state + assert state.state == STATE_UNKNOWN + + entry = registry.async_get("button.fake_profile_clear_logs") + assert entry + assert entry.unique_id == "xyz12_clear_logs" + + +async def test_button_press(hass): + """Test button press.""" + await init_integration(hass) + + now = dt_util.utcnow() + with patch( + "homeassistant.components.nextdns.NextDns.clear_logs" + ) as mock_clear_logs, patch("homeassistant.core.dt_util.utcnow", return_value=now): + await hass.services.async_call( + BUTTON_DOMAIN, + "press", + {ATTR_ENTITY_ID: "button.fake_profile_clear_logs"}, + blocking=True, + ) + await hass.async_block_till_done() + + mock_clear_logs.assert_called_once() + + state = hass.states.get("button.fake_profile_clear_logs") + assert state + assert state.state == now.isoformat()