core/tests/components/withings/conftest.py

351 lines
12 KiB
Python

"""Fixtures for withings tests."""
import time
from typing import Awaitable, Callable, List
import asynctest
import withings_api as withings
import pytest
import homeassistant.components.api as api
import homeassistant.components.http as http
import homeassistant.components.withings.const as const
from homeassistant.components.withings import CONFIG_SCHEMA, DOMAIN
from homeassistant.config import async_process_ha_core_config
from homeassistant.const import CONF_UNIT_SYSTEM, CONF_UNIT_SYSTEM_METRIC
from homeassistant.setup import async_setup_component
from .common import (
WITHINGS_MEASURES_RESPONSE,
WITHINGS_SLEEP_RESPONSE,
WITHINGS_SLEEP_SUMMARY_RESPONSE,
)
class WithingsFactoryConfig:
"""Configuration for withings test fixture."""
PROFILE_1 = "Person 1"
PROFILE_2 = "Person 2"
def __init__(
self,
api_config: dict = None,
http_config: dict = None,
measures: List[str] = None,
unit_system: str = None,
throttle_interval: int = const.THROTTLE_INTERVAL,
withings_request_response="DATA",
withings_measures_response: withings.WithingsMeasures = WITHINGS_MEASURES_RESPONSE,
withings_sleep_response: withings.WithingsSleep = WITHINGS_SLEEP_RESPONSE,
withings_sleep_summary_response: withings.WithingsSleepSummary = WITHINGS_SLEEP_SUMMARY_RESPONSE,
) -> None:
"""Constructor."""
self._throttle_interval = throttle_interval
self._withings_request_response = withings_request_response
self._withings_measures_response = withings_measures_response
self._withings_sleep_response = withings_sleep_response
self._withings_sleep_summary_response = withings_sleep_summary_response
self._withings_config = {
const.CLIENT_ID: "my_client_id",
const.CLIENT_SECRET: "my_client_secret",
const.PROFILES: [
WithingsFactoryConfig.PROFILE_1,
WithingsFactoryConfig.PROFILE_2,
],
}
self._api_config = api_config or {"base_url": "http://localhost/"}
self._http_config = http_config or {}
self._measures = measures
assert self._withings_config, "withings_config must be set."
assert isinstance(
self._withings_config, dict
), "withings_config must be a dict."
assert isinstance(self._api_config, dict), "api_config must be a dict."
assert isinstance(self._http_config, dict), "http_config must be a dict."
self._hass_config = {
"homeassistant": {CONF_UNIT_SYSTEM: unit_system or CONF_UNIT_SYSTEM_METRIC},
api.DOMAIN: self._api_config,
http.DOMAIN: self._http_config,
DOMAIN: self._withings_config,
}
@property
def withings_config(self):
"""Get withings component config."""
return self._withings_config
@property
def api_config(self):
"""Get api component config."""
return self._api_config
@property
def http_config(self):
"""Get http component config."""
return self._http_config
@property
def measures(self):
"""Get the measures."""
return self._measures
@property
def hass_config(self):
"""Home assistant config."""
return self._hass_config
@property
def throttle_interval(self):
"""Throttle interval."""
return self._throttle_interval
@property
def withings_request_response(self):
"""Request response."""
return self._withings_request_response
@property
def withings_measures_response(self) -> withings.WithingsMeasures:
"""Measures response."""
return self._withings_measures_response
@property
def withings_sleep_response(self) -> withings.WithingsSleep:
"""Sleep response."""
return self._withings_sleep_response
@property
def withings_sleep_summary_response(self) -> withings.WithingsSleepSummary:
"""Sleep summary response."""
return self._withings_sleep_summary_response
class WithingsFactoryData:
"""Data about the configured withing test component."""
def __init__(
self,
hass,
flow_id,
withings_auth_get_credentials_mock,
withings_api_request_mock,
withings_api_get_measures_mock,
withings_api_get_sleep_mock,
withings_api_get_sleep_summary_mock,
data_manager_get_throttle_interval_mock,
):
"""Constructor."""
self._hass = hass
self._flow_id = flow_id
self._withings_auth_get_credentials_mock = withings_auth_get_credentials_mock
self._withings_api_request_mock = withings_api_request_mock
self._withings_api_get_measures_mock = withings_api_get_measures_mock
self._withings_api_get_sleep_mock = withings_api_get_sleep_mock
self._withings_api_get_sleep_summary_mock = withings_api_get_sleep_summary_mock
self._data_manager_get_throttle_interval_mock = (
data_manager_get_throttle_interval_mock
)
@property
def hass(self):
"""Get hass instance."""
return self._hass
@property
def flow_id(self):
"""Get flow id."""
return self._flow_id
@property
def withings_auth_get_credentials_mock(self):
"""Get auth credentials mock."""
return self._withings_auth_get_credentials_mock
@property
def withings_api_request_mock(self):
"""Get request mock."""
return self._withings_api_request_mock
@property
def withings_api_get_measures_mock(self):
"""Get measures mock."""
return self._withings_api_get_measures_mock
@property
def withings_api_get_sleep_mock(self):
"""Get sleep mock."""
return self._withings_api_get_sleep_mock
@property
def withings_api_get_sleep_summary_mock(self):
"""Get sleep summary mock."""
return self._withings_api_get_sleep_summary_mock
@property
def data_manager_get_throttle_interval_mock(self):
"""Get throttle mock."""
return self._data_manager_get_throttle_interval_mock
async def configure_user(self):
"""Present a form with user profiles."""
step = await self.hass.config_entries.flow.async_configure(self.flow_id, None)
assert step["step_id"] == "user"
async def configure_profile(self, profile: str):
"""Select the user profile. Present a form with authorization link."""
print("CONFIG_PROFILE:", profile)
step = await self.hass.config_entries.flow.async_configure(
self.flow_id, {const.PROFILE: profile}
)
assert step["step_id"] == "auth"
async def configure_code(self, profile: str, code: str):
"""Handle authorization code. Create config entries."""
step = await self.hass.config_entries.flow.async_configure(
self.flow_id, {const.PROFILE: profile, const.CODE: code}
)
assert step["type"] == "external_done"
await self.hass.async_block_till_done()
step = await self.hass.config_entries.flow.async_configure(
self.flow_id, {const.PROFILE: profile, const.CODE: code}
)
assert step["type"] == "create_entry"
await self.hass.async_block_till_done()
async def configure_all(self, profile: str, code: str):
"""Configure all flow steps."""
await self.configure_user()
await self.configure_profile(profile)
await self.configure_code(profile, code)
WithingsFactory = Callable[[WithingsFactoryConfig], Awaitable[WithingsFactoryData]]
@pytest.fixture(name="withings_factory")
def withings_factory_fixture(request, hass) -> WithingsFactory:
"""Home assistant platform fixture."""
patches = []
async def factory(config: WithingsFactoryConfig) -> WithingsFactoryData:
CONFIG_SCHEMA(config.hass_config.get(DOMAIN))
await async_process_ha_core_config(
hass, config.hass_config.get("homeassistant")
)
assert await async_setup_component(hass, http.DOMAIN, config.hass_config)
assert await async_setup_component(hass, api.DOMAIN, config.hass_config)
withings_auth_get_credentials_patch = asynctest.patch(
"withings_api.WithingsAuth.get_credentials",
return_value=withings.WithingsCredentials(
access_token="my_access_token",
token_expiry=time.time() + 600,
token_type="my_token_type",
refresh_token="my_refresh_token",
user_id="my_user_id",
client_id=config.withings_config.get(const.CLIENT_ID),
consumer_secret=config.withings_config.get(const.CLIENT_SECRET),
),
)
withings_auth_get_credentials_mock = withings_auth_get_credentials_patch.start()
withings_api_request_patch = asynctest.patch(
"withings_api.WithingsApi.request",
return_value=config.withings_request_response,
)
withings_api_request_mock = withings_api_request_patch.start()
withings_api_get_measures_patch = asynctest.patch(
"withings_api.WithingsApi.get_measures",
return_value=config.withings_measures_response,
)
withings_api_get_measures_mock = withings_api_get_measures_patch.start()
withings_api_get_sleep_patch = asynctest.patch(
"withings_api.WithingsApi.get_sleep",
return_value=config.withings_sleep_response,
)
withings_api_get_sleep_mock = withings_api_get_sleep_patch.start()
withings_api_get_sleep_summary_patch = asynctest.patch(
"withings_api.WithingsApi.get_sleep_summary",
return_value=config.withings_sleep_summary_response,
)
withings_api_get_sleep_summary_mock = (
withings_api_get_sleep_summary_patch.start()
)
data_manager_get_throttle_interval_patch = asynctest.patch(
"homeassistant.components.withings.common.WithingsDataManager"
".get_throttle_interval",
return_value=config.throttle_interval,
)
data_manager_get_throttle_interval_mock = (
data_manager_get_throttle_interval_patch.start()
)
get_measures_patch = asynctest.patch(
"homeassistant.components.withings.sensor.get_measures",
return_value=config.measures,
)
get_measures_patch.start()
patches.extend(
[
withings_auth_get_credentials_patch,
withings_api_request_patch,
withings_api_get_measures_patch,
withings_api_get_sleep_patch,
withings_api_get_sleep_summary_patch,
data_manager_get_throttle_interval_patch,
get_measures_patch,
]
)
# Collect the flow id.
tasks = []
orig_async_create_task = hass.async_create_task
def create_task(*args):
task = orig_async_create_task(*args)
tasks.append(task)
return task
async_create_task_patch = asynctest.patch.object(
hass, "async_create_task", side_effect=create_task
)
with async_create_task_patch:
assert await async_setup_component(hass, DOMAIN, config.hass_config)
await hass.async_block_till_done()
flow_id = tasks[2].result()["flow_id"]
return WithingsFactoryData(
hass,
flow_id,
withings_auth_get_credentials_mock,
withings_api_request_mock,
withings_api_get_measures_mock,
withings_api_get_sleep_mock,
withings_api_get_sleep_summary_mock,
data_manager_get_throttle_interval_mock,
)
def cleanup():
for patch in patches:
patch.stop()
request.addfinalizer(cleanup)
return factory