Add diagnostics to Withings (#102066)

pull/102074/head
Joost Lekkerkerker 2023-10-15 20:29:20 +02:00 committed by GitHub
parent 6f5a72edf2
commit b4e4a98f17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 206 additions and 0 deletions

View File

@ -34,6 +34,7 @@ class WithingsDataUpdateCoordinator(DataUpdateCoordinator[_T]):
config_entry: ConfigEntry
_default_update_interval: timedelta | None = UPDATE_INTERVAL
_last_valid_update: datetime | None = None
webhooks_connected: bool = False
def __init__(self, hass: HomeAssistant, client: WithingsClient) -> None:
"""Initialize the Withings data coordinator."""
@ -45,6 +46,7 @@ class WithingsDataUpdateCoordinator(DataUpdateCoordinator[_T]):
def webhook_subscription_listener(self, connected: bool) -> None:
"""Call when webhook status changed."""
self.webhooks_connected = connected
if connected:
self.update_interval = None
else:

View File

@ -0,0 +1,45 @@
"""Diagnostics support for Withings."""
from __future__ import annotations
from typing import Any
from yarl import URL
from homeassistant.components.webhook import async_generate_url as webhook_generate_url
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_WEBHOOK_ID
from homeassistant.core import HomeAssistant
from . import (
CONF_CLOUDHOOK_URL,
WithingsMeasurementDataUpdateCoordinator,
WithingsSleepDataUpdateCoordinator,
)
from .const import DOMAIN, MEASUREMENT_COORDINATOR, SLEEP_COORDINATOR
async def async_get_config_entry_diagnostics(
hass: HomeAssistant, entry: ConfigEntry
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""
webhook_url = webhook_generate_url(hass, entry.data[CONF_WEBHOOK_ID])
url = URL(webhook_url)
has_valid_external_webhook_url = url.scheme == "https" and url.port == 443
has_cloudhooks = CONF_CLOUDHOOK_URL in entry.data
measurement_coordinator: WithingsMeasurementDataUpdateCoordinator = hass.data[
DOMAIN
][entry.entry_id][MEASUREMENT_COORDINATOR]
sleep_coordinator: WithingsSleepDataUpdateCoordinator = hass.data[DOMAIN][
entry.entry_id
][SLEEP_COORDINATOR]
return {
"has_valid_external_webhook_url": has_valid_external_webhook_url,
"has_cloudhooks": has_cloudhooks,
"webhooks_connected": measurement_coordinator.webhooks_connected,
"received_measurements": list(measurement_coordinator.data.keys()),
"received_sleep_data": sleep_coordinator.data is not None,
}

View File

@ -0,0 +1,79 @@
# serializer version: 1
# name: test_diagnostics_cloudhook_instance
dict({
'has_cloudhooks': True,
'has_valid_external_webhook_url': True,
'received_measurements': list([
1,
8,
5,
76,
88,
4,
12,
71,
73,
6,
9,
10,
11,
54,
77,
91,
]),
'received_sleep_data': True,
'webhooks_connected': True,
})
# ---
# name: test_diagnostics_polling_instance
dict({
'has_cloudhooks': False,
'has_valid_external_webhook_url': False,
'received_measurements': list([
1,
8,
5,
76,
88,
4,
12,
71,
73,
6,
9,
10,
11,
54,
77,
91,
]),
'received_sleep_data': True,
'webhooks_connected': False,
})
# ---
# name: test_diagnostics_webhook_instance
dict({
'has_cloudhooks': False,
'has_valid_external_webhook_url': True,
'received_measurements': list([
1,
8,
5,
76,
88,
4,
12,
71,
73,
6,
9,
10,
11,
54,
77,
91,
]),
'received_sleep_data': True,
'webhooks_connected': True,
})
# ---

View File

@ -0,0 +1,80 @@
"""Tests for the diagnostics data provided by the Withings integration."""
from unittest.mock import AsyncMock, patch
from freezegun.api import FrozenDateTimeFactory
from syrupy import SnapshotAssertion
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
from tests.components.diagnostics import get_diagnostics_for_config_entry
from tests.components.withings import prepare_webhook_setup, setup_integration
from tests.typing import ClientSessionGenerator
async def test_diagnostics_polling_instance(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
withings: AsyncMock,
polling_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test diagnostics."""
await setup_integration(hass, polling_config_entry, False)
assert (
await get_diagnostics_for_config_entry(hass, hass_client, polling_config_entry)
== snapshot
)
async def test_diagnostics_webhook_instance(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
withings: AsyncMock,
webhook_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test diagnostics."""
await setup_integration(hass, webhook_config_entry)
await prepare_webhook_setup(hass, freezer)
assert (
await get_diagnostics_for_config_entry(hass, hass_client, webhook_config_entry)
== snapshot
)
async def test_diagnostics_cloudhook_instance(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
withings: AsyncMock,
webhook_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test diagnostics."""
with patch(
"homeassistant.components.cloud.async_is_logged_in", return_value=True
), patch(
"homeassistant.components.cloud.async_is_connected", return_value=True
), patch(
"homeassistant.components.cloud.async_active_subscription", return_value=True
), patch(
"homeassistant.components.cloud.async_create_cloudhook",
return_value="https://hooks.nabu.casa/ABCD",
), patch(
"homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation",
), patch(
"homeassistant.components.cloud.async_delete_cloudhook"
), patch(
"homeassistant.components.withings.webhook_generate_url"
):
await setup_integration(hass, webhook_config_entry)
await prepare_webhook_setup(hass, freezer)
assert (
await get_diagnostics_for_config_entry(hass, hass_client, webhook_config_entry)
== snapshot
)