Refactor nest test_init_sdm tests to use fixtures with varied config types (#64736)

This commit is contained in:
Allen Porter 2022-01-22 20:56:03 -08:00 committed by GitHub
parent 15532c38d7
commit cdf7742c3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 373 additions and 188 deletions

View File

@ -1,7 +1,9 @@
"""Common libraries for test setup."""
from collections.abc import Awaitable, Callable
from dataclasses import dataclass
import time
from typing import Any, Generator, TypeVar
from unittest.mock import patch
from google_nest_sdm.device_manager import DeviceManager
@ -15,17 +17,22 @@ from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry
# Typing helpers
PlatformSetup = Callable[[], Awaitable[None]]
T = TypeVar("T")
YieldFixture = Generator[T, None, None]
PROJECT_ID = "some-project-id"
CLIENT_ID = "some-client-id"
CLIENT_SECRET = "some-client-secret"
SUBSCRIBER_ID = "projects/example/subscriptions/subscriber-id-9876"
CONFIG = {
"nest": {
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
# Required fields for using SDM API
"project_id": PROJECT_ID,
"subscriber_id": "projects/example/subscriptions/subscriber-id-9876",
"subscriber_id": SUBSCRIBER_ID,
},
}
@ -33,24 +40,64 @@ FAKE_TOKEN = "some-token"
FAKE_REFRESH_TOKEN = "some-refresh-token"
def create_config_entry(hass, token_expiration_time=None) -> MockConfigEntry:
"""Create a ConfigEntry and add it to Home Assistant."""
def create_token_entry(token_expiration_time=None):
"""Create OAuth 'token' data for a ConfigEntry."""
if token_expiration_time is None:
token_expiration_time = time.time() + 86400
return {
"access_token": FAKE_TOKEN,
"refresh_token": FAKE_REFRESH_TOKEN,
"scope": " ".join(SDM_SCOPES),
"token_type": "Bearer",
"expires_at": token_expiration_time,
}
def create_config_entry(token_expiration_time=None) -> MockConfigEntry:
"""Create a ConfigEntry and add it to Home Assistant."""
config_entry_data = {
"sdm": {}, # Indicates new SDM API, not legacy API
"auth_implementation": "nest",
"token": {
"access_token": FAKE_TOKEN,
"refresh_token": FAKE_REFRESH_TOKEN,
"scope": " ".join(SDM_SCOPES),
"token_type": "Bearer",
"expires_at": token_expiration_time,
},
"token": create_token_entry(token_expiration_time),
}
config_entry = MockConfigEntry(domain=DOMAIN, data=config_entry_data)
config_entry.add_to_hass(hass)
return config_entry
return MockConfigEntry(domain=DOMAIN, data=config_entry_data)
@dataclass
class NestTestConfig:
"""Holder for integration configuration."""
config: dict[str, Any]
config_entry_data: dict[str, Any]
# Exercises mode where all configuration is in configuration.yaml
TEST_CONFIG_YAML_ONLY = NestTestConfig(
config=CONFIG,
config_entry_data={
"sdm": {},
"auth_implementation": "nest",
"token": create_token_entry(),
},
)
# Exercises mode where subscriber id is created in the config flow, but
# all authentication is defined in configuration.yaml
TEST_CONFIG_HYBRID = NestTestConfig(
config={
"nest": {
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"project_id": PROJECT_ID,
},
},
config_entry_data={
"sdm": {},
"auth_implementation": "nest",
"token": create_token_entry(),
"subscriber_id": SUBSCRIBER_ID,
},
)
class FakeSubscriber(GoogleNestSubscriber):
@ -100,7 +147,7 @@ async def async_setup_sdm_platform(
):
"""Set up the platform and prerequisites."""
if with_config:
create_config_entry(hass)
create_config_entry().add_to_hass(hass)
subscriber = FakeSubscriber()
device_manager = await subscriber.async_get_device_manager()
if devices:

View File

@ -1,13 +1,34 @@
"""Common libraries for test setup."""
from __future__ import annotations
import copy
import shutil
from typing import Any
from unittest.mock import patch
import uuid
import aiohttp
from google_nest_sdm.auth import AbstractAuth
from google_nest_sdm.device_manager import DeviceManager
import pytest
from homeassistant.components.nest import DOMAIN
from homeassistant.components.nest.const import CONF_SUBSCRIBER_ID
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from .common import (
SUBSCRIBER_ID,
TEST_CONFIG_HYBRID,
TEST_CONFIG_YAML_ONLY,
FakeSubscriber,
NestTestConfig,
PlatformSetup,
YieldFixture,
)
from tests.common import MockConfigEntry
class FakeAuth(AbstractAuth):
"""A fake implementation of the auth class that records requests.
@ -76,3 +97,100 @@ def cleanup_media_storage(hass):
with patch("homeassistant.components.nest.media_source.MEDIA_PATH", new=tmp_path):
yield
shutil.rmtree(hass.config.path(tmp_path), ignore_errors=True)
@pytest.fixture
def subscriber() -> YieldFixture[FakeSubscriber]:
"""Set up the FakeSusbcriber."""
subscriber = FakeSubscriber()
with patch(
"homeassistant.components.nest.api.GoogleNestSubscriber",
return_value=subscriber,
):
yield subscriber
@pytest.fixture
async def device_manager(subscriber: FakeSubscriber) -> DeviceManager:
"""Set up the DeviceManager."""
return await subscriber.async_get_device_manager()
@pytest.fixture
def platforms() -> list[str]:
"""Fixture to specify platforms to test."""
return []
@pytest.fixture
def subscriber_id() -> str:
"""Fixture to let tests override subscriber id regardless of configuration type used."""
return SUBSCRIBER_ID
@pytest.fixture(
params=[TEST_CONFIG_YAML_ONLY, TEST_CONFIG_HYBRID],
ids=["yaml-config-only", "hybrid-config"],
)
def nest_test_config(request) -> NestTestConfig:
"""Fixture that sets up the configuration used for the test."""
return request.param
@pytest.fixture
def config(
subscriber_id: str | None, nest_test_config: NestTestConfig
) -> dict[str, Any]:
"""Fixture that sets up the configuration.yaml for the test."""
config = copy.deepcopy(nest_test_config.config)
if CONF_SUBSCRIBER_ID in config.get(DOMAIN, {}):
if subscriber_id:
config[DOMAIN][CONF_SUBSCRIBER_ID] = subscriber_id
else:
del config[DOMAIN][CONF_SUBSCRIBER_ID]
return config
@pytest.fixture
def config_entry(
subscriber_id: str | None, nest_test_config: NestTestConfig
) -> MockConfigEntry | None:
"""Fixture that sets up the ConfigEntry for the test."""
if nest_test_config.config_entry_data is None:
return None
data = copy.deepcopy(nest_test_config.config_entry_data)
if CONF_SUBSCRIBER_ID in data:
if subscriber_id:
data[CONF_SUBSCRIBER_ID] = subscriber_id
else:
del data[CONF_SUBSCRIBER_ID]
return MockConfigEntry(domain=DOMAIN, data=data)
@pytest.fixture
async def setup_base_platform(
hass: HomeAssistant,
platforms: list[str],
config: dict[str, Any],
config_entry: MockConfigEntry | None,
) -> YieldFixture[PlatformSetup]:
"""Fixture to setup the integration platform."""
if config_entry:
config_entry.add_to_hass(hass)
with patch(
"homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation"
), patch("homeassistant.components.nest.PLATFORMS", platforms):
async def _setup_func() -> bool:
assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
yield _setup_func
@pytest.fixture
async def setup_platform(
setup_base_platform: PlatformSetup, subscriber: FakeSubscriber
) -> PlatformSetup:
"""Fixture to setup the integration platform and subscriber."""
return setup_base_platform

View File

@ -39,7 +39,7 @@ async def test_auth(hass, aioclient_mock):
"""Exercise authentication library creates valid credentials."""
expiration_time = time.time() + 86400
create_config_entry(hass, expiration_time)
create_config_entry(expiration_time).add_to_hass(hass)
# Prepare to capture credentials in API request. Empty payloads just mean
# no devices or structures are loaded.
@ -88,7 +88,7 @@ async def test_auth_expired_token(hass, aioclient_mock):
"""Verify behavior of an expired token."""
expiration_time = time.time() - 86400
create_config_entry(hass, expiration_time)
create_config_entry(expiration_time).add_to_hass(hass)
# Prepare a token refresh response
aioclient_mock.post(

View File

@ -70,7 +70,8 @@ async def test_entry_diagnostics(hass, hass_client):
async def test_setup_susbcriber_failure(hass, hass_client):
"""Test configuration error."""
config_entry = create_config_entry(hass)
config_entry = create_config_entry()
config_entry.add_to_hass(hass)
with patch(
"homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation"
), patch(

View File

@ -3,10 +3,14 @@ Test for setup methods for the SDM API.
The tests fake out the subscriber/devicemanager and simulate setup behavior
and failure modes.
By default all tests use test fixtures that run in each possible configuration
mode (e.g. yaml, ConfigEntry, etc) however some tests override and just run in
relevant modes.
"""
import copy
import logging
from typing import Any
from unittest.mock import patch
from google_nest_sdm.exceptions import (
@ -15,44 +19,75 @@ from google_nest_sdm.exceptions import (
ConfigurationException,
SubscriberException,
)
import pytest
from homeassistant.components.nest import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.setup import async_setup_component
from .common import CONFIG, async_setup_sdm_platform, create_config_entry
from .common import (
TEST_CONFIG_HYBRID,
TEST_CONFIG_YAML_ONLY,
FakeSubscriber,
NestTestConfig,
YieldFixture,
)
PLATFORM = "sensor"
async def test_setup_success(hass, caplog):
"""Test successful setup."""
@pytest.fixture
def platforms() -> list[str]:
"""Fixture to setup the platforms to test."""
return ["sensor"]
@pytest.fixture
def error_caplog(caplog):
"""Fixture to capture nest init error messages."""
with caplog.at_level(logging.ERROR, logger="homeassistant.components.nest"):
await async_setup_sdm_platform(hass, PLATFORM)
assert not caplog.records
yield caplog
@pytest.fixture
def warning_caplog(caplog):
"""Fixture to capture nest init warning messages."""
with caplog.at_level(logging.WARNING, logger="homeassistant.components.nest"):
yield caplog
@pytest.fixture
def subscriber_side_effect() -> None:
"""Fixture to inject failures into FakeSubscriber start."""
return None
@pytest.fixture
def failing_subscriber(subscriber_side_effect: Any) -> YieldFixture[FakeSubscriber]:
"""Fixture overriding default subscriber behavior to allow failure injection."""
subscriber = FakeSubscriber()
with patch(
"homeassistant.components.nest.api.GoogleNestSubscriber.start_async",
side_effect=subscriber_side_effect,
):
yield subscriber
async def test_setup_success(hass, error_caplog, setup_platform):
"""Test successful setup."""
await setup_platform()
assert not error_caplog.records
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
assert entries[0].state is ConfigEntryState.LOADED
async def async_setup_sdm(hass, config=CONFIG, with_config=True):
"""Prepare test setup."""
if with_config:
create_config_entry(hass)
with patch(
"homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation"
):
return await async_setup_component(hass, DOMAIN, config)
async def test_setup_configuration_failure(hass, caplog):
@pytest.mark.parametrize("subscriber_id", [("invalid-subscriber-format")])
async def test_setup_configuration_failure(
hass, caplog, subscriber_id, setup_base_platform
):
"""Test configuration error."""
config = copy.deepcopy(CONFIG)
config[DOMAIN]["subscriber_id"] = "invalid-subscriber-format"
result = await async_setup_sdm(hass, config)
assert result
await setup_base_platform()
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
@ -63,49 +98,43 @@ async def test_setup_configuration_failure(hass, caplog):
assert "Subscription misconfigured. Expected subscriber_id" in caplog.text
async def test_setup_susbcriber_failure(hass, caplog):
@pytest.mark.parametrize("subscriber_side_effect", [SubscriberException()])
async def test_setup_susbcriber_failure(
hass, error_caplog, failing_subscriber, setup_base_platform
):
"""Test configuration error."""
with patch(
"homeassistant.components.nest.api.GoogleNestSubscriber.start_async",
side_effect=SubscriberException(),
), caplog.at_level(logging.ERROR, logger="homeassistant.components.nest"):
result = await async_setup_sdm(hass)
assert result
assert "Subscriber error:" in caplog.text
await setup_base_platform()
assert "Subscriber error:" in error_caplog.text
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
assert entries[0].state is ConfigEntryState.SETUP_RETRY
async def test_setup_device_manager_failure(hass, caplog):
"""Test configuration error."""
async def test_setup_device_manager_failure(hass, error_caplog, setup_base_platform):
"""Test device manager api failure."""
with patch(
"homeassistant.components.nest.api.GoogleNestSubscriber.start_async"
), patch(
"homeassistant.components.nest.api.GoogleNestSubscriber.async_get_device_manager",
side_effect=ApiException(),
), caplog.at_level(
logging.ERROR, logger="homeassistant.components.nest"
):
result = await async_setup_sdm(hass)
assert result
assert len(caplog.messages) == 1
assert "Device manager error:" in caplog.text
await setup_base_platform()
assert len(error_caplog.messages) == 1
assert "Device manager error:" in error_caplog.text
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
assert entries[0].state is ConfigEntryState.SETUP_RETRY
async def test_subscriber_auth_failure(hass, caplog):
"""Test configuration error."""
with patch(
"homeassistant.components.nest.api.GoogleNestSubscriber.start_async",
side_effect=AuthException(),
):
result = await async_setup_sdm(hass, CONFIG)
assert result
@pytest.mark.parametrize("subscriber_side_effect", [AuthException()])
async def test_subscriber_auth_failure(
hass, caplog, setup_base_platform, failing_subscriber
):
"""Test subscriber throws an authentication error."""
await setup_base_platform()
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
@ -116,70 +145,45 @@ async def test_subscriber_auth_failure(hass, caplog):
assert flows[0]["step_id"] == "reauth_confirm"
async def test_setup_missing_subscriber_id(hass, caplog):
"""Test missing susbcriber id from config and config entry."""
config = copy.deepcopy(CONFIG)
del config[DOMAIN]["subscriber_id"]
with caplog.at_level(logging.WARNING, logger="homeassistant.components.nest"):
result = await async_setup_sdm(hass, config)
assert result
assert "Configuration option" in caplog.text
@pytest.mark.parametrize("subscriber_id", [(None)])
async def test_setup_missing_subscriber_id(hass, warning_caplog, setup_base_platform):
"""Test missing susbcriber id from configuration."""
await setup_base_platform()
assert "Configuration option" in warning_caplog.text
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
assert entries[0].state is ConfigEntryState.SETUP_ERROR
async def test_setup_subscriber_id_config_entry(hass, caplog):
"""Test successful setup with subscriber id in ConfigEntry."""
config = copy.deepcopy(CONFIG)
subscriber_id = config[DOMAIN]["subscriber_id"]
del config[DOMAIN]["subscriber_id"]
config_entry = create_config_entry(hass)
data = {**config_entry.data}
data["subscriber_id"] = subscriber_id
hass.config_entries.async_update_entry(config_entry, data=data)
with caplog.at_level(logging.ERROR, logger="homeassistant.components.nest"):
await async_setup_sdm_platform(hass, PLATFORM, with_config=False)
assert not caplog.records
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
assert entries[0].state is ConfigEntryState.LOADED
async def test_subscriber_configuration_failure(hass, caplog):
@pytest.mark.parametrize("subscriber_side_effect", [(ConfigurationException())])
async def test_subscriber_configuration_failure(
hass, error_caplog, setup_base_platform, failing_subscriber
):
"""Test configuration error."""
with patch(
"homeassistant.components.nest.api.GoogleNestSubscriber.start_async",
side_effect=ConfigurationException(),
), caplog.at_level(logging.ERROR, logger="homeassistant.components.nest"):
result = await async_setup_sdm(hass, CONFIG)
assert result
assert "Configuration error: " in caplog.text
await setup_base_platform()
assert "Configuration error: " in error_caplog.text
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
assert entries[0].state is ConfigEntryState.SETUP_ERROR
async def test_empty_config(hass, caplog):
"""Test successful setup."""
with caplog.at_level(logging.ERROR, logger="homeassistant.components.nest"):
result = await async_setup_component(hass, DOMAIN, {})
assert result
assert not caplog.records
@pytest.mark.parametrize(
"nest_test_config", [NestTestConfig(config={}, config_entry_data=None)]
)
async def test_empty_config(hass, error_caplog, config, setup_platform):
"""Test setup is a no-op with not config."""
await setup_platform()
assert not error_caplog.records
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 0
async def test_unload_entry(hass, caplog):
async def test_unload_entry(hass, setup_platform):
"""Test successful unload of a ConfigEntry."""
await async_setup_sdm_platform(hass, PLATFORM)
await setup_platform()
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
@ -190,33 +194,27 @@ async def test_unload_entry(hass, caplog):
assert entry.state == ConfigEntryState.NOT_LOADED
async def test_remove_entry(hass, caplog):
@pytest.mark.parametrize(
"nest_test_config,delete_called",
[
(
TEST_CONFIG_YAML_ONLY,
False,
), # User manually created subscriber, preserve on remove
(
TEST_CONFIG_HYBRID,
True,
), # Integration created subscriber, garbage collect on remove
],
ids=["yaml-config-only", "hybrid-config"],
)
async def test_remove_entry(hass, nest_test_config, setup_base_platform, delete_called):
"""Test successful unload of a ConfigEntry."""
await async_setup_sdm_platform(hass, PLATFORM)
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
entry = entries[0]
assert entry.state is ConfigEntryState.LOADED
assert await hass.config_entries.async_remove(entry.entry_id)
entries = hass.config_entries.async_entries(DOMAIN)
assert not entries
async def test_remove_entry_deletes_subscriber(hass, caplog):
"""Test ConfigEntry unload deletes a subscription."""
config = copy.deepcopy(CONFIG)
subscriber_id = config[DOMAIN]["subscriber_id"]
del config[DOMAIN]["subscriber_id"]
config_entry = create_config_entry(hass)
data = {**config_entry.data}
data["subscriber_id"] = subscriber_id
hass.config_entries.async_update_entry(config_entry, data=data)
await async_setup_sdm_platform(hass, PLATFORM, with_config=False)
with patch(
"homeassistant.components.nest.api.GoogleNestSubscriber",
return_value=FakeSubscriber(),
):
await setup_base_platform()
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
@ -224,27 +222,29 @@ async def test_remove_entry_deletes_subscriber(hass, caplog):
assert entry.state is ConfigEntryState.LOADED
with patch(
"homeassistant.components.nest.api.GoogleNestSubscriber.subscriber_id"
), patch(
"homeassistant.components.nest.api.GoogleNestSubscriber.delete_subscription",
) as delete:
assert await hass.config_entries.async_remove(entry.entry_id)
assert delete.called
assert delete.called == delete_called
entries = hass.config_entries.async_entries(DOMAIN)
assert not entries
async def test_remove_entry_delete_subscriber_failure(hass, caplog):
@pytest.mark.parametrize(
"nest_test_config", [TEST_CONFIG_HYBRID], ids=["hyrbid-config"]
)
async def test_remove_entry_delete_subscriber_failure(
hass, nest_test_config, setup_base_platform
):
"""Test a failure when deleting the subscription."""
config = copy.deepcopy(CONFIG)
subscriber_id = config[DOMAIN]["subscriber_id"]
del config[DOMAIN]["subscriber_id"]
config_entry = create_config_entry(hass)
data = {**config_entry.data}
data["subscriber_id"] = subscriber_id
hass.config_entries.async_update_entry(config_entry, data=data)
await async_setup_sdm_platform(hass, PLATFORM, with_config=False)
with patch(
"homeassistant.components.nest.api.GoogleNestSubscriber",
return_value=FakeSubscriber(),
):
await setup_base_platform()
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
@ -254,8 +254,9 @@ async def test_remove_entry_delete_subscriber_failure(hass, caplog):
with patch(
"homeassistant.components.nest.api.GoogleNestSubscriber.delete_subscription",
side_effect=SubscriberException(),
):
) as delete:
assert await hass.config_entries.async_remove(entry.entry_id)
assert delete.called
entries = hass.config_entries.async_entries(DOMAIN)
assert not entries

View File

@ -1043,7 +1043,8 @@ async def test_media_store_persistence(hass, auth, hass_client, event_store):
# Fetch media for events when published
subscriber.cache_policy.fetch = True
config_entry = create_config_entry(hass)
config_entry = create_config_entry()
config_entry.add_to_hass(hass)
with patch(
"homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation"

View File

@ -6,7 +6,9 @@ pubsub subscriber.
"""
from google_nest_sdm.device import Device
from google_nest_sdm.device_manager import DeviceManager
from google_nest_sdm.event import EventMessage
import pytest
from homeassistant.components.sensor import ATTR_STATE_CLASS, STATE_CLASS_MEASUREMENT
from homeassistant.const import (
@ -17,24 +19,26 @@ from homeassistant.const import (
PERCENTAGE,
TEMP_CELSIUS,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from .common import async_setup_sdm_platform
PLATFORM = "sensor"
from .common import FakeSubscriber, PlatformSetup
THERMOSTAT_TYPE = "sdm.devices.types.THERMOSTAT"
async def async_setup_sensor(hass, devices={}, structures={}):
"""Set up the platform and prerequisites."""
return await async_setup_sdm_platform(hass, PLATFORM, devices, structures)
@pytest.fixture
def platforms() -> list[str]:
"""Fixture to setup the platforms to test."""
return ["sensor"]
async def test_thermostat_device(hass):
async def test_thermostat_device(
hass: HomeAssistant, device_manager: DeviceManager, setup_platform: PlatformSetup
):
"""Test a thermostat with temperature and humidity sensors."""
devices = {
"some-device-id": Device.MakeDevice(
device_manager.add_device(
Device.MakeDevice(
{
"name": "some-device-id",
"type": THERMOSTAT_TYPE,
@ -52,8 +56,8 @@ async def test_thermostat_device(hass):
},
auth=None,
)
}
await async_setup_sensor(hass, devices)
)
await setup_platform()
temperature = hass.states.get("sensor.my_sensor_temperature")
assert temperature is not None
@ -87,9 +91,9 @@ async def test_thermostat_device(hass):
assert device.identifiers == {("nest", "some-device-id")}
async def test_no_devices(hass):
async def test_no_devices(hass: HomeAssistant, setup_platform: PlatformSetup):
"""Test no devices returned by the api."""
await async_setup_sensor(hass)
await setup_platform()
temperature = hass.states.get("sensor.my_sensor_temperature")
assert temperature is None
@ -98,10 +102,12 @@ async def test_no_devices(hass):
assert humidity is None
async def test_device_no_sensor_traits(hass):
async def test_device_no_sensor_traits(
hass: HomeAssistant, device_manager: DeviceManager, setup_platform: PlatformSetup
) -> None:
"""Test a device with applicable sensor traits."""
devices = {
"some-device-id": Device.MakeDevice(
device_manager.add_device(
Device.MakeDevice(
{
"name": "some-device-id",
"type": THERMOSTAT_TYPE,
@ -109,8 +115,8 @@ async def test_device_no_sensor_traits(hass):
},
auth=None,
)
}
await async_setup_sensor(hass, devices)
)
await setup_platform()
temperature = hass.states.get("sensor.my_sensor_temperature")
assert temperature is None
@ -119,10 +125,12 @@ async def test_device_no_sensor_traits(hass):
assert humidity is None
async def test_device_name_from_structure(hass):
async def test_device_name_from_structure(
hass: HomeAssistant, device_manager: DeviceManager, setup_platform: PlatformSetup
) -> None:
"""Test a device without a custom name, inferring name from structure."""
devices = {
"some-device-id": Device.MakeDevice(
device_manager.add_device(
Device.MakeDevice(
{
"name": "some-device-id",
"type": THERMOSTAT_TYPE,
@ -137,18 +145,23 @@ async def test_device_name_from_structure(hass):
},
auth=None,
)
}
await async_setup_sensor(hass, devices)
)
await setup_platform()
temperature = hass.states.get("sensor.some_room_temperature")
assert temperature is not None
assert temperature.state == "25.2"
async def test_event_updates_sensor(hass):
async def test_event_updates_sensor(
hass: HomeAssistant,
subscriber: FakeSubscriber,
device_manager: DeviceManager,
setup_platform: PlatformSetup,
) -> None:
"""Test a pubsub message received by subscriber to update temperature."""
devices = {
"some-device-id": Device.MakeDevice(
device_manager.add_device(
Device.MakeDevice(
{
"name": "some-device-id",
"type": THERMOSTAT_TYPE,
@ -163,8 +176,8 @@ async def test_event_updates_sensor(hass):
},
auth=None,
)
}
subscriber = await async_setup_sensor(hass, devices)
)
await setup_platform()
temperature = hass.states.get("sensor.my_sensor_temperature")
assert temperature is not None
@ -194,10 +207,12 @@ async def test_event_updates_sensor(hass):
assert temperature.state == "26.2"
async def test_device_with_unknown_type(hass):
async def test_device_with_unknown_type(
hass: HomeAssistant, device_manager: DeviceManager, setup_platform: PlatformSetup
) -> None:
"""Test a device without a custom name, inferring name from structure."""
devices = {
"some-device-id": Device.MakeDevice(
device_manager.add_device(
Device.MakeDevice(
{
"name": "some-device-id",
"type": "some-unknown-type",
@ -212,8 +227,8 @@ async def test_device_with_unknown_type(hass):
},
auth=None,
)
}
await async_setup_sensor(hass, devices)
)
await setup_platform()
temperature = hass.states.get("sensor.my_sensor_temperature")
assert temperature is not None
@ -232,10 +247,12 @@ async def test_device_with_unknown_type(hass):
assert device.identifiers == {("nest", "some-device-id")}
async def test_temperature_rounding(hass):
async def test_temperature_rounding(
hass: HomeAssistant, device_manager: DeviceManager, setup_platform: PlatformSetup
) -> None:
"""Test the rounding of overly precise temperatures."""
devices = {
"some-device-id": Device.MakeDevice(
device_manager.add_device(
Device.MakeDevice(
{
"name": "some-device-id",
"type": THERMOSTAT_TYPE,
@ -250,8 +267,8 @@ async def test_temperature_rounding(hass):
},
auth=None,
)
}
await async_setup_sensor(hass, devices)
)
await setup_platform()
temperature = hass.states.get("sensor.my_sensor_temperature")
assert temperature.state == "25.2"