|
| 1 | +"""Test the AuroraWatch UK sensor platform.""" |
| 2 | + |
| 3 | +from unittest.mock import AsyncMock |
| 4 | + |
| 5 | +from aiohttp import ClientError |
| 6 | +import pytest |
| 7 | + |
| 8 | +from homeassistant.components.aurorawatch.const import ( |
| 9 | + ATTR_API_VERSION, |
| 10 | + ATTR_LAST_UPDATED, |
| 11 | + ATTR_PROJECT_ID, |
| 12 | + ATTR_SITE_ID, |
| 13 | + ATTR_SITE_URL, |
| 14 | + DOMAIN, |
| 15 | +) |
| 16 | +from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN |
| 17 | +from homeassistant.const import STATE_UNAVAILABLE |
| 18 | +from homeassistant.core import HomeAssistant |
| 19 | +from homeassistant.helpers import entity_registry as er |
| 20 | + |
| 21 | +from . import setup_integration |
| 22 | + |
| 23 | +from tests.common import MockConfigEntry |
| 24 | + |
| 25 | + |
| 26 | +async def test_sensor_setup( |
| 27 | + hass: HomeAssistant, |
| 28 | + mock_aiohttp_session: AsyncMock, |
| 29 | + mock_config_entry: MockConfigEntry, |
| 30 | +) -> None: |
| 31 | + """Test sensor setup.""" |
| 32 | + await setup_integration(hass, mock_config_entry) |
| 33 | + |
| 34 | + entity_registry = er.async_get(hass) |
| 35 | + |
| 36 | + # Check that both sensors are created |
| 37 | + status_sensor = entity_registry.async_get("sensor.aurorawatch_uk_aurora_status") |
| 38 | + assert status_sensor |
| 39 | + assert status_sensor.unique_id == "aurorawatch_aurora_status" |
| 40 | + assert status_sensor.translation_key == "aurora_status" |
| 41 | + |
| 42 | + activity_sensor = entity_registry.async_get( |
| 43 | + "sensor.aurorawatch_uk_geomagnetic_activity" |
| 44 | + ) |
| 45 | + assert activity_sensor |
| 46 | + assert activity_sensor.unique_id == "aurorawatch_geomagnetic_activity" |
| 47 | + assert activity_sensor.translation_key == "geomagnetic_activity" |
| 48 | + |
| 49 | + |
| 50 | +async def test_sensor_states( |
| 51 | + hass: HomeAssistant, |
| 52 | + mock_aiohttp_session: AsyncMock, |
| 53 | + mock_config_entry: MockConfigEntry, |
| 54 | +) -> None: |
| 55 | + """Test sensor states.""" |
| 56 | + await setup_integration(hass, mock_config_entry) |
| 57 | + |
| 58 | + # Check status sensor state |
| 59 | + status_state = hass.states.get("sensor.aurorawatch_uk_aurora_status") |
| 60 | + assert status_state |
| 61 | + assert status_state.state == "green" |
| 62 | + |
| 63 | + # Check activity sensor state |
| 64 | + activity_state = hass.states.get("sensor.aurorawatch_uk_geomagnetic_activity") |
| 65 | + assert activity_state |
| 66 | + assert activity_state.state == "52.7" |
| 67 | + assert activity_state.attributes.get("unit_of_measurement") == "nT" |
| 68 | + assert activity_state.attributes.get("state_class") == "measurement" |
| 69 | + |
| 70 | + |
| 71 | +async def test_sensor_attributes( |
| 72 | + hass: HomeAssistant, |
| 73 | + mock_aiohttp_session: AsyncMock, |
| 74 | + mock_config_entry: MockConfigEntry, |
| 75 | +) -> None: |
| 76 | + """Test sensor attributes.""" |
| 77 | + await setup_integration(hass, mock_config_entry) |
| 78 | + |
| 79 | + # Check status sensor attributes |
| 80 | + status_state = hass.states.get("sensor.aurorawatch_uk_aurora_status") |
| 81 | + assert status_state |
| 82 | + assert status_state.attributes.get(ATTR_LAST_UPDATED) == "2024-01-15T12:00:00Z" |
| 83 | + assert status_state.attributes.get(ATTR_PROJECT_ID) == "awn" |
| 84 | + assert status_state.attributes.get(ATTR_SITE_ID) == "lancaster" |
| 85 | + assert ( |
| 86 | + status_state.attributes.get(ATTR_SITE_URL) == "http://aurorawatch.lancs.ac.uk" |
| 87 | + ) |
| 88 | + assert status_state.attributes.get(ATTR_API_VERSION) == "0.2" |
| 89 | + assert ( |
| 90 | + status_state.attributes.get("attribution") == "Data provided by AuroraWatch UK" |
| 91 | + ) |
| 92 | + |
| 93 | + |
| 94 | +async def test_sensor_update_failure_network_error( |
| 95 | + hass: HomeAssistant, |
| 96 | + mock_config_entry: MockConfigEntry, |
| 97 | +) -> None: |
| 98 | + """Test sensor update with network error.""" |
| 99 | + from unittest.mock import patch |
| 100 | + |
| 101 | + with patch( |
| 102 | + "homeassistant.components.aurorawatch.coordinator.async_get_clientsession" |
| 103 | + ) as mock_session_factory: |
| 104 | + mock_session = AsyncMock() |
| 105 | + mock_session_factory.return_value = mock_session |
| 106 | + |
| 107 | + # Mock network error |
| 108 | + mock_session.get.side_effect = ClientError("Connection failed") |
| 109 | + |
| 110 | + mock_config_entry.add_to_hass(hass) |
| 111 | + await hass.config_entries.async_setup(mock_config_entry.entry_id) |
| 112 | + await hass.async_block_till_done() |
| 113 | + |
| 114 | + # Sensors should be unavailable |
| 115 | + status_state = hass.states.get("sensor.aurorawatch_uk_aurora_status") |
| 116 | + assert status_state |
| 117 | + assert status_state.state == STATE_UNAVAILABLE |
| 118 | + |
| 119 | + activity_state = hass.states.get("sensor.aurorawatch_uk_geomagnetic_activity") |
| 120 | + assert activity_state |
| 121 | + assert activity_state.state == STATE_UNAVAILABLE |
| 122 | + |
| 123 | + |
| 124 | +async def test_sensor_update_failure_invalid_xml( |
| 125 | + hass: HomeAssistant, |
| 126 | + mock_config_entry: MockConfigEntry, |
| 127 | +) -> None: |
| 128 | + """Test sensor update with invalid XML.""" |
| 129 | + from unittest.mock import patch |
| 130 | + |
| 131 | + from tests.components.aurorawatch.conftest import MOCK_MALFORMED_XML |
| 132 | + |
| 133 | + with patch( |
| 134 | + "homeassistant.components.aurorawatch.coordinator.async_get_clientsession" |
| 135 | + ) as mock_session_factory: |
| 136 | + mock_session = AsyncMock() |
| 137 | + mock_session_factory.return_value = mock_session |
| 138 | + |
| 139 | + # Mock malformed XML response |
| 140 | + mock_response = AsyncMock() |
| 141 | + mock_response.text = AsyncMock(return_value=MOCK_MALFORMED_XML) |
| 142 | + mock_response.raise_for_status = AsyncMock() |
| 143 | + mock_session.get.return_value = mock_response |
| 144 | + |
| 145 | + mock_config_entry.add_to_hass(hass) |
| 146 | + await hass.config_entries.async_setup(mock_config_entry.entry_id) |
| 147 | + await hass.async_block_till_done() |
| 148 | + |
| 149 | + # Sensors should be unavailable due to parsing error |
| 150 | + status_state = hass.states.get("sensor.aurorawatch_uk_aurora_status") |
| 151 | + assert status_state |
| 152 | + assert status_state.state == STATE_UNAVAILABLE |
| 153 | + |
| 154 | + |
| 155 | +async def test_sensor_update_failure_missing_fields( |
| 156 | + hass: HomeAssistant, |
| 157 | + mock_config_entry: MockConfigEntry, |
| 158 | +) -> None: |
| 159 | + """Test sensor update with missing required fields.""" |
| 160 | + from unittest.mock import patch |
| 161 | + |
| 162 | + from tests.components.aurorawatch.conftest import MOCK_INVALID_STATUS_XML |
| 163 | + |
| 164 | + with patch( |
| 165 | + "homeassistant.components.aurorawatch.coordinator.async_get_clientsession" |
| 166 | + ) as mock_session_factory: |
| 167 | + mock_session = AsyncMock() |
| 168 | + mock_session_factory.return_value = mock_session |
| 169 | + |
| 170 | + # Mock invalid XML response (missing required fields) |
| 171 | + mock_response = AsyncMock() |
| 172 | + mock_response.text = AsyncMock(return_value=MOCK_INVALID_STATUS_XML) |
| 173 | + mock_response.raise_for_status = AsyncMock() |
| 174 | + mock_session.get.return_value = mock_response |
| 175 | + |
| 176 | + mock_config_entry.add_to_hass(hass) |
| 177 | + await hass.config_entries.async_setup(mock_config_entry.entry_id) |
| 178 | + await hass.async_block_till_done() |
| 179 | + |
| 180 | + # Sensors should be unavailable due to missing fields |
| 181 | + status_state = hass.states.get("sensor.aurorawatch_uk_aurora_status") |
| 182 | + assert status_state |
| 183 | + assert status_state.state == STATE_UNAVAILABLE |
| 184 | + |
| 185 | + |
| 186 | +async def test_sensor_device_info( |
| 187 | + hass: HomeAssistant, |
| 188 | + mock_aiohttp_session: AsyncMock, |
| 189 | + mock_config_entry: MockConfigEntry, |
| 190 | +) -> None: |
| 191 | + """Test sensor device info.""" |
| 192 | + await setup_integration(hass, mock_config_entry) |
| 193 | + |
| 194 | + entity_registry = er.async_get(hass) |
| 195 | + status_sensor = entity_registry.async_get("sensor.aurorawatch_uk_aurora_status") |
| 196 | + assert status_sensor |
| 197 | + assert status_sensor.device_id |
| 198 | + |
| 199 | + from homeassistant.helpers import device_registry as dr |
| 200 | + |
| 201 | + device_registry = dr.async_get(hass) |
| 202 | + device = device_registry.async_get(status_sensor.device_id) |
| 203 | + assert device |
| 204 | + assert device.manufacturer == "Lancaster University" |
| 205 | + assert device.model == "AuroraWatch UK" |
| 206 | + assert device.name == "AuroraWatch UK" |
0 commit comments