|
4 | 4 | from datetime import timedelta |
5 | 5 | import logging |
6 | 6 | from types import MappingProxyType |
7 | | -from unittest.mock import AsyncMock, patch |
| 7 | +from unittest.mock import AsyncMock |
8 | 8 |
|
9 | 9 | from freezegun.api import FrozenDateTimeFactory |
10 | 10 | from librehardwaremonitor_api import ( |
|
26 | 26 | from homeassistant.const import STATE_UNAVAILABLE, STATE_UNKNOWN |
27 | 27 | from homeassistant.core import HomeAssistant |
28 | 28 | from homeassistant.helpers import device_registry as dr, entity_registry as er |
| 29 | +from homeassistant.helpers.device_registry import DeviceEntry |
29 | 30 |
|
30 | 31 | from . import init_integration |
31 | 32 |
|
@@ -152,42 +153,74 @@ async def test_sensor_state_is_unknown_when_no_sensor_data_is_provided( |
152 | 153 | assert state.state == STATE_UNKNOWN |
153 | 154 |
|
154 | 155 |
|
155 | | -async def test_orphaned_devices_are_removed( |
| 156 | +async def test_orphaned_devices_are_removed_if_not_present_after_update( |
156 | 157 | hass: HomeAssistant, |
157 | 158 | mock_lhm_client: AsyncMock, |
158 | 159 | mock_config_entry: MockConfigEntry, |
159 | 160 | freezer: FrozenDateTimeFactory, |
| 161 | + device_registry: dr.DeviceRegistry, |
160 | 162 | ) -> None: |
161 | | - """Test that devices in HA that do not receive updates are removed.""" |
| 163 | + """Test that devices in HA that are not found in LHM's data after sensor update are removed.""" |
| 164 | + orphaned_device = await _mock_orphaned_device( |
| 165 | + device_registry, hass, mock_config_entry, mock_lhm_client |
| 166 | + ) |
| 167 | + |
| 168 | + freezer.tick(timedelta(DEFAULT_SCAN_INTERVAL)) |
| 169 | + async_fire_time_changed(hass) |
| 170 | + await hass.async_block_till_done() |
| 171 | + |
| 172 | + assert device_registry.async_get(orphaned_device.id) is None |
| 173 | + |
| 174 | + |
| 175 | +async def test_orphaned_devices_are_removed_if_not_present_during_startup( |
| 176 | + hass: HomeAssistant, |
| 177 | + mock_lhm_client: AsyncMock, |
| 178 | + mock_config_entry: MockConfigEntry, |
| 179 | + device_registry: dr.DeviceRegistry, |
| 180 | +) -> None: |
| 181 | + """Test that devices in HA that are not found in LHM's data during integration startup are removed.""" |
| 182 | + orphaned_device = await _mock_orphaned_device( |
| 183 | + device_registry, hass, mock_config_entry, mock_lhm_client |
| 184 | + ) |
| 185 | + |
| 186 | + hass.config_entries.async_schedule_reload(mock_config_entry.entry_id) |
| 187 | + |
| 188 | + assert device_registry.async_get(orphaned_device.id) is None |
| 189 | + |
| 190 | + |
| 191 | +async def _mock_orphaned_device( |
| 192 | + device_registry: dr.DeviceRegistry, |
| 193 | + hass: HomeAssistant, |
| 194 | + mock_config_entry: MockConfigEntry, |
| 195 | + mock_lhm_client: AsyncMock, |
| 196 | +) -> DeviceEntry: |
162 | 197 | await init_integration(hass, mock_config_entry) |
163 | 198 |
|
| 199 | + removed_device = "lpc-nct6687d-0" |
| 200 | + previous_data = mock_lhm_client.get_data.return_value |
| 201 | + |
164 | 202 | mock_lhm_client.get_data.return_value = LibreHardwareMonitorData( |
165 | 203 | main_device_ids_and_names=MappingProxyType( |
166 | 204 | { |
167 | | - DeviceId("amdcpu-0"): DeviceName("AMD Ryzen 7 7800X3D"), |
168 | | - DeviceId("gpu-nvidia-0"): DeviceName("NVIDIA GeForce RTX 4080 SUPER"), |
| 205 | + device_id: name |
| 206 | + for (device_id, name) in previous_data.main_device_ids_and_names.items() |
| 207 | + if device_id != removed_device |
| 208 | + } |
| 209 | + ), |
| 210 | + sensor_data=MappingProxyType( |
| 211 | + { |
| 212 | + sensor_id: data |
| 213 | + for (sensor_id, data) in previous_data.sensor_data.items() |
| 214 | + if not sensor_id.startswith(removed_device) |
169 | 215 | } |
170 | 216 | ), |
171 | | - sensor_data=mock_lhm_client.get_data.return_value.sensor_data, |
172 | 217 | ) |
173 | 218 |
|
174 | | - device_registry = dr.async_get(hass) |
175 | | - orphaned_device = device_registry.async_get_or_create( |
| 219 | + return device_registry.async_get_or_create( |
176 | 220 | config_entry_id=mock_config_entry.entry_id, |
177 | | - identifiers={(DOMAIN, f"{mock_config_entry.entry_id}_lpc-nct6687d-0")}, |
| 221 | + identifiers={(DOMAIN, f"{mock_config_entry.entry_id}_{removed_device}")}, |
178 | 222 | ) |
179 | 223 |
|
180 | | - with patch.object( |
181 | | - device_registry, |
182 | | - "async_remove_device", |
183 | | - wraps=device_registry.async_update_device, |
184 | | - ) as mock_remove: |
185 | | - freezer.tick(timedelta(DEFAULT_SCAN_INTERVAL)) |
186 | | - async_fire_time_changed(hass) |
187 | | - await hass.async_block_till_done() |
188 | | - |
189 | | - mock_remove.assert_called_once_with(orphaned_device.id) |
190 | | - |
191 | 224 |
|
192 | 225 | async def test_integration_does_not_log_new_devices_on_first_refresh( |
193 | 226 | hass: HomeAssistant, |
|
0 commit comments