Files

232 lines
7.8 KiB
Python

"""Test fixtures for Google Health."""
from collections.abc import Awaitable, Callable, Generator
import time
from typing import Any
from unittest.mock import AsyncMock, patch
from google_health_api.model import (
BODY_FAT,
DAILY_RESTING_HEART_RATE,
SLEEP,
WEIGHT,
ActiveEnergyBurnedRollupValue,
DailyRollupDataPoint,
DataPoint,
DataType,
DistanceRollupValue,
FloorsRollupValue,
HydrationLogRollupValue,
Identity,
ListDataPointResult,
ListPairedDevicesResult,
NutritionLogRollupValue,
StepsRollupValue,
TotalCaloriesRollupValue,
UserInfo,
_ListDataPointsModel,
_ListPairedDevicesModel,
)
import pytest
from homeassistant.components.application_credentials import (
DOMAIN as APPLICATION_CREDENTIALS_DOMAIN,
ClientCredential,
async_import_client_credential,
)
from homeassistant.components.google_health.const import DOMAIN, OAUTH_SCOPES
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry, load_json_object_fixture
CLIENT_ID = "1234"
CLIENT_SECRET = "5678"
FAKE_ACCESS_TOKEN = "some-access-token"
FAKE_REFRESH_TOKEN = "some-refresh-token"
HEALTH_USER_ID = "mock-health-user-id"
def _rollup_fixture(
filename: str, rollup_cls: type, field_name: str
) -> DailyRollupDataPoint | None:
"""Build the most recent daily rollup data point from a fixture."""
points = load_json_object_fixture(filename, DOMAIN)["rollupDataPoints"]
if not points:
return None
return DailyRollupDataPoint.from_api_dict(rollup_cls, field_name, points[0])
def _list_fixture(filename: str, data_type: DataType) -> ListDataPointResult:
"""Build a list data point result from a fixture."""
data_points = [
DataPoint.from_api_dict(data_type, item)
for item in load_json_object_fixture(filename, DOMAIN)["dataPoints"]
]
return ListDataPointResult(_ListDataPointsModel(data_points=data_points))
def paired_devices_fixture(filename: str) -> ListPairedDevicesResult:
"""Build a list of paired devices result from a fixture."""
raw_json = load_json_object_fixture(filename, DOMAIN)
return ListPairedDevicesResult(_ListPairedDevicesModel.from_dict(raw_json))
@pytest.fixture(name="expires_at")
def mock_expires_at() -> int:
"""Fixture to set the oauth token expiration time."""
return int(time.time() + 86400)
@pytest.fixture
def scopes(request: pytest.FixtureRequest) -> list[str]:
"""Fixture with scopes to set up."""
return getattr(request, "param", OAUTH_SCOPES)
@pytest.fixture(name="token_entry")
def mock_token_entry(expires_at: int, scopes: list[str]) -> dict[str, Any]:
"""Fixture for OAuth 'token' data for a ConfigEntry."""
return {
"access_token": FAKE_ACCESS_TOKEN,
"refresh_token": FAKE_REFRESH_TOKEN,
"scope": " ".join(scopes),
"token_type": "Bearer",
"expires_at": expires_at,
}
@pytest.fixture(name="config_entry")
def mock_config_entry(token_entry: dict[str, Any]) -> MockConfigEntry:
"""Fixture for a config entry."""
return MockConfigEntry(
domain=DOMAIN,
title="Google Health",
unique_id=HEALTH_USER_ID,
entry_id="01J0BC4QM2YBRP6H5G933CETT7",
data={
"auth_implementation": DOMAIN,
"token": token_entry,
},
)
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.google_health.async_setup_entry", return_value=True
) as mock_setup_entry:
yield mock_setup_entry
@pytest.fixture
def mock_google_health_client() -> Generator[AsyncMock]:
"""Mock a Google Health client."""
with (
patch(
"homeassistant.components.google_health.GoogleHealthApi",
autospec=True,
) as mock_client,
patch(
"homeassistant.components.google_health.config_flow.GoogleHealthApi",
new=mock_client,
),
):
client = mock_client.return_value
client.steps = AsyncMock()
client.steps.today.return_value = _rollup_fixture(
"steps.json", StepsRollupValue, "steps"
)
client.steps.required_read_scopes = [
"https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly"
]
client.distance = AsyncMock()
client.distance.today.return_value = _rollup_fixture(
"distance.json", DistanceRollupValue, "distance"
)
client.active_energy_burned = AsyncMock()
client.active_energy_burned.today.return_value = _rollup_fixture(
"active_energy_burned.json",
ActiveEnergyBurnedRollupValue,
"activeEnergyBurned",
)
client.total_calories = AsyncMock()
client.total_calories.today.return_value = _rollup_fixture(
"total_calories.json", TotalCaloriesRollupValue, "totalCalories"
)
client.floors = AsyncMock()
client.floors.today.return_value = _rollup_fixture(
"floors.json", FloorsRollupValue, "floors"
)
client.hydration_log = AsyncMock()
client.hydration_log.today.return_value = _rollup_fixture(
"hydration.json", HydrationLogRollupValue, "hydrationLog"
)
client.hydration_log.required_read_scopes = [
"https://www.googleapis.com/auth/googlehealth.nutrition.readonly"
]
client.nutrition_log = AsyncMock()
client.nutrition_log.today.return_value = _rollup_fixture(
"nutrition.json", NutritionLogRollupValue, "nutritionLog"
)
client.weight = AsyncMock()
client.weight.list.return_value = _list_fixture("weight.json", WEIGHT)
client.weight.required_read_scopes = [
"https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly"
]
client.daily_resting_heart_rate = AsyncMock()
client.daily_resting_heart_rate.list.return_value = _list_fixture(
"resting_heart_rate.json", DAILY_RESTING_HEART_RATE
)
client.body_fat = AsyncMock()
client.body_fat.list.return_value = _list_fixture("body_fat.json", BODY_FAT)
client.paired_devices = AsyncMock()
client.paired_devices.list.return_value = paired_devices_fixture(
"paired_devices.json"
)
client.paired_devices.required_read_scopes = [
"https://www.googleapis.com/auth/googlehealth.settings.readonly"
]
client.sleep = AsyncMock()
client.sleep.list.return_value = _list_fixture("sleep.json", SLEEP)
client.sleep.required_read_scopes = [
"https://www.googleapis.com/auth/googlehealth.sleep.readonly"
]
client.get_identity.return_value = Identity.from_dict(
load_json_object_fixture("identity.json", DOMAIN)
)
client.get_user_info.return_value = UserInfo.from_dict(
load_json_object_fixture("userinfo.json", DOMAIN)
)
yield client
@pytest.fixture
async def setup_credentials(hass: HomeAssistant) -> None:
"""Fixture to setup credentials."""
assert await async_setup_component(hass, APPLICATION_CREDENTIALS_DOMAIN, {})
await async_import_client_credential(
hass,
DOMAIN,
ClientCredential(CLIENT_ID, CLIENT_SECRET),
)
@pytest.fixture(name="integration_setup")
async def mock_integration_setup(
hass: HomeAssistant,
config_entry: MockConfigEntry,
setup_credentials: None,
) -> Callable[[], Awaitable[bool]]:
"""Fixture to set up the integration."""
config_entry.add_to_hass(hass)
async def run() -> bool:
result = await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
return result
return run