Add 100% test coverage for Uptime Robot (#54314)

* Add 100% test coverage for Uptime Robot

* Update tests/components/uptimerobot/test_binary_sensor.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Add more typehints

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
pull/54411/head
Joakim Sørensen 2021-08-10 16:29:51 +02:00 committed by GitHub
parent f03b160c46
commit d1ea38e8f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 381 additions and 191 deletions

View File

@ -1115,10 +1115,6 @@ omit =
homeassistant/components/upcloud/switch.py
homeassistant/components/upnp/*
homeassistant/components/upc_connect/*
homeassistant/components/uptimerobot/__init__.py
homeassistant/components/uptimerobot/binary_sensor.py
homeassistant/components/uptimerobot/const.py
homeassistant/components/uptimerobot/entity.py
homeassistant/components/uscis/sensor.py
homeassistant/components/vallox/*
homeassistant/components/vasttrafik/sensor.py

View File

@ -53,7 +53,7 @@ async def async_setup_entry(
name=monitor.friendly_name,
device_class=DEVICE_CLASS_CONNECTIVITY,
),
target=monitor.url,
monitor=monitor,
)
for monitor in coordinator.data
],

View File

@ -20,11 +20,12 @@ class UptimeRobotEntity(CoordinatorEntity):
self,
coordinator: DataUpdateCoordinator,
description: EntityDescription,
target: str,
monitor: UptimeRobotMonitor,
) -> None:
"""Initialize Uptime Robot entities."""
super().__init__(coordinator)
self.entity_description = description
self._monitor = monitor
self._attr_device_info = {
"identifiers": {(DOMAIN, str(self.monitor.id))},
"name": "Uptime Robot",
@ -34,7 +35,7 @@ class UptimeRobotEntity(CoordinatorEntity):
}
self._attr_extra_state_attributes = {
ATTR_ATTRIBUTION: ATTRIBUTION,
ATTR_TARGET: target,
ATTR_TARGET: self.monitor.url,
}
self._attr_unique_id = str(self.monitor.id)
@ -47,9 +48,12 @@ class UptimeRobotEntity(CoordinatorEntity):
def monitor(self) -> UptimeRobotMonitor:
"""Return the monitor for this entity."""
return next(
monitor
for monitor in self._monitors
if str(monitor.id) == self.entity_description.key
(
monitor
for monitor in self._monitors
if str(monitor.id) == self.entity_description.key
),
self._monitor,
)
@property

View File

@ -0,0 +1,95 @@
"""Common constants and functions for Uptime Robot tests."""
from __future__ import annotations
from enum import Enum
from typing import Any
from unittest.mock import patch
from pyuptimerobot import (
APIStatus,
UptimeRobotAccount,
UptimeRobotApiError,
UptimeRobotApiResponse,
UptimeRobotMonitor,
)
from homeassistant import config_entries
from homeassistant.components.uptimerobot.const import DOMAIN
from homeassistant.const import STATE_ON
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
MOCK_UPTIMEROBOT_API_KEY = "1234"
MOCK_UPTIMEROBOT_UNIQUE_ID = "1234567890"
MOCK_UPTIMEROBOT_ACCOUNT = {"email": "test@test.test", "user_id": 1234567890}
MOCK_UPTIMEROBOT_ERROR = {"message": "test error from API."}
MOCK_UPTIMEROBOT_MONITOR = {
"id": 1234,
"friendly_name": "Test monitor",
"status": 2,
"type": 1,
"url": "http://example.com",
}
MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA = {
"domain": DOMAIN,
"title": "test@test.test",
"data": {"platform": DOMAIN, "api_key": MOCK_UPTIMEROBOT_API_KEY},
"unique_id": MOCK_UPTIMEROBOT_UNIQUE_ID,
"source": config_entries.SOURCE_USER,
}
UPTIMEROBOT_TEST_ENTITY = "binary_sensor.test_monitor"
class MockApiResponseKey(str, Enum):
"""Mock API response key."""
ACCOUNT = "account"
ERROR = "error"
MONITORS = "monitors"
def mock_uptimerobot_api_response(
data: dict[str, Any]
| None
| list[UptimeRobotMonitor]
| UptimeRobotAccount
| UptimeRobotApiError = None,
status: APIStatus = APIStatus.OK,
key: MockApiResponseKey = MockApiResponseKey.MONITORS,
) -> UptimeRobotApiResponse:
"""Mock API response for Uptime Robot."""
return UptimeRobotApiResponse.from_dict(
{
"stat": {"error": APIStatus.FAIL}.get(key, status),
key: data
if data is not None
else {
"account": MOCK_UPTIMEROBOT_ACCOUNT,
"error": MOCK_UPTIMEROBOT_ERROR,
"monitors": [MOCK_UPTIMEROBOT_MONITOR],
}.get(key, {}),
}
)
async def setup_uptimerobot_integration(hass: HomeAssistant) -> MockConfigEntry:
"""Set up the Uptime Robot integration."""
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]),
):
assert await hass.config_entries.async_setup(mock_entry.entry_id)
await hass.async_block_till_done()
assert hass.states.get(UPTIMEROBOT_TEST_ENTITY).state == STATE_ON
assert mock_entry.state == config_entries.ConfigEntryState.LOADED
return mock_entry

View File

@ -0,0 +1,82 @@
"""Test Uptime Robot binary_sensor."""
from unittest.mock import patch
from pyuptimerobot import UptimeRobotAuthenticationException
from homeassistant.components.binary_sensor import DEVICE_CLASS_CONNECTIVITY
from homeassistant.components.uptimerobot.const import (
ATTRIBUTION,
COORDINATOR_UPDATE_INTERVAL,
DOMAIN,
)
from homeassistant.const import STATE_ON, STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from homeassistant.util import dt
from .common import (
MOCK_UPTIMEROBOT_API_KEY,
MOCK_UPTIMEROBOT_MONITOR,
UPTIMEROBOT_TEST_ENTITY,
MockApiResponseKey,
mock_uptimerobot_api_response,
setup_uptimerobot_integration,
)
from tests.common import async_fire_time_changed
async def test_config_import(hass: HomeAssistant) -> None:
"""Test importing YAML configuration."""
config = {
"binary_sensor": {
"platform": DOMAIN,
"api_key": MOCK_UPTIMEROBOT_API_KEY,
}
}
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
return_value=mock_uptimerobot_api_response(key=MockApiResponseKey.ACCOUNT),
), patch(
"pyuptimerobot.UptimeRobot.async_get_monitors",
return_value=mock_uptimerobot_api_response(),
):
assert await async_setup_component(hass, "binary_sensor", config)
await hass.async_block_till_done()
config_entries = hass.config_entries.async_entries(DOMAIN)
assert len(config_entries) == 1
config_entry = config_entries[0]
assert config_entry.source == "import"
async def test_presentation(hass: HomeAssistant) -> None:
"""Test the presenstation of Uptime Robot binary_sensors."""
await setup_uptimerobot_integration(hass)
entity = hass.states.get(UPTIMEROBOT_TEST_ENTITY)
assert entity.state == STATE_ON
assert entity.attributes["device_class"] == DEVICE_CLASS_CONNECTIVITY
assert entity.attributes["attribution"] == ATTRIBUTION
assert entity.attributes["target"] == MOCK_UPTIMEROBOT_MONITOR["url"]
async def test_unaviable_on_update_failure(hass: HomeAssistant) -> None:
"""Test entity unaviable on update failure."""
await setup_uptimerobot_integration(hass)
entity = hass.states.get(UPTIMEROBOT_TEST_ENTITY)
assert entity.state == STATE_ON
with patch(
"pyuptimerobot.UptimeRobot.async_get_monitors",
side_effect=UptimeRobotAuthenticationException,
):
async_fire_time_changed(hass, dt.utcnow() + COORDINATOR_UPDATE_INTERVAL)
await hass.async_block_till_done()
entity = hass.states.get(UPTIMEROBOT_TEST_ENTITY)
assert entity.state == STATE_UNAVAILABLE

View File

@ -1,15 +1,13 @@
"""Test the Uptime Robot config flow."""
from unittest.mock import patch
import pytest
from pytest import LogCaptureFixture
from pyuptimerobot import UptimeRobotApiResponse
from pyuptimerobot.exceptions import (
UptimeRobotAuthenticationException,
UptimeRobotException,
)
from pyuptimerobot import UptimeRobotAuthenticationException, UptimeRobotException
from homeassistant import config_entries, setup
from homeassistant.components.uptimerobot.const import DOMAIN
from homeassistant.const import CONF_API_KEY
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import (
RESULT_TYPE_ABORT,
@ -17,6 +15,15 @@ from homeassistant.data_entry_flow import (
RESULT_TYPE_FORM,
)
from .common import (
MOCK_UPTIMEROBOT_ACCOUNT,
MOCK_UPTIMEROBOT_API_KEY,
MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA,
MOCK_UPTIMEROBOT_UNIQUE_ID,
MockApiResponseKey,
mock_uptimerobot_api_response,
)
from tests.common import MockConfigEntry
@ -31,82 +38,49 @@ async def test_form(hass: HomeAssistant) -> None:
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
return_value=UptimeRobotApiResponse.from_dict(
{
"stat": "ok",
"account": {"email": "test@test.test", "user_id": 1234567890},
}
),
return_value=mock_uptimerobot_api_response(key=MockApiResponseKey.ACCOUNT),
), patch(
"homeassistant.components.uptimerobot.async_setup_entry",
return_value=True,
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "1234"},
{CONF_API_KEY: MOCK_UPTIMEROBOT_API_KEY},
)
await hass.async_block_till_done()
assert result2["result"].unique_id == "1234567890"
assert result2["result"].unique_id == MOCK_UPTIMEROBOT_UNIQUE_ID
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
assert result2["title"] == "test@test.test"
assert result2["data"] == {"api_key": "1234"}
assert result2["title"] == MOCK_UPTIMEROBOT_ACCOUNT["email"]
assert result2["data"] == {CONF_API_KEY: MOCK_UPTIMEROBOT_API_KEY}
assert len(mock_setup_entry.mock_calls) == 1
async def test_form_cannot_connect(hass: HomeAssistant) -> None:
"""Test we handle cannot connect error."""
@pytest.mark.parametrize(
"exception,error_key",
[
(Exception, "unknown"),
(UptimeRobotException, "cannot_connect"),
(UptimeRobotAuthenticationException, "invalid_api_key"),
],
)
async def test_form_exception_thrown(hass: HomeAssistant, exception, error_key) -> None:
"""Test that we handle exceptions."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
side_effect=UptimeRobotException,
side_effect=exception,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "1234"},
{CONF_API_KEY: MOCK_UPTIMEROBOT_API_KEY},
)
assert result2["type"] == RESULT_TYPE_FORM
assert result2["errors"]["base"] == "cannot_connect"
async def test_form_unexpected_error(hass: HomeAssistant) -> None:
"""Test we handle unexpected error."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
side_effect=Exception,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "1234"},
)
assert result2["errors"]["base"] == "unknown"
async def test_form_api_key_error(hass: HomeAssistant) -> None:
"""Test we handle unexpected error."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
side_effect=UptimeRobotAuthenticationException,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "1234"},
)
assert result2["errors"]["base"] == "invalid_api_key"
assert result2["errors"]["base"] == error_key
async def test_form_api_error(hass: HomeAssistant, caplog: LogCaptureFixture) -> None:
@ -117,32 +91,24 @@ async def test_form_api_error(hass: HomeAssistant, caplog: LogCaptureFixture) ->
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
return_value=UptimeRobotApiResponse.from_dict(
{
"stat": "fail",
"error": {"message": "test error from API."},
}
),
return_value=mock_uptimerobot_api_response(key=MockApiResponseKey.ERROR),
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "1234"},
{CONF_API_KEY: MOCK_UPTIMEROBOT_API_KEY},
)
assert result2["errors"]["base"] == "unknown"
assert "test error from API." in caplog.text
async def test_flow_import(hass):
async def test_flow_import(
hass: HomeAssistant,
) -> None:
"""Test an import flow."""
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
return_value=UptimeRobotApiResponse.from_dict(
{
"stat": "ok",
"account": {"email": "test@test.test", "user_id": 1234567890},
}
),
return_value=mock_uptimerobot_api_response(key=MockApiResponseKey.ACCOUNT),
), patch(
"homeassistant.components.uptimerobot.async_setup_entry",
return_value=True,
@ -150,22 +116,17 @@ async def test_flow_import(hass):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data={"platform": DOMAIN, "api_key": "1234"},
data={"platform": DOMAIN, CONF_API_KEY: MOCK_UPTIMEROBOT_API_KEY},
)
await hass.async_block_till_done()
assert len(mock_setup_entry.mock_calls) == 1
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
assert result["data"] == {"api_key": "1234"}
assert result["data"] == {CONF_API_KEY: MOCK_UPTIMEROBOT_API_KEY}
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
return_value=UptimeRobotApiResponse.from_dict(
{
"stat": "ok",
"account": {"email": "test@test.test", "user_id": 1234567890},
}
),
return_value=mock_uptimerobot_api_response(key=MockApiResponseKey.ACCOUNT),
), patch(
"homeassistant.components.uptimerobot.async_setup_entry",
return_value=True,
@ -173,7 +134,7 @@ async def test_flow_import(hass):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data={"platform": DOMAIN, "api_key": "1234"},
data={"platform": DOMAIN, CONF_API_KEY: MOCK_UPTIMEROBOT_API_KEY},
)
await hass.async_block_till_done()
@ -183,7 +144,9 @@ async def test_flow_import(hass):
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
return_value=UptimeRobotApiResponse.from_dict({"stat": "ok"}),
return_value=mock_uptimerobot_api_response(
key=MockApiResponseKey.ACCOUNT, data={}
),
), patch(
"homeassistant.components.uptimerobot.async_setup_entry",
return_value=True,
@ -191,7 +154,7 @@ async def test_flow_import(hass):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data={"platform": DOMAIN, "api_key": "12345"},
data={"platform": DOMAIN, CONF_API_KEY: "12345"},
)
await hass.async_block_till_done()
@ -199,13 +162,11 @@ async def test_flow_import(hass):
assert result["reason"] == "unknown"
async def test_user_unique_id_already_exists(hass):
async def test_user_unique_id_already_exists(
hass: HomeAssistant,
) -> None:
"""Test creating an entry where the unique_id already exists."""
entry = MockConfigEntry(
domain=DOMAIN,
data={"platform": DOMAIN, "api_key": "1234"},
unique_id="1234567890",
)
entry = MockConfigEntry(**MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA)
entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
@ -216,19 +177,14 @@ async def test_user_unique_id_already_exists(hass):
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
return_value=UptimeRobotApiResponse.from_dict(
{
"stat": "ok",
"account": {"email": "test@test.test", "user_id": 1234567890},
}
),
return_value=mock_uptimerobot_api_response(key=MockApiResponseKey.ACCOUNT),
), patch(
"homeassistant.components.uptimerobot.async_setup_entry",
return_value=True,
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "12345"},
{CONF_API_KEY: "12345"},
)
await hass.async_block_till_done()
@ -237,13 +193,11 @@ async def test_user_unique_id_already_exists(hass):
assert result2["reason"] == "already_configured"
async def test_reauthentication(hass):
async def test_reauthentication(
hass: HomeAssistant,
) -> None:
"""Test Uptime Robot reauthentication."""
old_entry = MockConfigEntry(
domain=DOMAIN,
data={"platform": DOMAIN, "api_key": "1234"},
unique_id="1234567890",
)
old_entry = MockConfigEntry(**MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA)
old_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
@ -262,12 +216,7 @@ async def test_reauthentication(hass):
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
return_value=UptimeRobotApiResponse.from_dict(
{
"stat": "ok",
"account": {"email": "test@test.test", "user_id": 1234567890},
}
),
return_value=mock_uptimerobot_api_response(key=MockApiResponseKey.ACCOUNT),
), patch(
"homeassistant.components.uptimerobot.async_setup_entry",
return_value=True,
@ -275,7 +224,7 @@ async def test_reauthentication(hass):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "1234"},
{CONF_API_KEY: MOCK_UPTIMEROBOT_API_KEY},
)
await hass.async_block_till_done()
@ -283,13 +232,11 @@ async def test_reauthentication(hass):
assert result2["reason"] == "reauth_successful"
async def test_reauthentication_failure(hass):
async def test_reauthentication_failure(
hass: HomeAssistant,
) -> None:
"""Test Uptime Robot reauthentication failure."""
old_entry = MockConfigEntry(
domain=DOMAIN,
data={"platform": DOMAIN, "api_key": "1234"},
unique_id="1234567890",
)
old_entry = MockConfigEntry(**MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA)
old_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
@ -308,12 +255,7 @@ async def test_reauthentication_failure(hass):
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
return_value=UptimeRobotApiResponse.from_dict(
{
"stat": "fail",
"error": {"message": "test error from API."},
}
),
return_value=mock_uptimerobot_api_response(key=MockApiResponseKey.ERROR),
), patch(
"homeassistant.components.uptimerobot.async_setup_entry",
return_value=True,
@ -321,7 +263,7 @@ async def test_reauthentication_failure(hass):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "1234"},
{CONF_API_KEY: MOCK_UPTIMEROBOT_API_KEY},
)
await hass.async_block_till_done()
@ -330,11 +272,12 @@ async def test_reauthentication_failure(hass):
assert result2["errors"]["base"] == "unknown"
async def test_reauthentication_failure_no_existing_entry(hass):
async def test_reauthentication_failure_no_existing_entry(
hass: HomeAssistant,
) -> None:
"""Test Uptime Robot reauthentication with no existing entry."""
old_entry = MockConfigEntry(
domain=DOMAIN,
data={"platform": DOMAIN, "api_key": "1234"},
**{**MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA, "unique_id": None}
)
old_entry.add_to_hass(hass)
@ -354,12 +297,7 @@ async def test_reauthentication_failure_no_existing_entry(hass):
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
return_value=UptimeRobotApiResponse.from_dict(
{
"stat": "ok",
"account": {"email": "test@test.test", "user_id": 1234567890},
}
),
return_value=mock_uptimerobot_api_response(key=MockApiResponseKey.ACCOUNT),
), patch(
"homeassistant.components.uptimerobot.async_setup_entry",
return_value=True,
@ -367,7 +305,7 @@ async def test_reauthentication_failure_no_existing_entry(hass):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "1234"},
{CONF_API_KEY: MOCK_UPTIMEROBOT_API_KEY},
)
await hass.async_block_till_done()
@ -375,13 +313,11 @@ async def test_reauthentication_failure_no_existing_entry(hass):
assert result2["reason"] == "reauth_failed_existing"
async def test_reauthentication_failure_account_not_matching(hass):
async def test_reauthentication_failure_account_not_matching(
hass: HomeAssistant,
) -> None:
"""Test Uptime Robot reauthentication failure when using another account."""
old_entry = MockConfigEntry(
domain=DOMAIN,
data={"platform": DOMAIN, "api_key": "1234"},
unique_id="1234567890",
)
old_entry = MockConfigEntry(**MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA)
old_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
@ -400,11 +336,9 @@ async def test_reauthentication_failure_account_not_matching(hass):
with patch(
"pyuptimerobot.UptimeRobot.async_get_account_details",
return_value=UptimeRobotApiResponse.from_dict(
{
"stat": "ok",
"account": {"email": "test@test.test", "user_id": 1234567891},
}
return_value=mock_uptimerobot_api_response(
key=MockApiResponseKey.ACCOUNT,
data={**MOCK_UPTIMEROBOT_ACCOUNT, "user_id": 1234567891},
),
), patch(
"homeassistant.components.uptimerobot.async_setup_entry",
@ -413,7 +347,7 @@ async def test_reauthentication_failure_account_not_matching(hass):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "1234"},
{CONF_API_KEY: MOCK_UPTIMEROBOT_API_KEY},
)
await hass.async_block_till_done()

View File

@ -1,16 +1,31 @@
"""Test the Uptime Robot init."""
import datetime
from unittest.mock import patch
from pytest import LogCaptureFixture
from pyuptimerobot import UptimeRobotApiResponse
from pyuptimerobot.exceptions import UptimeRobotAuthenticationException
from pyuptimerobot import UptimeRobotAuthenticationException, UptimeRobotException
from homeassistant import config_entries
from homeassistant.components.uptimerobot.const import DOMAIN
from homeassistant.components.uptimerobot.const import (
COORDINATOR_UPDATE_INTERVAL,
DOMAIN,
)
from homeassistant.const import STATE_ON, STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import (
async_entries_for_config_entry,
async_get_registry,
)
from homeassistant.util import dt
from .common import (
MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA,
MOCK_UPTIMEROBOT_MONITOR,
UPTIMEROBOT_TEST_ENTITY,
MockApiResponseKey,
mock_uptimerobot_api_response,
setup_uptimerobot_integration,
)
from tests.common import MockConfigEntry, async_fire_time_changed
@ -18,13 +33,7 @@ async def test_reauthentication_trigger_in_setup(
hass: HomeAssistant, caplog: LogCaptureFixture
):
"""Test reauthentication trigger."""
mock_config_entry = MockConfigEntry(
domain=DOMAIN,
title="test@test.test",
data={"platform": DOMAIN, "api_key": "1234"},
unique_id="1234567890",
source=config_entries.SOURCE_USER,
)
mock_config_entry = MockConfigEntry(**MOCK_UPTIMEROBOT_CONFIG_ENTRY_DATA)
mock_config_entry.add_to_hass(hass)
with patch(
@ -57,46 +66,23 @@ async def test_reauthentication_trigger_after_setup(
hass: HomeAssistant, caplog: LogCaptureFixture
):
"""Test reauthentication trigger."""
mock_config_entry = MockConfigEntry(
domain=DOMAIN,
title="test@test.test",
data={"platform": DOMAIN, "api_key": "1234"},
unique_id="1234567890",
source=config_entries.SOURCE_USER,
)
mock_config_entry.add_to_hass(hass)
mock_config_entry = await setup_uptimerobot_integration(hass)
with patch(
"pyuptimerobot.UptimeRobot.async_get_monitors",
return_value=UptimeRobotApiResponse.from_dict(
{
"stat": "ok",
"monitors": [
{"id": 1234, "friendly_name": "Test monitor", "status": 2}
],
}
),
):
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
binary_sensor = hass.states.get("binary_sensor.test_monitor")
binary_sensor = hass.states.get(UPTIMEROBOT_TEST_ENTITY)
assert mock_config_entry.state == config_entries.ConfigEntryState.LOADED
assert binary_sensor.state == "on"
assert binary_sensor.state == STATE_ON
with patch(
"pyuptimerobot.UptimeRobot.async_get_monitors",
side_effect=UptimeRobotAuthenticationException,
):
async_fire_time_changed(hass, dt.utcnow() + datetime.timedelta(seconds=10))
async_fire_time_changed(hass, dt.utcnow() + COORDINATOR_UPDATE_INTERVAL)
await hass.async_block_till_done()
flows = hass.config_entries.flow.async_progress()
binary_sensor = hass.states.get("binary_sensor.test_monitor")
assert hass.states.get(UPTIMEROBOT_TEST_ENTITY).state == STATE_UNAVAILABLE
assert binary_sensor.state == "unavailable"
assert "Authentication failed while fetching uptimerobot data" in caplog.text
assert len(flows) == 1
@ -105,3 +91,96 @@ async def test_reauthentication_trigger_after_setup(
assert flow["handler"] == DOMAIN
assert flow["context"]["source"] == config_entries.SOURCE_REAUTH
assert flow["context"]["entry_id"] == mock_config_entry.entry_id
async def test_integration_reload(hass: HomeAssistant):
"""Test integration reload."""
mock_entry = await setup_uptimerobot_integration(hass)
with patch(
"pyuptimerobot.UptimeRobot.async_get_monitors",
return_value=mock_uptimerobot_api_response(),
):
assert await hass.config_entries.async_reload(mock_entry.entry_id)
async_fire_time_changed(hass, dt.utcnow() + COORDINATOR_UPDATE_INTERVAL)
await hass.async_block_till_done()
entry = hass.config_entries.async_get_entry(mock_entry.entry_id)
assert entry.state == config_entries.ConfigEntryState.LOADED
assert hass.states.get(UPTIMEROBOT_TEST_ENTITY).state == STATE_ON
async def test_update_errors(hass: HomeAssistant, caplog: LogCaptureFixture):
"""Test errors during updates."""
await setup_uptimerobot_integration(hass)
with patch(
"pyuptimerobot.UptimeRobot.async_get_monitors",
side_effect=UptimeRobotException,
):
async_fire_time_changed(hass, dt.utcnow() + COORDINATOR_UPDATE_INTERVAL)
await hass.async_block_till_done()
assert hass.states.get(UPTIMEROBOT_TEST_ENTITY).state == STATE_UNAVAILABLE
with patch(
"pyuptimerobot.UptimeRobot.async_get_monitors",
return_value=mock_uptimerobot_api_response(),
):
async_fire_time_changed(hass, dt.utcnow() + COORDINATOR_UPDATE_INTERVAL)
await hass.async_block_till_done()
assert hass.states.get(UPTIMEROBOT_TEST_ENTITY).state == STATE_ON
with patch(
"pyuptimerobot.UptimeRobot.async_get_monitors",
return_value=mock_uptimerobot_api_response(key=MockApiResponseKey.ERROR),
):
async_fire_time_changed(hass, dt.utcnow() + COORDINATOR_UPDATE_INTERVAL)
await hass.async_block_till_done()
assert hass.states.get(UPTIMEROBOT_TEST_ENTITY).state == STATE_UNAVAILABLE
assert "Error fetching uptimerobot data: test error from API" in caplog.text
async def test_device_management(hass: HomeAssistant):
"""Test that we are adding and removing devices for monitors returned from the API."""
mock_entry = await setup_uptimerobot_integration(hass)
dev_reg = await async_get_registry(hass)
devices = async_entries_for_config_entry(dev_reg, mock_entry.entry_id)
assert len(devices) == 1
assert devices[0].identifiers == {(DOMAIN, "1234")}
assert hass.states.get(UPTIMEROBOT_TEST_ENTITY).state == STATE_ON
assert hass.states.get(f"{UPTIMEROBOT_TEST_ENTITY}_2") is None
with patch(
"pyuptimerobot.UptimeRobot.async_get_monitors",
return_value=mock_uptimerobot_api_response(
data=[MOCK_UPTIMEROBOT_MONITOR, {**MOCK_UPTIMEROBOT_MONITOR, "id": 12345}]
),
):
async_fire_time_changed(hass, dt.utcnow() + COORDINATOR_UPDATE_INTERVAL)
await hass.async_block_till_done()
devices = async_entries_for_config_entry(dev_reg, mock_entry.entry_id)
assert len(devices) == 2
assert devices[0].identifiers == {(DOMAIN, "1234")}
assert devices[1].identifiers == {(DOMAIN, "12345")}
assert hass.states.get(UPTIMEROBOT_TEST_ENTITY).state == STATE_ON
assert hass.states.get(f"{UPTIMEROBOT_TEST_ENTITY}_2").state == STATE_ON
with patch(
"pyuptimerobot.UptimeRobot.async_get_monitors",
return_value=mock_uptimerobot_api_response(),
):
async_fire_time_changed(hass, dt.utcnow() + COORDINATOR_UPDATE_INTERVAL)
await hass.async_block_till_done()
devices = async_entries_for_config_entry(dev_reg, mock_entry.entry_id)
assert len(devices) == 1
assert devices[0].identifiers == {(DOMAIN, "1234")}
assert hass.states.get(UPTIMEROBOT_TEST_ENTITY).state == STATE_ON
assert hass.states.get(f"{UPTIMEROBOT_TEST_ENTITY}_2") is None