diff --git a/homeassistant/components/environment_canada/diagnostics.py b/homeassistant/components/environment_canada/diagnostics.py new file mode 100644 index 00000000000..f1064cea52e --- /dev/null +++ b/homeassistant/components/environment_canada/diagnostics.py @@ -0,0 +1,26 @@ +"""Diagnostics support for Environment Canada.""" +from __future__ import annotations + +from homeassistant.components.diagnostics import async_redact_data +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE +from homeassistant.core import HomeAssistant + +from .const import DOMAIN + +TO_REDACT = {CONF_LATITUDE, CONF_LONGITUDE} + + +async def async_get_config_entry_diagnostics( + hass: HomeAssistant, config_entry: ConfigEntry +) -> dict: + """Return diagnostics for a config entry.""" + coordinators = hass.data[DOMAIN][config_entry.entry_id] + weather_coord = coordinators["weather_coordinator"] + + diagnostics_data = { + "config_entry_data": async_redact_data(dict(config_entry.data), TO_REDACT), + "weather_data": dict(weather_coord.ec_data.conditions), + } + + return diagnostics_data diff --git a/tests/components/environment_canada/fixtures/config_entry_data.json b/tests/components/environment_canada/fixtures/config_entry_data.json new file mode 100644 index 00000000000..085a3394dce --- /dev/null +++ b/tests/components/environment_canada/fixtures/config_entry_data.json @@ -0,0 +1,110 @@ +{ + "config_entry_data": { + "latitude": "**REDACTED**", + "longitude": "**REDACTED**", + "station": "XX/1234567", + "language": "Gibberish" + }, + "weather_data": { + "temperature": { + "label": "Temperature", + "value": 14.9, + "unit": "C" + }, + "dewpoint": { + "label": "Dew Point", + "value": 1.4, + "unit": "C" + }, + "wind_chill": { + "label": "Wind Chill", + "value": null + }, + "humidex": { + "label": "Humidex", + "value": null + }, + "pressure": { + "label": "Pressure", + "value": 102.7, + "unit": "kPa" + }, + "tendency": { + "label": "Tendency", + "value": "falling" + }, + "humidity": { + "label": "Humidity", + "value": 40, + "unit": "%" + }, + "visibility": { + "label": "Visibility", + "value": 24.1, + "unit": "km" + }, + "condition": { + "label": "Condition", + "value": "Mainly Sunny" + }, + "wind_speed": { + "label": "Wind Speed", + "value": 1, + "unit": "km/h" + }, + "wind_gust": { + "label": "Wind Gust", + "value": null + }, + "wind_dir": { + "label": "Wind Direction", + "value": "N" + }, + "wind_bearing": { + "label": "Wind Bearing", + "value": 0, + "unit": "degrees" + }, + "high_temp": { + "label": "High Temperature", + "value": 18, + "unit": "C" + }, + "low_temp": { + "label": "Low Temperature", + "value": -1, + "unit": "C" + }, + "uv_index": { + "label": "UV Index", + "value": 5 + }, + "pop": { + "label": "Chance of Precip.", + "value": null + }, + "icon_code": { + "label": "Icon Code", + "value": "01" + }, + "precip_yesterday": { + "label": "Precipitation Yesterday", + "value": 0.0, + "unit": "mm" + }, + "normal_high": { + "label": "Normal High Temperature", + "value": 15, + "unit": "C" + }, + "normal_low": { + "label": "Normal Low Temperature", + "value": 6, + "unit": "C" + }, + "text_summary": { + "label": "Forecast", + "value": "Tonight. Clear. Fog patches developing after midnight. Low minus 1 with frost." + } + } +} diff --git a/tests/components/environment_canada/fixtures/current_conditions_data.json b/tests/components/environment_canada/fixtures/current_conditions_data.json new file mode 100644 index 00000000000..f3a18869940 --- /dev/null +++ b/tests/components/environment_canada/fixtures/current_conditions_data.json @@ -0,0 +1,235 @@ +{ + "alerts": { + "warnings": { + "value": [], + "label": "Warnings" + }, + "watches": { + "value": [], + "label": "Watches" + }, + "advisories": { + "value": [ + { + "title": "Frost Advisory", + "date": "Monday October 03, 2022 at 15:05 EDT" + } + ], + "label": "Advisories" + }, + "statements": { + "value": [], + "label": "Statements" + }, + "endings": { + "value": [], + "label": "Endings" + } + }, + "conditions": { + "temperature": { + "label": "Temperature", + "value": 14.9, + "unit": "C" + }, + "dewpoint": { + "label": "Dew Point", + "value": 1.4, + "unit": "C" + }, + "wind_chill": { + "label": "Wind Chill", + "value": null + }, + "humidex": { + "label": "Humidex", + "value": null + }, + "pressure": { + "label": "Pressure", + "value": 102.7, + "unit": "kPa" + }, + "tendency": { + "label": "Tendency", + "value": "falling" + }, + "humidity": { + "label": "Humidity", + "value": 40, + "unit": "%" + }, + "visibility": { + "label": "Visibility", + "value": 24.1, + "unit": "km" + }, + "condition": { + "label": "Condition", + "value": "Mainly Sunny" + }, + "wind_speed": { + "label": "Wind Speed", + "value": 1, + "unit": "km/h" + }, + "wind_gust": { + "label": "Wind Gust", + "value": null + }, + "wind_dir": { + "label": "Wind Direction", + "value": "N" + }, + "wind_bearing": { + "label": "Wind Bearing", + "value": 0, + "unit": "degrees" + }, + "high_temp": { + "label": "High Temperature", + "value": 18, + "unit": "C" + }, + "low_temp": { + "label": "Low Temperature", + "value": -1, + "unit": "C" + }, + "uv_index": { + "label": "UV Index", + "value": 5 + }, + "pop": { + "label": "Chance of Precip.", + "value": null + }, + "icon_code": { + "label": "Icon Code", + "value": "01" + }, + "precip_yesterday": { + "label": "Precipitation Yesterday", + "value": 0.0, + "unit": "mm" + }, + "normal_high": { + "label": "Normal High Temperature", + "value": 15, + "unit": "C" + }, + "normal_low": { + "label": "Normal Low Temperature", + "value": 6, + "unit": "C" + }, + "text_summary": { + "label": "Forecast", + "value": "Tonight. Clear. Fog patches developing after midnight. Low minus 1 with frost." + } + }, + "daily_forecasts": [ + { + "period": "Monday night", + "text_summary": "Clear. Fog patches developing after midnight. Low minus 1 with frost.", + "icon_code": "30", + "temperature": -1, + "temperature_class": "low", + "precip_probability": 0 + }, + { + "period": "Tuesday", + "text_summary": "Sunny. Fog patches dissipating in the morning. High 18. UV index 5 or moderate.", + "icon_code": "00", + "temperature": 18, + "temperature_class": "high", + "precip_probability": 0 + }, + { + "period": "Tuesday night", + "text_summary": "Clear. Fog patches developing overnight. Low plus 3.", + "icon_code": "30", + "temperature": 3, + "temperature_class": "low", + "precip_probability": 0 + }, + { + "period": "Wednesday", + "text_summary": "Sunny. High 20.", + "icon_code": "00", + "temperature": 20, + "temperature_class": "high", + "precip_probability": 0 + }, + { + "period": "Wednesday night", + "text_summary": "Clear. Low 9.", + "icon_code": "30", + "temperature": 9, + "temperature_class": "low", + "precip_probability": 0 + }, + { + "period": "Thursday", + "text_summary": "A mix of sun and cloud. High 20.", + "icon_code": "02", + "temperature": 20, + "temperature_class": "high", + "precip_probability": 0 + }, + { + "period": "Thursday night", + "text_summary": "Showers. Low 7.", + "icon_code": "12", + "temperature": 7, + "temperature_class": "low", + "precip_probability": 0 + }, + { + "period": "Friday", + "text_summary": "Cloudy with 40 percent chance of showers. High 13.", + "icon_code": "12", + "temperature": 13, + "temperature_class": "high", + "precip_probability": 40 + }, + { + "period": "Friday night", + "text_summary": "Cloudy periods. Low plus 1.", + "icon_code": "32", + "temperature": 1, + "temperature_class": "low", + "precip_probability": 0 + }, + { + "period": "Saturday", + "text_summary": "A mix of sun and cloud. High 10.", + "icon_code": "02", + "temperature": 10, + "temperature_class": "high", + "precip_probability": 0 + }, + { + "period": "Saturday night", + "text_summary": "Cloudy periods. Low plus 3.", + "icon_code": "32", + "temperature": 3, + "temperature_class": "low", + "precip_probability": 0 + }, + { + "period": "Sunday", + "text_summary": "A mix of sun and cloud. High 12.", + "icon_code": "02", + "temperature": 12, + "temperature_class": "high", + "precip_probability": 0 + } + ], + "metadata": { + "attribution": "Data provided by Environment Canada", + "timestamp": "2022/10/3", + "location": "Ottawa (Kanata - Orl\u00e9ans)", + "station": "Ottawa Macdonald-Cartier Intl Airport" + } +} diff --git a/tests/components/environment_canada/test_diagnostics.py b/tests/components/environment_canada/test_diagnostics.py new file mode 100644 index 00000000000..a1f3539a5e4 --- /dev/null +++ b/tests/components/environment_canada/test_diagnostics.py @@ -0,0 +1,85 @@ +"""Test Environment Canada diagnostics.""" + +from datetime import datetime, timezone +import json +from unittest.mock import AsyncMock, MagicMock, patch + +from homeassistant.components.environment_canada.const import ( + CONF_LANGUAGE, + CONF_STATION, + DOMAIN, +) +from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE +from homeassistant.core import HomeAssistant + +from tests.common import MockConfigEntry, load_fixture +from tests.components.diagnostics import get_diagnostics_for_config_entry + +FIXTURE_USER_INPUT = { + CONF_LATITUDE: 55.55, + CONF_LONGITUDE: 42.42, + CONF_STATION: "XX/1234567", + CONF_LANGUAGE: "Gibberish", +} + + +async def init_integration(hass: HomeAssistant) -> MockConfigEntry: + """Set up the Environment Canada integration in Home Assistant.""" + + def mock_ec(): + ec_mock = MagicMock() + ec_mock.station_id = FIXTURE_USER_INPUT[CONF_STATION] + ec_mock.lat = FIXTURE_USER_INPUT[CONF_LATITUDE] + ec_mock.lon = FIXTURE_USER_INPUT[CONF_LONGITUDE] + ec_mock.language = FIXTURE_USER_INPUT[CONF_LANGUAGE] + ec_mock.update = AsyncMock() + return ec_mock + + config_entry = MockConfigEntry(domain=DOMAIN, data=FIXTURE_USER_INPUT) + config_entry.add_to_hass(hass) + + ec_data = json.loads( + load_fixture("environment_canada/current_conditions_data.json") + ) + + weather_mock = mock_ec() + ec_data["metadata"]["timestamp"] = datetime(2022, 10, 4, tzinfo=timezone.utc) + weather_mock.conditions = ec_data["conditions"] + weather_mock.alerts = ec_data["alerts"] + weather_mock.daily_forecasts = ec_data["daily_forecasts"] + weather_mock.metadata = ec_data["metadata"] + + radar_mock = mock_ec() + radar_mock.image = b"GIF..." + radar_mock.timestamp = datetime(2022, 10, 4, tzinfo=timezone.utc) + + with patch( + "homeassistant.components.environment_canada.ECWeather", + return_value=weather_mock, + ), patch( + "homeassistant.components.environment_canada.ECAirQuality", + return_value=mock_ec(), + ), patch( + "homeassistant.components.environment_canada.ECRadar", return_value=radar_mock + ), patch( + "homeassistant.components.environment_canada.config_flow.ECWeather", + return_value=weather_mock, + ): + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + return config_entry + + +async def test_entry_diagnostics(hass, hass_client): + """Test config entry diagnostics.""" + + config_entry = await init_integration(hass) + diagnostics = await get_diagnostics_for_config_entry( + hass, hass_client, config_entry + ) + redacted_entry = json.loads( + load_fixture("environment_canada/config_entry_data.json") + ) + + assert diagnostics == redacted_entry