|
1 | 1 | """Test the Teslemetry init.""" |
2 | 2 |
|
3 | | -from unittest.mock import AsyncMock |
| 3 | +from unittest.mock import AsyncMock, patch |
4 | 4 |
|
5 | 5 | from freezegun.api import FrozenDateTimeFactory |
6 | 6 | import pytest |
|
11 | 11 | TeslaFleetError, |
12 | 12 | ) |
13 | 13 |
|
| 14 | +from homeassistant.components.teslemetry.const import DOMAIN |
14 | 15 | from homeassistant.components.teslemetry.coordinator import VEHICLE_INTERVAL |
15 | 16 | from homeassistant.components.teslemetry.models import TeslemetryData |
16 | 17 | from homeassistant.config_entries import ConfigEntryState |
@@ -187,3 +188,94 @@ async def test_modern_no_poll( |
187 | 188 | assert mock_vehicle_data.called is False |
188 | 189 | freezer.tick(VEHICLE_INTERVAL) |
189 | 190 | assert mock_vehicle_data.called is False |
| 191 | + |
| 192 | + |
| 193 | +async def test_stale_device_removal( |
| 194 | + hass: HomeAssistant, |
| 195 | + device_registry: dr.DeviceRegistry, |
| 196 | + mock_products: AsyncMock, |
| 197 | +) -> None: |
| 198 | + """Test removal of stale devices.""" |
| 199 | + |
| 200 | + # Setup the entry first to get a valid config_entry_id |
| 201 | + entry = await setup_platform(hass) |
| 202 | + |
| 203 | + # Create a device that should be removed (with the valid entry_id) |
| 204 | + device_registry.async_get_or_create( |
| 205 | + config_entry_id=entry.entry_id, |
| 206 | + identifiers={(DOMAIN, "stale-vin")}, |
| 207 | + manufacturer="Tesla", |
| 208 | + name="Stale Vehicle", |
| 209 | + ) |
| 210 | + |
| 211 | + # Verify the stale device exists |
| 212 | + pre_devices = dr.async_entries_for_config_entry(device_registry, entry.entry_id) |
| 213 | + stale_identifiers = { |
| 214 | + identifier for device in pre_devices for identifier in device.identifiers |
| 215 | + } |
| 216 | + assert (DOMAIN, "stale-vin") in stale_identifiers |
| 217 | + |
| 218 | + # Update products with an empty response (no devices) and reload entry |
| 219 | + with patch( |
| 220 | + "tesla_fleet_api.teslemetry.Teslemetry.products", |
| 221 | + return_value={"response": []}, |
| 222 | + ): |
| 223 | + await hass.config_entries.async_reload(entry.entry_id) |
| 224 | + await hass.async_block_till_done() |
| 225 | + |
| 226 | + # Get updated devices after reload |
| 227 | + post_devices = dr.async_entries_for_config_entry( |
| 228 | + device_registry, entry.entry_id |
| 229 | + ) |
| 230 | + post_identifiers = { |
| 231 | + identifier for device in post_devices for identifier in device.identifiers |
| 232 | + } |
| 233 | + |
| 234 | + # Verify the stale device has been removed |
| 235 | + assert (DOMAIN, "stale-vin") not in post_identifiers |
| 236 | + |
| 237 | + # Verify the device itself has been completely removed from the registry |
| 238 | + # since it had no other config entries |
| 239 | + updated_device = device_registry.async_get_device( |
| 240 | + identifiers={(DOMAIN, "stale-vin")} |
| 241 | + ) |
| 242 | + assert updated_device is None |
| 243 | + |
| 244 | + |
| 245 | +async def test_device_retention_during_reload( |
| 246 | + hass: HomeAssistant, |
| 247 | + device_registry: dr.DeviceRegistry, |
| 248 | + mock_products: AsyncMock, |
| 249 | +) -> None: |
| 250 | + """Test that valid devices are retained during a config entry reload.""" |
| 251 | + # Setup entry with normal devices |
| 252 | + entry = await setup_platform(hass) |
| 253 | + |
| 254 | + # Get initial device count and identifiers |
| 255 | + pre_devices = dr.async_entries_for_config_entry(device_registry, entry.entry_id) |
| 256 | + pre_count = len(pre_devices) |
| 257 | + pre_identifiers = { |
| 258 | + identifier for device in pre_devices for identifier in device.identifiers |
| 259 | + } |
| 260 | + |
| 261 | + # Make sure we have some devices |
| 262 | + assert pre_count > 0 |
| 263 | + |
| 264 | + # Save the original identifiers to compare after reload |
| 265 | + original_identifiers = pre_identifiers.copy() |
| 266 | + |
| 267 | + # Reload the config entry with the same products data |
| 268 | + # The mock_products fixture will return the same data as during setup |
| 269 | + await hass.config_entries.async_reload(entry.entry_id) |
| 270 | + await hass.async_block_till_done() |
| 271 | + |
| 272 | + # Verify device count and identifiers after reload match pre-reload |
| 273 | + post_devices = dr.async_entries_for_config_entry(device_registry, entry.entry_id) |
| 274 | + post_count = len(post_devices) |
| 275 | + post_identifiers = { |
| 276 | + identifier for device in post_devices for identifier in device.identifiers |
| 277 | + } |
| 278 | + |
| 279 | + # Since the products data didn't change, we should have the same devices |
| 280 | + assert post_count == pre_count |
| 281 | + assert post_identifiers == original_identifiers |
0 commit comments