Add switch platform to UptimeRobot (#65394)
* Add switch platfor mto UptimeRobot * Add tests * Apply review comment * review comments part 2 * review comments part 3 * Fix tests after swapping logic on/off * Fix reauth test * Check for read-only key * Fix reauth for switch platform * mypy * cleanup * cleanup part 2 * Fixes + review comments * Tests * Apply more review comments * Required changes * fix test * Remove if * 100% tests coverage * Check readonly key in config_flow * Fix strings & translation * Add guard for 'monitor' keys * allign tests * Wrong API key message reworded
This commit is contained in:
parent
5bb271c9fb
commit
35261a9089
13 changed files with 357 additions and 42 deletions
|
@ -26,9 +26,12 @@ from .const import API_ATTR_OK, COORDINATOR_UPDATE_INTERVAL, DOMAIN, LOGGER, PLA
|
|||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up UptimeRobot from a config entry."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
uptime_robot_api = UptimeRobot(
|
||||
entry.data[CONF_API_KEY], async_get_clientsession(hass)
|
||||
key: str = entry.data[CONF_API_KEY]
|
||||
if key.startswith("ur") or key.startswith("m"):
|
||||
raise ConfigEntryAuthFailed(
|
||||
"Wrong API key type detected, use the 'main' API key"
|
||||
)
|
||||
uptime_robot_api = UptimeRobot(key, async_get_clientsession(hass))
|
||||
dev_reg = await async_get_registry(hass)
|
||||
|
||||
hass.data[DOMAIN][entry.entry_id] = coordinator = UptimeRobotDataUpdateCoordinator(
|
||||
|
@ -58,6 +61,7 @@ class UptimeRobotDataUpdateCoordinator(DataUpdateCoordinator):
|
|||
"""Data update coordinator for UptimeRobot."""
|
||||
|
||||
data: list[UptimeRobotMonitor]
|
||||
config_entry: ConfigEntry
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
|
|
@ -23,7 +23,6 @@ async def async_setup_entry(
|
|||
"""Set up the UptimeRobot binary_sensors."""
|
||||
coordinator: UptimeRobotDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
async_add_entities(
|
||||
[
|
||||
UptimeRobotBinarySensor(
|
||||
coordinator,
|
||||
BinarySensorEntityDescription(
|
||||
|
@ -34,7 +33,6 @@ async def async_setup_entry(
|
|||
monitor=monitor,
|
||||
)
|
||||
for monitor in coordinator.data
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -34,9 +34,12 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"""Validate the user input allows us to connect."""
|
||||
errors: dict[str, str] = {}
|
||||
response: UptimeRobotApiResponse | UptimeRobotApiError | None = None
|
||||
uptime_robot_api = UptimeRobot(
|
||||
data[CONF_API_KEY], async_get_clientsession(self.hass)
|
||||
)
|
||||
key: str = data[CONF_API_KEY]
|
||||
if key.startswith("ur") or key.startswith("m"):
|
||||
LOGGER.error("Wrong API key type detected, use the 'main' API key")
|
||||
errors["base"] = "not_main_key"
|
||||
return errors, None
|
||||
uptime_robot_api = UptimeRobot(key, async_get_clientsession(self.hass))
|
||||
|
||||
try:
|
||||
response = await uptime_robot_api.async_get_account_details()
|
||||
|
|
|
@ -13,7 +13,7 @@ LOGGER: Logger = getLogger(__package__)
|
|||
COORDINATOR_UPDATE_INTERVAL: timedelta = timedelta(seconds=10)
|
||||
|
||||
DOMAIN: Final = "uptimerobot"
|
||||
PLATFORMS: Final = [Platform.BINARY_SENSOR, Platform.SENSOR]
|
||||
PLATFORMS: Final = [Platform.BINARY_SENSOR, Platform.SENSOR, Platform.SWITCH]
|
||||
|
||||
ATTRIBUTION: Final = "Data provided by UptimeRobot"
|
||||
|
||||
|
|
|
@ -5,11 +5,9 @@ from pyuptimerobot import UptimeRobotMonitor
|
|||
|
||||
from homeassistant.helpers.device_registry import DeviceEntryType
|
||||
from homeassistant.helpers.entity import DeviceInfo, EntityDescription
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
CoordinatorEntity,
|
||||
DataUpdateCoordinator,
|
||||
)
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import UptimeRobotDataUpdateCoordinator
|
||||
from .const import ATTR_TARGET, ATTRIBUTION, DOMAIN
|
||||
|
||||
|
||||
|
@ -17,10 +15,11 @@ class UptimeRobotEntity(CoordinatorEntity):
|
|||
"""Base UptimeRobot entity."""
|
||||
|
||||
_attr_attribution = ATTRIBUTION
|
||||
coordinator: UptimeRobotDataUpdateCoordinator
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: DataUpdateCoordinator,
|
||||
coordinator: UptimeRobotDataUpdateCoordinator,
|
||||
description: EntityDescription,
|
||||
monitor: UptimeRobotMonitor,
|
||||
) -> None:
|
||||
|
@ -40,6 +39,7 @@ class UptimeRobotEntity(CoordinatorEntity):
|
|||
ATTR_TARGET: self.monitor.url,
|
||||
}
|
||||
self._attr_unique_id = str(self.monitor.id)
|
||||
self.api = coordinator.api
|
||||
|
||||
@property
|
||||
def _monitors(self) -> list[UptimeRobotMonitor]:
|
||||
|
|
|
@ -38,7 +38,6 @@ async def async_setup_entry(
|
|||
"""Set up the UptimeRobot sensors."""
|
||||
coordinator: UptimeRobotDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
async_add_entities(
|
||||
[
|
||||
UptimeRobotSensor(
|
||||
coordinator,
|
||||
SensorEntityDescription(
|
||||
|
@ -50,7 +49,6 @@ async def async_setup_entry(
|
|||
monitor=monitor,
|
||||
)
|
||||
for monitor in coordinator.data
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"description": "You need to supply a read-only API key from UptimeRobot",
|
||||
"description": "You need to supply the 'main' API key from UptimeRobot",
|
||||
"data": {
|
||||
"api_key": "[%key:common::config_flow::data::api_key%]"
|
||||
}
|
||||
},
|
||||
"reauth_confirm": {
|
||||
"title": "[%key:common::config_flow::title::reauth%]",
|
||||
"description": "You need to supply a new read-only API key from UptimeRobot",
|
||||
"description": "You need to supply a new 'main' API key from UptimeRobot",
|
||||
"data": {
|
||||
"api_key": "[%key:common::config_flow::data::api_key%]"
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
|||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"invalid_api_key": "[%key:common::config_flow::error::invalid_api_key%]",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]",
|
||||
"not_main_key": "Wrong API key type detected, use the 'main' API key",
|
||||
"reauth_failed_matching_account": "The API key you provided does not match the account ID for existing configuration."
|
||||
},
|
||||
"abort": {
|
||||
|
|
75
homeassistant/components/uptimerobot/switch.py
Normal file
75
homeassistant/components/uptimerobot/switch.py
Normal file
|
@ -0,0 +1,75 @@
|
|||
"""UptimeRobot switch platform."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from pyuptimerobot import UptimeRobotAuthenticationException, UptimeRobotException
|
||||
|
||||
from homeassistant.components.switch import (
|
||||
SwitchDeviceClass,
|
||||
SwitchEntity,
|
||||
SwitchEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import UptimeRobotDataUpdateCoordinator
|
||||
from .const import API_ATTR_OK, DOMAIN, LOGGER
|
||||
from .entity import UptimeRobotEntity
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||
) -> None:
|
||||
"""Set up the UptimeRobot switches."""
|
||||
coordinator: UptimeRobotDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
async_add_entities(
|
||||
UptimeRobotSwitch(
|
||||
coordinator,
|
||||
SwitchEntityDescription(
|
||||
key=str(monitor.id),
|
||||
name=f"{monitor.friendly_name} Active",
|
||||
device_class=SwitchDeviceClass.SWITCH,
|
||||
),
|
||||
monitor=monitor,
|
||||
)
|
||||
for monitor in coordinator.data
|
||||
)
|
||||
|
||||
|
||||
class UptimeRobotSwitch(UptimeRobotEntity, SwitchEntity):
|
||||
"""Representation of a UptimeRobot switch."""
|
||||
|
||||
_attr_icon = "mdi:cog"
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return True if the entity is on."""
|
||||
return bool(self.monitor.status != 0)
|
||||
|
||||
async def _async_edit_monitor(self, **kwargs: Any) -> None:
|
||||
"""Edit monitor status."""
|
||||
try:
|
||||
response = await self.api.async_edit_monitor(**kwargs)
|
||||
except UptimeRobotAuthenticationException:
|
||||
LOGGER.debug("API authentication error, calling reauth")
|
||||
self.coordinator.config_entry.async_start_reauth(self.hass)
|
||||
return
|
||||
except UptimeRobotException as exception:
|
||||
LOGGER.error("API exception: %s", exception)
|
||||
return
|
||||
|
||||
if response.status != API_ATTR_OK:
|
||||
LOGGER.error("API exception: %s", response.error.message, exc_info=True)
|
||||
return
|
||||
|
||||
await self.coordinator.async_request_refresh()
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn on switch."""
|
||||
await self._async_edit_monitor(id=self.monitor.id, status=0)
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn off switch."""
|
||||
await self._async_edit_monitor(id=self.monitor.id, status=1)
|
|
@ -9,6 +9,7 @@
|
|||
"error": {
|
||||
"cannot_connect": "Failed to connect",
|
||||
"invalid_api_key": "Invalid API key",
|
||||
"not_main_key": "Wrong API key type detected, use the 'main' API key",
|
||||
"reauth_failed_matching_account": "The API key you provided does not match the account ID for existing configuration.",
|
||||
"unknown": "Unexpected error"
|
||||
},
|
||||
|
@ -17,14 +18,14 @@
|
|||
"data": {
|
||||
"api_key": "API Key"
|
||||
},
|
||||
"description": "You need to supply a new read-only API key from UptimeRobot",
|
||||
"description": "You need to supply a new 'main' API key from UptimeRobot",
|
||||
"title": "Reauthenticate Integration"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API Key"
|
||||
},
|
||||
"description": "You need to supply a read-only API key from UptimeRobot"
|
||||
"description": "You need to supply the 'main' API key from UptimeRobot"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ from homeassistant.core import HomeAssistant
|
|||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
MOCK_UPTIMEROBOT_API_KEY = "0242ac120003"
|
||||
MOCK_UPTIMEROBOT_API_KEY = "u0242ac120003"
|
||||
MOCK_UPTIMEROBOT_API_KEY_READ_ONLY = "ur0242ac120003"
|
||||
MOCK_UPTIMEROBOT_EMAIL = "test@test.test"
|
||||
MOCK_UPTIMEROBOT_UNIQUE_ID = "1234567890"
|
||||
|
||||
|
@ -37,6 +38,14 @@ MOCK_UPTIMEROBOT_MONITOR = {
|
|||
"type": 1,
|
||||
"url": "http://example.com",
|
||||
}
|
||||
MOCK_UPTIMEROBOT_MONITOR_PAUSED = {
|
||||
"id": 1234,
|
||||
"friendly_name": "Test monitor",
|
||||
"status": 0,
|
||||
"type": 1,
|
||||
"url": "http://example.com",
|
||||
}
|
||||
|
||||
|
||||
MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA = {
|
||||
"domain": DOMAIN,
|
||||
|
@ -45,11 +54,19 @@ MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA = {
|
|||
"unique_id": MOCK_UPTIMEROBOT_UNIQUE_ID,
|
||||
"source": config_entries.SOURCE_USER,
|
||||
}
|
||||
MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA_KEY_READ_ONLY = {
|
||||
"domain": DOMAIN,
|
||||
"title": MOCK_UPTIMEROBOT_EMAIL,
|
||||
"data": {"platform": DOMAIN, "api_key": MOCK_UPTIMEROBOT_API_KEY_READ_ONLY},
|
||||
"unique_id": MOCK_UPTIMEROBOT_UNIQUE_ID,
|
||||
"source": config_entries.SOURCE_USER,
|
||||
}
|
||||
|
||||
STATE_UP = "up"
|
||||
|
||||
UPTIMEROBOT_BINARY_SENSOR_TEST_ENTITY = "binary_sensor.test_monitor"
|
||||
UPTIMEROBOT_SENSOR_TEST_ENTITY = "sensor.test_monitor"
|
||||
UPTIMEROBOT_SWITCH_TEST_ENTITY = "switch.test_monitor_active"
|
||||
|
||||
|
||||
class MockApiResponseKey(str, Enum):
|
||||
|
|
|
@ -18,6 +18,7 @@ from homeassistant.data_entry_flow import (
|
|||
from .common import (
|
||||
MOCK_UPTIMEROBOT_ACCOUNT,
|
||||
MOCK_UPTIMEROBOT_API_KEY,
|
||||
MOCK_UPTIMEROBOT_API_KEY_READ_ONLY,
|
||||
MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA,
|
||||
MOCK_UPTIMEROBOT_UNIQUE_ID,
|
||||
MockApiResponseKey,
|
||||
|
@ -56,6 +57,29 @@ async def test_form(hass: HomeAssistant) -> None:
|
|||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_form_read_only(hass: HomeAssistant) -> None:
|
||||
"""Test we get the form."""
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert result["errors"] is None
|
||||
|
||||
with patch(
|
||||
"pyuptimerobot.UptimeRobot.async_get_account_details",
|
||||
return_value=mock_uptimerobot_api_response(key=MockApiResponseKey.ACCOUNT),
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{CONF_API_KEY: MOCK_UPTIMEROBOT_API_KEY_READ_ONLY},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] == RESULT_TYPE_FORM
|
||||
assert result2["errors"]["base"] == "not_main_key"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"exception,error_key",
|
||||
[
|
||||
|
|
|
@ -19,6 +19,7 @@ from homeassistant.util import dt
|
|||
|
||||
from .common import (
|
||||
MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA,
|
||||
MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA_KEY_READ_ONLY,
|
||||
MOCK_UPTIMEROBOT_MONITOR,
|
||||
UPTIMEROBOT_BINARY_SENSOR_TEST_ENTITY,
|
||||
MockApiResponseKey,
|
||||
|
@ -62,6 +63,39 @@ async def test_reauthentication_trigger_in_setup(
|
|||
)
|
||||
|
||||
|
||||
async def test_reauthentication_trigger_key_read_only(
|
||||
hass: HomeAssistant, caplog: LogCaptureFixture
|
||||
):
|
||||
"""Test reauthentication trigger."""
|
||||
mock_config_entry = MockConfigEntry(
|
||||
**MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA_KEY_READ_ONLY
|
||||
)
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
flows = hass.config_entries.flow.async_progress()
|
||||
|
||||
assert mock_config_entry.state == config_entries.ConfigEntryState.SETUP_ERROR
|
||||
assert (
|
||||
mock_config_entry.reason
|
||||
== "Wrong API key type detected, use the 'main' API key"
|
||||
)
|
||||
|
||||
assert len(flows) == 1
|
||||
flow = flows[0]
|
||||
assert flow["step_id"] == "reauth_confirm"
|
||||
assert flow["handler"] == DOMAIN
|
||||
assert flow["context"]["source"] == config_entries.SOURCE_REAUTH
|
||||
assert flow["context"]["entry_id"] == mock_config_entry.entry_id
|
||||
|
||||
assert (
|
||||
"Config entry 'test@test.test' for uptimerobot integration could not authenticate"
|
||||
in caplog.text
|
||||
)
|
||||
|
||||
|
||||
async def test_reauthentication_trigger_after_setup(
|
||||
hass: HomeAssistant, caplog: LogCaptureFixture
|
||||
):
|
||||
|
|
160
tests/components/uptimerobot/test_switch.py
Normal file
160
tests/components/uptimerobot/test_switch.py
Normal file
|
@ -0,0 +1,160 @@
|
|||
"""Test UptimeRobot switch."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from pyuptimerobot import UptimeRobotAuthenticationException
|
||||
|
||||
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,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .common import (
|
||||
MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA,
|
||||
MOCK_UPTIMEROBOT_MONITOR,
|
||||
MOCK_UPTIMEROBOT_MONITOR_PAUSED,
|
||||
UPTIMEROBOT_SWITCH_TEST_ENTITY,
|
||||
MockApiResponseKey,
|
||||
mock_uptimerobot_api_response,
|
||||
setup_uptimerobot_integration,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_presentation(hass: HomeAssistant) -> None:
|
||||
"""Test the presenstation of UptimeRobot sensors."""
|
||||
await setup_uptimerobot_integration(hass)
|
||||
|
||||
entity = hass.states.get(UPTIMEROBOT_SWITCH_TEST_ENTITY)
|
||||
|
||||
assert entity.state == STATE_ON
|
||||
assert entity.attributes["icon"] == "mdi:cog"
|
||||
assert entity.attributes["target"] == MOCK_UPTIMEROBOT_MONITOR["url"]
|
||||
|
||||
|
||||
async def test_switch_off(hass: HomeAssistant) -> None:
|
||||
"""Test entity unaviable on update failure."""
|
||||
|
||||
mock_entry = MockConfigEntry(**MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA)
|
||||
mock_entry.add_to_hass(hass)
|
||||
|
||||
with patch(
|
||||
"pyuptimerobot.UptimeRobot.async_get_monitors",
|
||||
return_value=mock_uptimerobot_api_response(
|
||||
data=[MOCK_UPTIMEROBOT_MONITOR_PAUSED]
|
||||
),
|
||||
), patch(
|
||||
"pyuptimerobot.UptimeRobot.async_edit_monitor",
|
||||
return_value=mock_uptimerobot_api_response(),
|
||||
):
|
||||
|
||||
assert await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: UPTIMEROBOT_SWITCH_TEST_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
entity = hass.states.get(UPTIMEROBOT_SWITCH_TEST_ENTITY)
|
||||
assert entity.state == STATE_OFF
|
||||
|
||||
|
||||
async def test_switch_on(hass: HomeAssistant) -> None:
|
||||
"""Test entity unaviable on update failure."""
|
||||
|
||||
mock_entry = MockConfigEntry(**MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA)
|
||||
mock_entry.add_to_hass(hass)
|
||||
|
||||
with patch(
|
||||
"pyuptimerobot.UptimeRobot.async_get_monitors",
|
||||
return_value=mock_uptimerobot_api_response(data=[MOCK_UPTIMEROBOT_MONITOR]),
|
||||
), patch(
|
||||
"pyuptimerobot.UptimeRobot.async_edit_monitor",
|
||||
return_value=mock_uptimerobot_api_response(),
|
||||
):
|
||||
|
||||
assert await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: UPTIMEROBOT_SWITCH_TEST_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
entity = hass.states.get(UPTIMEROBOT_SWITCH_TEST_ENTITY)
|
||||
assert entity.state == STATE_ON
|
||||
|
||||
|
||||
async def test_authentication_error(hass: HomeAssistant, caplog) -> None:
|
||||
"""Test authentication error turning switch on/off."""
|
||||
await setup_uptimerobot_integration(hass)
|
||||
|
||||
entity = hass.states.get(UPTIMEROBOT_SWITCH_TEST_ENTITY)
|
||||
assert entity.state == STATE_ON
|
||||
|
||||
with patch(
|
||||
"pyuptimerobot.UptimeRobot.async_edit_monitor",
|
||||
side_effect=UptimeRobotAuthenticationException,
|
||||
), patch(
|
||||
"homeassistant.config_entries.ConfigEntry.async_start_reauth"
|
||||
) as config_entry_reauth:
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: UPTIMEROBOT_SWITCH_TEST_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert config_entry_reauth.assert_called
|
||||
|
||||
|
||||
async def test_refresh_data(hass: HomeAssistant, caplog) -> None:
|
||||
"""Test authentication error turning switch on/off."""
|
||||
await setup_uptimerobot_integration(hass)
|
||||
|
||||
entity = hass.states.get(UPTIMEROBOT_SWITCH_TEST_ENTITY)
|
||||
assert entity.state == STATE_ON
|
||||
|
||||
with patch(
|
||||
"homeassistant.helpers.update_coordinator.DataUpdateCoordinator.async_request_refresh"
|
||||
) as coordinator_refresh:
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: UPTIMEROBOT_SWITCH_TEST_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert coordinator_refresh.assert_called
|
||||
|
||||
|
||||
async def test_switch_api_failure(hass: HomeAssistant, caplog) -> None:
|
||||
"""Test general exception turning switch on/off."""
|
||||
await setup_uptimerobot_integration(hass)
|
||||
|
||||
entity = hass.states.get(UPTIMEROBOT_SWITCH_TEST_ENTITY)
|
||||
assert entity.state == STATE_ON
|
||||
|
||||
with patch(
|
||||
"pyuptimerobot.UptimeRobot.async_edit_monitor",
|
||||
return_value=mock_uptimerobot_api_response(key=MockApiResponseKey.ERROR),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: UPTIMEROBOT_SWITCH_TEST_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert "API exception" in caplog.text
|
Loading…
Add table
Add a link
Reference in a new issue