From fe11a6d38f7dba467fa9d38ec5000207496c02fb Mon Sep 17 00:00:00 2001 From: John O'Nolan Date: Sun, 8 Mar 2026 16:03:57 +0400 Subject: [PATCH] Add diagnostics to Ghost integration (#165130) --- homeassistant/components/ghost/config_flow.py | 8 +- homeassistant/components/ghost/diagnostics.py | 27 +++++++ .../components/ghost/quality_scale.yaml | 2 +- homeassistant/components/ghost/strings.json | 4 +- .../ghost/snapshots/test_diagnostics.ambr | 74 +++++++++++++++++++ tests/components/ghost/test_diagnostics.py | 28 +++++++ 6 files changed, 136 insertions(+), 7 deletions(-) create mode 100644 homeassistant/components/ghost/diagnostics.py create mode 100644 tests/components/ghost/snapshots/test_diagnostics.ambr create mode 100644 tests/components/ghost/test_diagnostics.py diff --git a/homeassistant/components/ghost/config_flow.py b/homeassistant/components/ghost/config_flow.py index 53567e496af..ff394a6d2c0 100644 --- a/homeassistant/components/ghost/config_flow.py +++ b/homeassistant/components/ghost/config_flow.py @@ -17,6 +17,8 @@ from .const import CONF_ADMIN_API_KEY, CONF_API_URL, DOMAIN _LOGGER = logging.getLogger(__name__) +GHOST_INTEGRATION_SETUP_URL = "https://account.ghost.org/?r=settings/integrations/new" + STEP_USER_DATA_SCHEMA = vol.Schema( { vol.Required(CONF_API_URL): str, @@ -78,7 +80,7 @@ class GhostConfigFlow(ConfigFlow, domain=DOMAIN): errors=errors, description_placeholders={ "title": reauth_entry.title, - "docs_url": "https://account.ghost.org/?r=settings/integrations/new", + "setup_url": GHOST_INTEGRATION_SETUP_URL, }, ) @@ -103,9 +105,7 @@ class GhostConfigFlow(ConfigFlow, domain=DOMAIN): step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors, - description_placeholders={ - "docs_url": "https://account.ghost.org/?r=settings/integrations/new" - }, + description_placeholders={"setup_url": GHOST_INTEGRATION_SETUP_URL}, ) async def _validate_credentials( diff --git a/homeassistant/components/ghost/diagnostics.py b/homeassistant/components/ghost/diagnostics.py new file mode 100644 index 00000000000..db24c9de6a4 --- /dev/null +++ b/homeassistant/components/ghost/diagnostics.py @@ -0,0 +1,27 @@ +"""Diagnostics support for Ghost.""" + +from __future__ import annotations + +from dataclasses import asdict +from typing import Any + +from homeassistant.components.diagnostics import async_redact_data +from homeassistant.core import HomeAssistant + +from . import GhostConfigEntry +from .const import CONF_ADMIN_API_KEY + +TO_REDACT = {CONF_ADMIN_API_KEY} + + +async def async_get_config_entry_diagnostics( + hass: HomeAssistant, config_entry: GhostConfigEntry +) -> dict[str, Any]: + """Return diagnostics for a config entry.""" + return async_redact_data( + { + "entry_data": dict(config_entry.data), + "coordinator_data": asdict(config_entry.runtime_data.coordinator.data), + }, + TO_REDACT, + ) diff --git a/homeassistant/components/ghost/quality_scale.yaml b/homeassistant/components/ghost/quality_scale.yaml index b2f5b9dfb63..f6fe8121090 100644 --- a/homeassistant/components/ghost/quality_scale.yaml +++ b/homeassistant/components/ghost/quality_scale.yaml @@ -43,7 +43,7 @@ rules: # Gold devices: done - diagnostics: todo + diagnostics: done discovery-update-info: status: exempt comment: Cloud service integration, not discoverable. diff --git a/homeassistant/components/ghost/strings.json b/homeassistant/components/ghost/strings.json index c0de7500dd7..5f25631ea8b 100644 --- a/homeassistant/components/ghost/strings.json +++ b/homeassistant/components/ghost/strings.json @@ -18,7 +18,7 @@ "data_description": { "admin_api_key": "[%key:component::ghost::config::step::user::data_description::admin_api_key%]" }, - "description": "Your API key for {title} is invalid. [Create a new integration key]({docs_url}) to reauthenticate.", + "description": "Your API key for {title} is invalid. [Create a new integration key]({setup_url}) to reauthenticate.", "title": "[%key:common::config_flow::title::reauth%]" }, "user": { @@ -30,7 +30,7 @@ "admin_api_key": "The Admin API key for your Ghost integration", "api_url": "The API URL for your Ghost integration" }, - "description": "[Create a custom integration]({docs_url}) to get your API URL and Admin API key.", + "description": "[Create a custom integration]({setup_url}) to get your API URL and Admin API key.", "title": "Connect to Ghost" } } diff --git a/tests/components/ghost/snapshots/test_diagnostics.ambr b/tests/components/ghost/snapshots/test_diagnostics.ambr new file mode 100644 index 00000000000..4bf180a4ccc --- /dev/null +++ b/tests/components/ghost/snapshots/test_diagnostics.ambr @@ -0,0 +1,74 @@ +# serializer version: 1 +# name: test_diagnostics + dict({ + 'coordinator_data': dict({ + 'activitypub': dict({ + 'followers': 150, + 'following': 25, + }), + 'arr': dict({ + 'usd': 60000, + }), + 'comments': 156, + 'latest_email': dict({ + 'click_rate': 10, + 'clicked_count': 50, + 'delivered_count': 490, + 'email_count': 500, + 'failed_count': 10, + 'open_rate': 40, + 'opened_count': 200, + 'subject': 'Newsletter #1', + 'submitted_at': '2026-01-15T10:00:00Z', + 'title': 'Newsletter #1', + }), + 'latest_post': dict({ + 'published_at': '2026-01-15T10:00:00Z', + 'slug': 'latest-post', + 'title': 'Latest Post', + 'url': 'https://test.ghost.io/latest-post/', + }), + 'members': dict({ + 'comped': 50, + 'free': 850, + 'paid': 100, + 'total': 1000, + }), + 'mrr': dict({ + 'usd': 5000, + }), + 'newsletters': dict({ + 'nl1': dict({ + 'count': dict({ + 'members': 800, + }), + 'id': 'nl1', + 'name': 'Weekly', + 'status': 'active', + }), + 'nl2': dict({ + 'count': dict({ + 'members': 200, + }), + 'id': 'nl2', + 'name': 'Archive', + 'status': 'archived', + }), + }), + 'posts': dict({ + 'drafts': 5, + 'published': 42, + 'scheduled': 2, + }), + 'site': dict({ + 'site_uuid': 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + 'title': 'Test Ghost', + 'url': 'https://test.ghost.io', + }), + }), + 'entry_data': dict({ + 'admin_api_key': '**REDACTED**', + 'api_url': 'https://test.ghost.io', + }), + }) +# --- diff --git a/tests/components/ghost/test_diagnostics.py b/tests/components/ghost/test_diagnostics.py new file mode 100644 index 00000000000..c07fc885ca7 --- /dev/null +++ b/tests/components/ghost/test_diagnostics.py @@ -0,0 +1,28 @@ +"""Tests for the diagnostics data provided by the Ghost integration.""" + +from unittest.mock import AsyncMock + +from syrupy.assertion import SnapshotAssertion + +from homeassistant.core import HomeAssistant + +from . import setup_integration + +from tests.common import MockConfigEntry +from tests.components.diagnostics import get_diagnostics_for_config_entry +from tests.typing import ClientSessionGenerator + + +async def test_diagnostics( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + mock_config_entry: MockConfigEntry, + mock_ghost_api: AsyncMock, + snapshot: SnapshotAssertion, +) -> None: + """Test diagnostics.""" + await setup_integration(hass, mock_config_entry) + assert ( + await get_diagnostics_for_config_entry(hass, hass_client, mock_config_entry) + == snapshot + )