async def test_extract_entity_ids_from_area(hass): """Test extract_entity_ids method with areas.""" hass.states.async_set('light.Bowl', STATE_ON) hass.states.async_set('light.Ceiling', STATE_OFF) hass.states.async_set('light.Kitchen', STATE_OFF) device_in_area = dev_reg.DeviceEntry(area_id='test-area') device_no_area = dev_reg.DeviceEntry() device_diff_area = dev_reg.DeviceEntry(area_id='diff-area') mock_device_registry(hass, { device_in_area.id: device_in_area, device_no_area.id: device_no_area, device_diff_area.id: device_diff_area, }) entity_in_area = ent_reg.RegistryEntry( entity_id='light.in_area', unique_id='in-area-id', platform='test', device_id=device_in_area.id, ) entity_no_area = ent_reg.RegistryEntry( entity_id='light.no_area', unique_id='no-area-id', platform='test', device_id=device_no_area.id, ) entity_diff_area = ent_reg.RegistryEntry( entity_id='light.diff_area', unique_id='diff-area-id', platform='test', device_id=device_diff_area.id, ) mock_registry(hass, { entity_in_area.entity_id: entity_in_area, entity_no_area.entity_id: entity_no_area, entity_diff_area.entity_id: entity_diff_area, }) call = ha.ServiceCall('light', 'turn_on', {'area_id': 'test-area'}) assert {'light.in_area'} == \ await service.async_extract_entity_ids(hass, call) call = ha.ServiceCall('light', 'turn_on', {'area_id': ['test-area', 'diff-area']}) assert {'light.in_area', 'light.diff_area'} == \ await service.async_extract_entity_ids(hass, call)
def test_entities_areas_area_true(hass): """Test entity ID policy for areas with specific area.""" entity_registry = mock_registry(hass, { 'light.kitchen': RegistryEntry( entity_id='light.kitchen', unique_id='1234', platform='test_platform', device_id='mock-dev-id' ), }) device_registry = mock_device_registry(hass, { 'mock-dev-id': DeviceEntry( id='mock-dev-id', area_id='mock-area-id' ) }) policy = { 'area_ids': { 'mock-area-id': { 'read': True, 'control': True, } } } ENTITY_POLICY_SCHEMA(policy) compiled = compile_entities(policy, PermissionLookup( entity_registry, device_registry )) assert compiled('light.kitchen', 'read') is True assert compiled('light.kitchen', 'control') is True assert compiled('light.kitchen', 'edit') is False assert compiled('switch.kitchen', 'read') is False
def test_entities_device_id_boolean(hass): """Test entity ID policy applying control on device id.""" entity_registry = mock_registry(hass, { 'test_domain.allowed': RegistryEntry( entity_id='test_domain.allowed', unique_id='1234', platform='test_platform', device_id='mock-allowed-dev-id' ), 'test_domain.not_allowed': RegistryEntry( entity_id='test_domain.not_allowed', unique_id='5678', platform='test_platform', device_id='mock-not-allowed-dev-id' ), }) device_registry = mock_device_registry(hass) policy = { 'device_ids': { 'mock-allowed-dev-id': { 'read': True, } } } ENTITY_POLICY_SCHEMA(policy) compiled = compile_entities(policy, PermissionLookup( entity_registry, device_registry )) assert compiled('test_domain.allowed', 'read') is True assert compiled('test_domain.allowed', 'control') is False assert compiled('test_domain.not_allowed', 'read') is False assert compiled('test_domain.not_allowed', 'control') is False
def registries(hass): """Registry mock setup.""" from types import SimpleNamespace ret = SimpleNamespace() ret.entity = mock_registry(hass) ret.device = mock_device_registry(hass) ret.area = mock_area_registry(hass) return ret
def area_mock(opp): """Mock including area info.""" opp.states.async_set("light.Bowl", STATE_ON) opp.states.async_set("light.Ceiling", STATE_OFF) opp.states.async_set("light.Kitchen", STATE_OFF) device_in_area = dev_reg.DeviceEntry(area_id="test-area") device_no_area = dev_reg.DeviceEntry(id="device-no-area-id") device_diff_area = dev_reg.DeviceEntry(area_id="diff-area") device_area_a = dev_reg.DeviceEntry(id="device-area-a-id", area_id="area-a") mock_device_registry( opp, { device_in_area.id: device_in_area, device_no_area.id: device_no_area, device_diff_area.id: device_diff_area, device_area_a.id: device_area_a, }, ) entity_in_own_area = ent_reg.RegistryEntry( entity_id="light.in_own_area", unique_id="in-own-area-id", platform="test", area_id="own-area", ) entity_in_area = ent_reg.RegistryEntry( entity_id="light.in_area", unique_id="in-area-id", platform="test", device_id=device_in_area.id, ) entity_in_other_area = ent_reg.RegistryEntry( entity_id="light.in_other_area", unique_id="in-area-a-id", platform="test", device_id=device_in_area.id, area_id="other-area", ) entity_assigned_to_area = ent_reg.RegistryEntry( entity_id="light.assigned_to_area", unique_id="assigned-area-id", platform="test", device_id=device_in_area.id, area_id="test-area", ) entity_no_area = ent_reg.RegistryEntry( entity_id="light.no_area", unique_id="no-area-id", platform="test", device_id=device_no_area.id, ) entity_diff_area = ent_reg.RegistryEntry( entity_id="light.diff_area", unique_id="diff-area-id", platform="test", device_id=device_diff_area.id, ) entity_in_area_a = ent_reg.RegistryEntry( entity_id="light.in_area_a", unique_id="in-area-a-id", platform="test", device_id=device_area_a.id, area_id="area-a", ) entity_in_area_b = ent_reg.RegistryEntry( entity_id="light.in_area_b", unique_id="in-area-b-id", platform="test", device_id=device_area_a.id, area_id="area-b", ) mock_registry( opp, { entity_in_own_area.entity_id: entity_in_own_area, entity_in_area.entity_id: entity_in_area, entity_in_other_area.entity_id: entity_in_other_area, entity_assigned_to_area.entity_id: entity_assigned_to_area, entity_no_area.entity_id: entity_no_area, entity_diff_area.entity_id: entity_diff_area, entity_in_area_a.entity_id: entity_in_area_a, entity_in_area_b.entity_id: entity_in_area_b, }, )
def registry(hass): """Return a configured device registry.""" return mock_device_registry(hass)
async def test_disable_config_entry_disables_entities(hass, registry): """Test that we disable entities tied to a config entry.""" device_registry = mock_device_registry(hass) config_entry = MockConfigEntry(domain="light") config_entry.add_to_hass(hass) device_entry = device_registry.async_get_or_create( config_entry_id=config_entry.entry_id, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) entry1 = registry.async_get_or_create( "light", "hue", "5678", config_entry=config_entry, device_id=device_entry.id, ) entry2 = registry.async_get_or_create( "light", "hue", "ABCD", config_entry=config_entry, device_id=device_entry.id, disabled_by=er.DISABLED_USER, ) entry3 = registry.async_get_or_create( "light", "hue", "EFGH", config_entry=config_entry, device_id=device_entry.id, disabled_by=er.DISABLED_DEVICE, ) assert not entry1.disabled assert entry2.disabled assert entry3.disabled await hass.config_entries.async_set_disabled_by( config_entry.entry_id, config_entries.DISABLED_USER) await hass.async_block_till_done() entry1 = registry.async_get(entry1.entity_id) assert entry1.disabled assert entry1.disabled_by == er.DISABLED_CONFIG_ENTRY entry2 = registry.async_get(entry2.entity_id) assert entry2.disabled assert entry2.disabled_by == er.DISABLED_USER entry3 = registry.async_get(entry3.entity_id) assert entry3.disabled assert entry3.disabled_by == er.DISABLED_DEVICE await hass.config_entries.async_set_disabled_by(config_entry.entry_id, None) await hass.async_block_till_done() entry1 = registry.async_get(entry1.entity_id) assert not entry1.disabled entry2 = registry.async_get(entry2.entity_id) assert entry2.disabled assert entry2.disabled_by == er.DISABLED_USER # The device was re-enabled, so entity disabled by the device will be re-enabled too entry3 = registry.async_get(entry3.entity_id) assert not entry3.disabled_by
def mock_device_reg(opp): """Get standard device.""" return mock_device_registry(opp)
def device_reg(hass: HomeAssistant) -> device_registry.DeviceRegistry: """Return an empty, loaded, registry.""" return mock_device_registry(hass)
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)
def registry(opp): """Return an empty, loaded, registry.""" return mock_device_registry(opp)
async def test_disable_device_disables_entities(hass, registry): """Test that we disable entities tied to a device.""" device_registry = mock_device_registry(hass) config_entry = MockConfigEntry(domain="light") config_entry.add_to_hass(hass) device_entry = device_registry.async_get_or_create( config_entry_id=config_entry.entry_id, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) entry1 = registry.async_get_or_create( "light", "hue", "5678", config_entry=config_entry, device_id=device_entry.id, ) entry2 = registry.async_get_or_create( "light", "hue", "ABCD", config_entry=config_entry, device_id=device_entry.id, disabled_by=er.RegistryEntryDisabler.USER, ) entry3 = registry.async_get_or_create( "light", "hue", "EFGH", config_entry=config_entry, device_id=device_entry.id, disabled_by=er.RegistryEntryDisabler.CONFIG_ENTRY, ) assert not entry1.disabled assert entry2.disabled assert entry3.disabled device_registry.async_update_device( device_entry.id, disabled_by=dr.DeviceEntryDisabler.USER) await hass.async_block_till_done() entry1 = registry.async_get(entry1.entity_id) assert entry1.disabled assert entry1.disabled_by is er.RegistryEntryDisabler.DEVICE entry2 = registry.async_get(entry2.entity_id) assert entry2.disabled assert entry2.disabled_by is er.RegistryEntryDisabler.USER entry3 = registry.async_get(entry3.entity_id) assert entry3.disabled assert entry3.disabled_by is er.RegistryEntryDisabler.CONFIG_ENTRY device_registry.async_update_device(device_entry.id, disabled_by=None) await hass.async_block_till_done() entry1 = registry.async_get(entry1.entity_id) assert not entry1.disabled entry2 = registry.async_get(entry2.entity_id) assert entry2.disabled assert entry2.disabled_by is er.RegistryEntryDisabler.USER entry3 = registry.async_get(entry3.entity_id) assert entry3.disabled assert entry3.disabled_by is er.RegistryEntryDisabler.CONFIG_ENTRY
def area_mock(hass): """Mock including area info.""" hass.states.async_set("light.Bowl", STATE_ON) hass.states.async_set("light.Ceiling", STATE_OFF) hass.states.async_set("light.Kitchen", STATE_OFF) device_in_area = dev_reg.DeviceEntry(area_id="test-area") device_no_area = dev_reg.DeviceEntry(id="device-no-area-id") device_diff_area = dev_reg.DeviceEntry(area_id="diff-area") device_area_a = dev_reg.DeviceEntry(id="device-area-a-id", area_id="area-a") mock_device_registry( hass, { device_in_area.id: device_in_area, device_no_area.id: device_no_area, device_diff_area.id: device_diff_area, device_area_a.id: device_area_a, }, ) entity_in_own_area = ent_reg.RegistryEntry( entity_id="light.in_own_area", unique_id="in-own-area-id", platform="test", area_id="own-area", ) config_entity_in_own_area = ent_reg.RegistryEntry( entity_id="light.config_in_own_area", unique_id="config-in-own-area-id", platform="test", area_id="own-area", entity_category=EntityCategory.CONFIG, ) hidden_entity_in_own_area = ent_reg.RegistryEntry( entity_id="light.hidden_in_own_area", unique_id="hidden-in-own-area-id", platform="test", area_id="own-area", hidden_by=ent_reg.RegistryEntryHider.USER, ) entity_in_area = ent_reg.RegistryEntry( entity_id="light.in_area", unique_id="in-area-id", platform="test", device_id=device_in_area.id, ) config_entity_in_area = ent_reg.RegistryEntry( entity_id="light.config_in_area", unique_id="config-in-area-id", platform="test", device_id=device_in_area.id, entity_category=EntityCategory.CONFIG, ) hidden_entity_in_area = ent_reg.RegistryEntry( entity_id="light.hidden_in_area", unique_id="hidden-in-area-id", platform="test", device_id=device_in_area.id, hidden_by=ent_reg.RegistryEntryHider.USER, ) entity_in_other_area = ent_reg.RegistryEntry( entity_id="light.in_other_area", unique_id="in-area-a-id", platform="test", device_id=device_in_area.id, area_id="other-area", ) entity_assigned_to_area = ent_reg.RegistryEntry( entity_id="light.assigned_to_area", unique_id="assigned-area-id", platform="test", device_id=device_in_area.id, area_id="test-area", ) entity_no_area = ent_reg.RegistryEntry( entity_id="light.no_area", unique_id="no-area-id", platform="test", device_id=device_no_area.id, ) config_entity_no_area = ent_reg.RegistryEntry( entity_id="light.config_no_area", unique_id="config-no-area-id", platform="test", device_id=device_no_area.id, entity_category=EntityCategory.CONFIG, ) hidden_entity_no_area = ent_reg.RegistryEntry( entity_id="light.hidden_no_area", unique_id="hidden-no-area-id", platform="test", device_id=device_no_area.id, hidden_by=ent_reg.RegistryEntryHider.USER, ) entity_diff_area = ent_reg.RegistryEntry( entity_id="light.diff_area", unique_id="diff-area-id", platform="test", device_id=device_diff_area.id, ) entity_in_area_a = ent_reg.RegistryEntry( entity_id="light.in_area_a", unique_id="in-area-a-id", platform="test", device_id=device_area_a.id, area_id="area-a", ) entity_in_area_b = ent_reg.RegistryEntry( entity_id="light.in_area_b", unique_id="in-area-b-id", platform="test", device_id=device_area_a.id, area_id="area-b", ) mock_registry( hass, { entity_in_own_area.entity_id: entity_in_own_area, config_entity_in_own_area.entity_id: config_entity_in_own_area, hidden_entity_in_own_area.entity_id: hidden_entity_in_own_area, entity_in_area.entity_id: entity_in_area, config_entity_in_area.entity_id: config_entity_in_area, hidden_entity_in_area.entity_id: hidden_entity_in_area, entity_in_other_area.entity_id: entity_in_other_area, entity_assigned_to_area.entity_id: entity_assigned_to_area, entity_no_area.entity_id: entity_no_area, config_entity_no_area.entity_id: config_entity_no_area, hidden_entity_no_area.entity_id: hidden_entity_no_area, entity_diff_area.entity_id: entity_diff_area, entity_in_area_a.entity_id: entity_in_area_a, entity_in_area_b.entity_id: entity_in_area_b, }, )
def device_reg(opp: OpenPeerPower) -> device_registry.DeviceRegistry: """Return an empty, loaded, registry.""" return mock_device_registry(opp)
def registry(hass): """Return a configured device registry.""" return mock_device_registry(hass)
async def test_disable_config_entry_disables_entities(hass, registry): """Test that we disable entities tied to a config entry.""" device_registry = mock_device_registry(hass) config_entry = MockConfigEntry(domain="light") config_entry.add_to_hass(hass) device_entry = device_registry.async_get_or_create( config_entry_id=config_entry.entry_id, connections={("mac", "12:34:56:AB:CD:EF")}, ) entry1 = registry.async_get_or_create( "light", "hue", "5678", config_entry=config_entry, device_id=device_entry.id, ) entry2 = registry.async_get_or_create( "light", "hue", "ABCD", config_entry=config_entry, device_id=device_entry.id, disabled_by="user", ) entry3 = registry.async_get_or_create( "light", "hue", "EFGH", config_entry=config_entry, device_id=device_entry.id, disabled_by="device", ) assert not entry1.disabled assert entry2.disabled assert entry3.disabled await hass.config_entries.async_set_disabled_by(config_entry.entry_id, "user") await hass.async_block_till_done() entry1 = registry.async_get(entry1.entity_id) assert entry1.disabled assert entry1.disabled_by == "config_entry" entry2 = registry.async_get(entry2.entity_id) assert entry2.disabled assert entry2.disabled_by == "user" entry3 = registry.async_get(entry3.entity_id) assert entry3.disabled assert entry3.disabled_by == "device" await hass.config_entries.async_set_disabled_by(config_entry.entry_id, None) await hass.async_block_till_done() entry1 = registry.async_get(entry1.entity_id) assert not entry1.disabled entry2 = registry.async_get(entry2.entity_id) assert entry2.disabled assert entry2.disabled_by == "user" # The device was re-enabled, so entity disabled by the device will be re-enabled too entry3 = registry.async_get(entry3.entity_id) assert not entry3.disabled_by
def zwave_migration_data_fixture(hass): """Return mock zwave migration data.""" zwave_source_node_device = DeviceEntry( id=ZWAVE_SOURCE_NODE_DEVICE_ID, name_by_user=ZWAVE_SOURCE_NODE_DEVICE_NAME, area_id=ZWAVE_SOURCE_NODE_DEVICE_AREA, ) zwave_source_node_entry = RegistryEntry( entity_id=ZWAVE_SOURCE_ENTITY, unique_id=ZWAVE_SOURCE_NODE_UNIQUE_ID, platform="zwave", name="Z-Wave Source Node", ) zwave_battery_device = DeviceEntry( id=ZWAVE_BATTERY_DEVICE_ID, name_by_user=ZWAVE_BATTERY_DEVICE_NAME, area_id=ZWAVE_BATTERY_DEVICE_AREA, ) zwave_battery_entry = RegistryEntry( entity_id=ZWAVE_BATTERY_ENTITY, unique_id=ZWAVE_BATTERY_UNIQUE_ID, platform="zwave", name=ZWAVE_BATTERY_NAME, icon=ZWAVE_BATTERY_ICON, ) zwave_power_device = DeviceEntry( id=ZWAVE_POWER_DEVICE_ID, name_by_user=ZWAVE_POWER_DEVICE_NAME, area_id=ZWAVE_POWER_DEVICE_AREA, ) zwave_power_entry = RegistryEntry( entity_id=ZWAVE_POWER_ENTITY, unique_id=ZWAVE_POWER_UNIQUE_ID, platform="zwave", name=ZWAVE_POWER_NAME, icon=ZWAVE_POWER_ICON, ) zwave_migration_data = { ZWAVE_SOURCE_NODE_UNIQUE_ID: { "node_id": 10, "node_instance": 1, "device_id": zwave_source_node_device.id, "command_class": 113, "command_class_label": "SourceNodeId", "value_index": 2, "unique_id": ZWAVE_SOURCE_NODE_UNIQUE_ID, "entity_entry": zwave_source_node_entry, }, ZWAVE_BATTERY_UNIQUE_ID: { "node_id": 36, "node_instance": 1, "device_id": zwave_battery_device.id, "command_class": 128, "command_class_label": "Battery Level", "value_index": 0, "unique_id": ZWAVE_BATTERY_UNIQUE_ID, "entity_entry": zwave_battery_entry, }, ZWAVE_POWER_UNIQUE_ID: { "node_id": 32, "node_instance": 1, "device_id": zwave_power_device.id, "command_class": 50, "command_class_label": "Power", "value_index": 8, "unique_id": ZWAVE_POWER_UNIQUE_ID, "entity_entry": zwave_power_entry, }, } mock_device_registry( hass, { zwave_source_node_device.id: zwave_source_node_device, zwave_battery_device.id: zwave_battery_device, zwave_power_device.id: zwave_power_device, }, ) mock_registry( hass, { ZWAVE_SOURCE_ENTITY: zwave_source_node_entry, ZWAVE_BATTERY_ENTITY: zwave_battery_entry, ZWAVE_POWER_ENTITY: zwave_power_entry, }, ) return zwave_migration_data
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"
def device_reg(hass): """Return an empty, loaded, registry.""" return mock_device_registry(hass)
def mock_device_reg(hass): """Get standard device.""" return mock_device_registry(hass)
async def test_sensors_flex(hass, canary) -> None: """Test the creation and values of the sensors for Canary Flex.""" await async_setup_component(hass, "persistent_notification", {}) registry = mock_registry(hass) device_registry = mock_device_registry(hass) online_device_at_home = mock_device(20, "Dining Room", True, "Canary Flex") instance = canary.return_value instance.get_locations.return_value = [ mock_location(100, "Home", True, devices=[online_device_at_home]), ] instance.get_latest_readings.return_value = [ mock_reading("battery", "70.4567"), mock_reading("wifi", "-57"), ] config = { DOMAIN: { "username": "******", "password": "******" } } with patch("homeassistant.components.canary.PLATFORMS", ["sensor"]): assert await async_setup_component(hass, DOMAIN, config) await hass.async_block_till_done() sensors = { "home_dining_room_battery": ( "20_battery", "70.46", PERCENTAGE, DEVICE_CLASS_BATTERY, None, ), "home_dining_room_wifi": ( "20_wifi", "-57.0", SIGNAL_STRENGTH_DECIBELS_MILLIWATT, DEVICE_CLASS_SIGNAL_STRENGTH, None, ), } for (sensor_id, data) in sensors.items(): entity_entry = registry.async_get(f"sensor.{sensor_id}") assert entity_entry assert entity_entry.device_class == data[3] assert entity_entry.unique_id == data[0] assert entity_entry.original_icon == data[4] state = hass.states.get(f"sensor.{sensor_id}") assert state assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == data[2] assert state.state == data[1] device = device_registry.async_get_device({(DOMAIN, "20")}, set()) assert device assert device.manufacturer == MANUFACTURER assert device.name == "Dining Room" assert device.model == "Canary Flex"
async def test_sensors_pro(hass, canary) -> None: """Test the creation and values of the sensors for Canary Pro.""" await async_setup_component(hass, "persistent_notification", {}) registry = mock_registry(hass) device_registry = mock_device_registry(hass) online_device_at_home = mock_device(20, "Dining Room", True, "Canary Pro") instance = canary.return_value instance.get_locations.return_value = [ mock_location(100, "Home", True, devices=[online_device_at_home]), ] instance.get_latest_readings.return_value = [ mock_reading("temperature", "21.12"), mock_reading("humidity", "50.46"), mock_reading("air_quality", "0.59"), ] config = { DOMAIN: { "username": "******", "password": "******" } } with patch("homeassistant.components.canary.PLATFORMS", ["sensor"]): assert await async_setup_component(hass, DOMAIN, config) await hass.async_block_till_done() sensors = { "home_dining_room_temperature": ( "20_temperature", "21.12", TEMP_CELSIUS, DEVICE_CLASS_TEMPERATURE, None, ), "home_dining_room_humidity": ( "20_humidity", "50.46", PERCENTAGE, DEVICE_CLASS_HUMIDITY, None, ), "home_dining_room_air_quality": ( "20_air_quality", "0.59", None, None, "mdi:weather-windy", ), } for (sensor_id, data) in sensors.items(): entity_entry = registry.async_get(f"sensor.{sensor_id}") assert entity_entry assert entity_entry.device_class == data[3] assert entity_entry.unique_id == data[0] assert entity_entry.original_icon == data[4] state = hass.states.get(f"sensor.{sensor_id}") assert state assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == data[2] assert state.state == data[1] device = device_registry.async_get_device({(DOMAIN, "20")}, set()) assert device assert device.manufacturer == MANUFACTURER assert device.name == "Dining Room" assert device.model == "Canary Pro"
def registry(hass): """Return an empty, loaded, registry.""" return mock_device_registry(hass)
async def test_remove_config_entry_from_device_removes_entities(hass, registry): """Test that we remove entities tied to a device when config entry is removed.""" device_registry = mock_device_registry(hass) config_entry_1 = MockConfigEntry(domain="hue") config_entry_2 = MockConfigEntry(domain="device_tracker") # Create device with two config entries device_registry.async_get_or_create( config_entry_id=config_entry_1.entry_id, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) device_entry = device_registry.async_get_or_create( config_entry_id=config_entry_2.entry_id, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) assert device_entry.config_entries == { config_entry_1.entry_id, config_entry_2.entry_id, } # Create one entity for each config entry entry_1 = registry.async_get_or_create( "light", "hue", "5678", config_entry=config_entry_1, device_id=device_entry.id, ) entry_2 = registry.async_get_or_create( "sensor", "device_tracker", "6789", config_entry=config_entry_2, device_id=device_entry.id, ) assert registry.async_is_registered(entry_1.entity_id) assert registry.async_is_registered(entry_2.entity_id) # Remove the first config entry from the device, the entity associated with it # should be removed device_registry.async_update_device( device_entry.id, remove_config_entry_id=config_entry_1.entry_id ) await hass.async_block_till_done() assert device_registry.async_get(device_entry.id) assert not registry.async_is_registered(entry_1.entity_id) assert registry.async_is_registered(entry_2.entity_id) # Remove the second config entry from the device, the entity associated with it # (and the device itself) should be removed device_registry.async_update_device( device_entry.id, remove_config_entry_id=config_entry_2.entry_id ) await hass.async_block_till_done() assert not device_registry.async_get(device_entry.id) assert not registry.async_is_registered(entry_1.entity_id) assert not registry.async_is_registered(entry_2.entity_id)