1
0
mirror of https://github.com/home-assistant/core.git synced 2026-05-15 13:01:22 +01:00
Files
core/tests/components/scrape/test_init.py
T
2026-04-15 09:59:12 +02:00

334 lines
11 KiB
Python

"""Test Scrape component setup process."""
from __future__ import annotations
from dataclasses import dataclass
from http import HTTPStatus
from typing import Any
from unittest.mock import patch
from freezegun.api import FrozenDateTimeFactory
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.scrape.const import DEFAULT_SCAN_INTERVAL, DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.config_entries import SOURCE_USER, ConfigEntryState, ConfigSubentry
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
from . import MockRestData, return_integration_config
from tests.common import MockConfigEntry, async_fire_time_changed
from tests.test_util.aiohttp import AiohttpClientMocker
from tests.typing import WebSocketGenerator
async def test_setup_config(hass: HomeAssistant) -> None:
"""Test setup from yaml."""
config = {
DOMAIN: [
return_integration_config(
sensors=[{"select": ".current-version h1", "name": "HA version"}]
)
]
}
mocker = MockRestData("test_scrape_sensor")
with patch(
"homeassistant.components.rest.RestData",
return_value=mocker,
) as mock_setup:
assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
state = hass.states.get("sensor.ha_version")
assert state.state == "Current Version: 2021.12.10"
assert len(mock_setup.mock_calls) == 1
async def test_setup_no_data_fails_with_recovery(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test setup entry no data fails and recovers."""
config = {
DOMAIN: [
return_integration_config(
sensors=[{"select": ".current-version h1", "name": "HA version"}]
),
]
}
mocker = MockRestData("test_scrape_sensor_no_data")
with patch(
"homeassistant.components.rest.RestData",
return_value=mocker,
):
assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
state = hass.states.get("sensor.ha_version")
assert state is None
assert "Platform scrape not ready yet" in caplog.text
mocker.payload = "test_scrape_sensor"
async_fire_time_changed(hass, dt_util.utcnow() + DEFAULT_SCAN_INTERVAL)
await hass.async_block_till_done()
state = hass.states.get("sensor.ha_version")
assert state.state == "Current Version: 2021.12.10"
async def test_setup_config_no_configuration(
hass: HomeAssistant, entity_registry: er.EntityRegistry
) -> None:
"""Test setup from yaml missing configuration options."""
config = {DOMAIN: None}
assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
assert entity_registry.entities == {}
async def test_setup_config_no_sensors(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test setup from yaml with no configured sensors finalize properly."""
config = {
DOMAIN: [
{
"resource": "https://www.address.com",
"verify_ssl": True,
},
{
"resource": "https://www.address2.com",
"verify_ssl": True,
"sensor": None,
},
]
}
mocker = MockRestData("test_scrape_sensor")
with patch(
"homeassistant.components.rest.RestData",
return_value=mocker,
):
assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
async def test_setup_entry(hass: HomeAssistant, loaded_entry: MockConfigEntry) -> None:
"""Test setup entry."""
assert loaded_entry.state is ConfigEntryState.LOADED
async def test_unload_entry(hass: HomeAssistant, loaded_entry: MockConfigEntry) -> None:
"""Test unload an entry."""
assert loaded_entry.state is ConfigEntryState.LOADED
assert await hass.config_entries.async_unload(loaded_entry.entry_id)
await hass.async_block_till_done()
assert loaded_entry.state is ConfigEntryState.NOT_LOADED
async def test_device_remove_devices(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
loaded_entry: MockConfigEntry,
hass_ws_client: WebSocketGenerator,
) -> None:
"""Test we can only remove a device that no longer exists."""
assert await async_setup_component(hass, "config", {})
entity = entity_registry.entities["sensor.current_version"]
device_entry = device_registry.async_get(entity.device_id)
client = await hass_ws_client(hass)
response = await client.remove_device(device_entry.id, loaded_entry.entry_id)
assert not response["success"]
dead_device_entry = device_registry.async_get_or_create(
config_entry_id=loaded_entry.entry_id,
identifiers={(DOMAIN, "remove-device-id")},
)
response = await client.remove_device(dead_device_entry.id, loaded_entry.entry_id)
assert response["success"]
async def test_resource_template(
hass: HomeAssistant,
aioclient_mock: AiohttpClientMocker,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test resource_template is evaluated on each scan."""
hass.states.async_set("sensor.input_sensor", "localhost")
aioclient_mock.get(
"http://localhost",
status=HTTPStatus.OK,
text="<h1>First</h1>",
)
aioclient_mock.get(
"http://localhost2",
status=HTTPStatus.OK,
text="<h1>Second</h1>",
)
config = {
DOMAIN: {
"resource_template": "http://{{ states.sensor.input_sensor.state }}",
"verify_ssl": True,
"sensor": [{"select": "h1", "name": "template sensor"}],
}
}
assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done(wait_background_tasks=True)
state = hass.states.get("sensor.template_sensor")
assert state.state == "First"
hass.states.async_set("sensor.input_sensor", "localhost2")
freezer.tick(DEFAULT_SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
state = hass.states.get("sensor.template_sensor")
assert state.state == "Second"
async def test_migrate_from_future(
hass: HomeAssistant,
get_resource_config: dict[str, Any],
get_sensor_config: tuple[dict[str, Any], ...],
get_data: MockRestData,
) -> None:
"""Test migration from future version fails."""
config_entry = MockConfigEntry(
domain=DOMAIN,
source=SOURCE_USER,
options=get_resource_config,
entry_id="01JZN04ZJ9BQXXGXDS05WS7D6P",
subentries_data=get_sensor_config,
version=3,
)
config_entry.add_to_hass(hass)
with patch(
"homeassistant.components.rest.RestData",
return_value=get_data,
):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.MIGRATION_ERROR
async def test_migrate_from_version_1_to_2(
hass: HomeAssistant,
get_data: MockRestData,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
) -> None:
"""Test migration from version 1.1 to 2.1 with config subentries."""
@dataclass(frozen=True, kw_only=True)
class MockConfigSubentry(ConfigSubentry):
"""Container for a configuration subentry."""
subentry_id: str = "01JZQ1G63X2DX66GZ9ZTFY9PEH"
config_entry = MockConfigEntry(
domain=DOMAIN,
source=SOURCE_USER,
options={
"encoding": "UTF-8",
"method": "GET",
"resource": "http://www.home-assistant.io",
"username": "user",
"password": "pass",
"sensor": [
{
"index": 0,
"name": "Current version",
"select": ".release-date",
"unique_id": "a0bde946-5c96-11f0-b55f-0242ac110002",
"value_template": "{{ value }}",
}
],
"timeout": 10.0,
"verify_ssl": True,
},
entry_id="01JZN04ZJ9BQXXGXDS05WS7D6P",
version=1,
)
config_entry.add_to_hass(hass)
device = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
entry_type=dr.DeviceEntryType.SERVICE,
identifiers={(DOMAIN, "a0bde946-5c96-11f0-b55f-0242ac110002")},
manufacturer="Scrape",
name="Current version",
)
entity_registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"a0bde946-5c96-11f0-b55f-0242ac110002",
config_entry=config_entry,
device_id=device.id,
original_name="Current version",
has_entity_name=True,
suggested_object_id="current_version",
)
assert hass.config_entries.async_get_entry(config_entry.entry_id) == snapshot(
name="pre_migration_config_entry"
)
with (
patch(
"homeassistant.components.rest.RestData",
return_value=get_data,
),
patch("homeassistant.components.scrape.ConfigSubentry", MockConfigSubentry),
):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done(wait_background_tasks=True)
assert config_entry.state is ConfigEntryState.LOADED
assert hass.config_entries.async_get_entry(config_entry.entry_id) == snapshot(
name="post_migration_config_entry"
)
device = device_registry.async_get(device.id)
assert device == snapshot(name="device_registry")
entity = entity_registry.async_get("sensor.current_version")
assert entity == snapshot(name="entity_registry")
assert config_entry.subentries == {
"01JZQ1G63X2DX66GZ9ZTFY9PEH": MockConfigSubentry(
data={
"advanced": {"value_template": "{{ value }}"},
"index": 0,
"select": ".release-date",
},
subentry_id="01JZQ1G63X2DX66GZ9ZTFY9PEH",
subentry_type="entity",
title="Current version",
unique_id=None,
),
}
assert device.config_entries == {"01JZN04ZJ9BQXXGXDS05WS7D6P"}
assert device.config_entries_subentries == {
"01JZN04ZJ9BQXXGXDS05WS7D6P": {
"01JZQ1G63X2DX66GZ9ZTFY9PEH",
},
}
assert entity.config_entry_id == config_entry.entry_id
assert entity.config_subentry_id == "01JZQ1G63X2DX66GZ9ZTFY9PEH"
state = hass.states.get("sensor.current_version")
assert state.state == "January 17, 2022"