From 51a04585e7629f21de28459963aba0e9c2dee9e3 Mon Sep 17 00:00:00 2001 From: Tom Brien Date: Tue, 25 Jan 2022 14:58:35 +0000 Subject: [PATCH] Add diagnostics for Coinbase (#64900) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Joakim Sørensen --- homeassistant/components/coinbase/const.py | 2 + .../components/coinbase/diagnostics.py | 33 ++++++++++++++ tests/components/coinbase/common.py | 2 +- tests/components/coinbase/const.py | 42 +++++++++++++++++ tests/components/coinbase/test_diagnostics.py | 45 +++++++++++++++++++ 5 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/coinbase/diagnostics.py create mode 100644 tests/components/coinbase/test_diagnostics.py diff --git a/homeassistant/components/coinbase/const.py b/homeassistant/components/coinbase/const.py index a01db46b095..e5573f1890f 100644 --- a/homeassistant/components/coinbase/const.py +++ b/homeassistant/components/coinbase/const.py @@ -4,6 +4,7 @@ CONF_CURRENCIES = "account_balance_currencies" CONF_EXCHANGE_BASE = "exchange_base" CONF_EXCHANGE_RATES = "exchange_rate_currencies" CONF_OPTIONS = "options" +CONF_TITLE = "title" DOMAIN = "coinbase" # These are constants used by the previous YAML configuration @@ -18,6 +19,7 @@ API_ACCOUNT_NATIVE_BALANCE = "native_balance" API_ACCOUNT_NAME = "name" API_ACCOUNTS_DATA = "data" API_RATES = "rates" +API_RESOURCE_PATH = "resource_path" API_RESOURCE_TYPE = "type" API_TYPE_VAULT = "vault" diff --git a/homeassistant/components/coinbase/diagnostics.py b/homeassistant/components/coinbase/diagnostics.py new file mode 100644 index 00000000000..54d4168776c --- /dev/null +++ b/homeassistant/components/coinbase/diagnostics.py @@ -0,0 +1,33 @@ +"""Diagnostics support for Coinbase.""" + +from homeassistant.components.diagnostics import async_redact_data +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import CONF_API_KEY, CONF_API_TOKEN, CONF_ID +from homeassistant.core import HomeAssistant + +from . import CoinbaseData +from .const import API_ACCOUNT_AMOUNT, API_RESOURCE_PATH, CONF_TITLE, DOMAIN + +TO_REDACT = { + API_ACCOUNT_AMOUNT, + API_RESOURCE_PATH, + CONF_API_KEY, + CONF_API_TOKEN, + CONF_ID, + CONF_TITLE, +} + + +async def async_get_config_entry_diagnostics( + hass: HomeAssistant, entry: ConfigEntry +) -> dict: + """Return diagnostics for a config entry.""" + instance: CoinbaseData = hass.data[DOMAIN][entry.entry_id] + + return async_redact_data( + { + "entry": entry.as_dict(), + "accounts": instance.accounts, + }, + TO_REDACT, + ) diff --git a/tests/components/coinbase/common.py b/tests/components/coinbase/common.py index 10d6e2a2c35..4866039f310 100644 --- a/tests/components/coinbase/common.py +++ b/tests/components/coinbase/common.py @@ -68,7 +68,7 @@ async def init_mock_coinbase(hass, currencies=None, rates=None): """Init Coinbase integration for testing.""" config_entry = MockConfigEntry( domain=DOMAIN, - unique_id="abcde12345", + unique_id=None, title="Test User", data={CONF_API_KEY: "123456", CONF_API_TOKEN: "AbCDeF"}, options={ diff --git a/tests/components/coinbase/const.py b/tests/components/coinbase/const.py index 082c986aa59..6f9fff94421 100644 --- a/tests/components/coinbase/const.py +++ b/tests/components/coinbase/const.py @@ -1,5 +1,7 @@ """Constants for testing the Coinbase integration.""" +from homeassistant.components.diagnostics.const import REDACTED + GOOD_CURRENCY = "BTC" GOOD_CURRENCY_2 = "USD" GOOD_CURRENCY_3 = "EUR" @@ -34,3 +36,43 @@ MOCK_ACCOUNTS_RESPONSE = [ "type": "fiat", }, ] + +MOCK_ACCOUNTS_RESPONSE_REDACTED = [ + { + "balance": {"amount": REDACTED, "currency": GOOD_CURRENCY}, + "currency": GOOD_CURRENCY, + "id": REDACTED, + "name": "BTC Wallet", + "native_balance": {"amount": REDACTED, "currency": GOOD_CURRENCY_2}, + "type": "wallet", + }, + { + "balance": {"amount": REDACTED, "currency": GOOD_CURRENCY}, + "currency": GOOD_CURRENCY, + "id": REDACTED, + "name": "BTC Vault", + "native_balance": {"amount": REDACTED, "currency": GOOD_CURRENCY_2}, + "type": "vault", + }, + { + "balance": {"amount": REDACTED, "currency": GOOD_CURRENCY_2}, + "currency": "USD", + "id": REDACTED, + "name": "USD Wallet", + "native_balance": {"amount": REDACTED, "currency": GOOD_CURRENCY_2}, + "type": "fiat", + }, +] + +MOCK_ENTRY_REDACTED = { + "version": 1, + "domain": "coinbase", + "title": REDACTED, + "data": {"api_token": REDACTED, "api_key": REDACTED}, + "options": {"account_balance_currencies": [], "exchange_rate_currencies": []}, + "pref_disable_new_entities": False, + "pref_disable_polling": False, + "source": "user", + "unique_id": None, + "disabled_by": None, +} diff --git a/tests/components/coinbase/test_diagnostics.py b/tests/components/coinbase/test_diagnostics.py new file mode 100644 index 00000000000..b19f5c94d1b --- /dev/null +++ b/tests/components/coinbase/test_diagnostics.py @@ -0,0 +1,45 @@ +"""Test the Coinbase diagnostics.""" + +from unittest.mock import patch + +from aiohttp import ClientSession + +from .common import ( + init_mock_coinbase, + mock_get_current_user, + mock_get_exchange_rates, + mocked_get_accounts, +) + +from tests.components.coinbase.const import ( + MOCK_ACCOUNTS_RESPONSE_REDACTED, + MOCK_ENTRY_REDACTED, +) +from tests.components.diagnostics import get_diagnostics_for_config_entry + + +async def test_entry_diagnostics(hass, hass_client: ClientSession): + """Test we handle a and redact a diagnostics request.""" + + with patch( + "coinbase.wallet.client.Client.get_current_user", + return_value=mock_get_current_user(), + ), patch( + "coinbase.wallet.client.Client.get_accounts", new=mocked_get_accounts + ), patch( + "coinbase.wallet.client.Client.get_exchange_rates", + return_value=mock_get_exchange_rates(), + ): + + config_entry = await init_mock_coinbase(hass) + await hass.async_block_till_done() + + result = await get_diagnostics_for_config_entry(hass, hass_client, config_entry) + + # Remove the ID to match the constant + result["entry"].pop("entry_id") + + assert result == { + "entry": MOCK_ENTRY_REDACTED, + "accounts": MOCK_ACCOUNTS_RESPONSE_REDACTED, + }