async def setup_rfx_test_cfg( hass, device="abcd", automatic_add=False, devices: dict[str, dict] | None = None ): """Construct a rfxtrx config entry.""" entry_data = create_rfx_test_cfg( device=device, automatic_add=automatic_add, devices=devices ) mock_entry = MockConfigEntry(domain="rfxtrx", unique_id=DOMAIN, data=entry_data) mock_entry.supports_remove_device = True mock_entry.add_to_hass(hass) await hass.config_entries.async_setup(mock_entry.entry_id) await hass.async_block_till_done() await hass.async_start() return mock_entry
async def test_device_remove_non_tasmota_device(hass, device_reg, hass_ws_client, mqtt_mock, setup_tasmota): """Test removing a non Tasmota device through device registry.""" assert await async_setup_component(hass, "config", {}) async def async_remove_config_entry_device(hass, config_entry, device_entry): return True mock_integration( hass, MockModule( "test", async_remove_config_entry_device=async_remove_config_entry_device), ) config_entry = MockConfigEntry(domain="test") config_entry.supports_remove_device = True config_entry.add_to_hass(hass) mac = "12:34:56:AB:CD:EF" device_entry = device_reg.async_get_or_create( config_entry_id=config_entry.entry_id, connections={(dr.CONNECTION_NETWORK_MAC, mac)}, ) assert device_entry is not None await remove_device(hass, await hass_ws_client(hass), device_entry.id, config_entry.entry_id) await hass.async_block_till_done() # Verify device entry is removed device_entry = device_reg.async_get_device( set(), {(dr.CONNECTION_NETWORK_MAC, mac)}) assert device_entry is None # Verify no Tasmota discovery message was sent mqtt_mock.async_publish.assert_not_called()
async def test_remove_config_entry_from_device_fails(hass, hass_ws_client): """Test removing config entry from device failing cases.""" assert await async_setup_component(hass, "config", {}) ws_client = await hass_ws_client(hass) device_registry = mock_device_registry(hass) async def async_remove_config_entry_device(hass, config_entry, device_entry): return True mock_integration( hass, MockModule("comp1"), ) mock_integration( hass, MockModule( "comp2", async_remove_config_entry_device=async_remove_config_entry_device ), ) entry_1 = MockConfigEntry( domain="comp1", title="Test 1", source="bla", ) entry_1.add_to_hass(hass) entry_2 = MockConfigEntry( domain="comp2", title="Test 1", source="bla", ) entry_2.supports_remove_device = True entry_2.add_to_hass(hass) entry_3 = MockConfigEntry( domain="comp3", title="Test 1", source="bla", ) entry_3.supports_remove_device = True entry_3.add_to_hass(hass) device_registry.async_get_or_create( config_entry_id=entry_1.entry_id, connections={(helpers_dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) device_registry.async_get_or_create( config_entry_id=entry_2.entry_id, connections={(helpers_dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) device_entry = device_registry.async_get_or_create( config_entry_id=entry_3.entry_id, connections={(helpers_dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) assert device_entry.config_entries == { entry_1.entry_id, entry_2.entry_id, entry_3.entry_id, } fake_entry_id = "abc123" assert entry_1.entry_id != fake_entry_id fake_device_id = "abc123" assert device_entry.id != fake_device_id # Try removing a non existing config entry from the device await ws_client.send_json( { "id": 5, "type": "config/device_registry/remove_config_entry", "config_entry_id": fake_entry_id, "device_id": device_entry.id, } ) response = await ws_client.receive_json() assert not response["success"] assert response["error"]["code"] == "unknown_error" assert response["error"]["message"] == "Unknown config entry" # Try removing a config entry which does not support removal from the device await ws_client.send_json( { "id": 6, "type": "config/device_registry/remove_config_entry", "config_entry_id": entry_1.entry_id, "device_id": device_entry.id, } ) response = await ws_client.receive_json() assert not response["success"] assert response["error"]["code"] == "unknown_error" assert ( response["error"]["message"] == "Config entry does not support device removal" ) # Try removing a config entry from a device which does not exist await ws_client.send_json( { "id": 7, "type": "config/device_registry/remove_config_entry", "config_entry_id": entry_2.entry_id, "device_id": fake_device_id, } ) response = await ws_client.receive_json() assert not response["success"] assert response["error"]["code"] == "unknown_error" assert response["error"]["message"] == "Unknown device" # Try removing a config entry from a device which it's not connected to await ws_client.send_json( { "id": 8, "type": "config/device_registry/remove_config_entry", "config_entry_id": entry_2.entry_id, "device_id": device_entry.id, } ) response = await ws_client.receive_json() assert response["success"] assert set(response["result"]["config_entries"]) == { entry_1.entry_id, entry_3.entry_id, } await ws_client.send_json( { "id": 9, "type": "config/device_registry/remove_config_entry", "config_entry_id": entry_2.entry_id, "device_id": device_entry.id, } ) response = await ws_client.receive_json() assert not response["success"] assert response["error"]["code"] == "unknown_error" assert response["error"]["message"] == "Config entry not in device" # Try removing a config entry which can't be loaded from a device - allowed await ws_client.send_json( { "id": 10, "type": "config/device_registry/remove_config_entry", "config_entry_id": entry_3.entry_id, "device_id": device_entry.id, } ) response = await ws_client.receive_json() assert not response["success"] assert response["error"]["code"] == "unknown_error" assert response["error"]["message"] == "Integration not found"
async def test_remove_config_entry_from_device(hass, hass_ws_client): """Test removing config entry from device.""" assert await async_setup_component(hass, "config", {}) ws_client = await hass_ws_client(hass) device_registry = mock_device_registry(hass) can_remove = False async def async_remove_config_entry_device(hass, config_entry, device_entry): return can_remove mock_integration( hass, MockModule( "comp1", async_remove_config_entry_device=async_remove_config_entry_device ), ) mock_integration( hass, MockModule( "comp2", async_remove_config_entry_device=async_remove_config_entry_device ), ) entry_1 = MockConfigEntry( domain="comp1", title="Test 1", source="bla", ) entry_1.supports_remove_device = True entry_1.add_to_hass(hass) entry_2 = MockConfigEntry( domain="comp1", title="Test 1", source="bla", ) entry_2.supports_remove_device = True entry_2.add_to_hass(hass) device_registry.async_get_or_create( config_entry_id=entry_1.entry_id, connections={(helpers_dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) device_entry = device_registry.async_get_or_create( config_entry_id=entry_2.entry_id, connections={(helpers_dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) assert device_entry.config_entries == {entry_1.entry_id, entry_2.entry_id} # Try removing a config entry from the device, it should fail because # async_remove_config_entry_device returns False await ws_client.send_json( { "id": 5, "type": "config/device_registry/remove_config_entry", "config_entry_id": entry_1.entry_id, "device_id": device_entry.id, } ) response = await ws_client.receive_json() assert not response["success"] assert response["error"]["code"] == "unknown_error" # Make async_remove_config_entry_device return True can_remove = True # Remove the 1st config entry await ws_client.send_json( { "id": 6, "type": "config/device_registry/remove_config_entry", "config_entry_id": entry_1.entry_id, "device_id": device_entry.id, } ) response = await ws_client.receive_json() assert response["success"] assert response["result"]["config_entries"] == [entry_2.entry_id] # Check that the config entry was removed from the device assert device_registry.async_get(device_entry.id).config_entries == { entry_2.entry_id } # Remove the 2nd config entry await ws_client.send_json( { "id": 7, "type": "config/device_registry/remove_config_entry", "config_entry_id": entry_2.entry_id, "device_id": device_entry.id, } ) response = await ws_client.receive_json() assert response["success"] assert response["result"] is None # This was the last config entry, the device is removed assert not device_registry.async_get(device_entry.id)