"""Test switch of NextDNS integration.""" from datetime import timedelta from unittest.mock import Mock, patch from aiohttp import ClientError from aiohttp.client_exceptions import ClientConnectorError from nextdns import ApiError import pytest from syrupy import SnapshotAssertion from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN from homeassistant.const import ( ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_OFF, STATE_ON, STATE_UNAVAILABLE, Platform, ) from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import entity_registry as er from homeassistant.util.dt import utcnow from . import init_integration, mock_nextdns from tests.common import async_fire_time_changed, snapshot_platform async def test_switch( hass: HomeAssistant, entity_registry_enabled_by_default: None, entity_registry: er.EntityRegistry, snapshot: SnapshotAssertion, ) -> None: """Test states of the switches.""" with patch("homeassistant.components.nextdns.PLATFORMS", [Platform.SWITCH]): entry = await init_integration(hass) await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id) async def test_switch_on(hass: HomeAssistant) -> None: """Test the switch can be turned on.""" await init_integration(hass) state = hass.states.get("switch.fake_profile_block_page") assert state assert state.state == STATE_OFF with patch( "homeassistant.components.nextdns.NextDns.set_setting", return_value=True ) as mock_switch_on: await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: "switch.fake_profile_block_page"}, blocking=True, ) await hass.async_block_till_done() state = hass.states.get("switch.fake_profile_block_page") assert state assert state.state == STATE_ON mock_switch_on.assert_called_once() async def test_switch_off(hass: HomeAssistant) -> None: """Test the switch can be turned on.""" await init_integration(hass) state = hass.states.get("switch.fake_profile_web3") assert state assert state.state == STATE_ON with patch( "homeassistant.components.nextdns.NextDns.set_setting", return_value=True ) as mock_switch_on: await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: "switch.fake_profile_web3"}, blocking=True, ) await hass.async_block_till_done() state = hass.states.get("switch.fake_profile_web3") assert state assert state.state == STATE_OFF mock_switch_on.assert_called_once() async def test_availability(hass: HomeAssistant) -> None: """Ensure that we mark the entities unavailable correctly when service causes an error.""" await init_integration(hass) state = hass.states.get("switch.fake_profile_web3") assert state assert state.state != STATE_UNAVAILABLE assert state.state == STATE_ON future = utcnow() + timedelta(minutes=10) with patch( "homeassistant.components.nextdns.NextDns.get_settings", side_effect=ApiError("API Error"), ): async_fire_time_changed(hass, future) await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("switch.fake_profile_web3") assert state assert state.state == STATE_UNAVAILABLE future = utcnow() + timedelta(minutes=20) with mock_nextdns(): async_fire_time_changed(hass, future) await hass.async_block_till_done(wait_background_tasks=True) state = hass.states.get("switch.fake_profile_web3") assert state assert state.state != STATE_UNAVAILABLE assert state.state == STATE_ON @pytest.mark.parametrize( "exc", [ ApiError(Mock()), TimeoutError, ClientConnectorError(Mock(), Mock()), ClientError, ], ) async def test_switch_failure(hass: HomeAssistant, exc: Exception) -> None: """Tests that the turn on/off service throws HomeAssistantError.""" await init_integration(hass) with ( patch("homeassistant.components.nextdns.NextDns.set_setting", side_effect=exc), pytest.raises(HomeAssistantError), ): await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: "switch.fake_profile_block_page"}, blocking=True, )