async def test_update_state_adds_entities_with_update_before_add_false(hass): """Test if not call update before add to state machine.""" component = EntityComponent(_LOGGER, DOMAIN, hass) ent = MockEntity() ent.update = Mock(spec_set=True) await component.async_add_entities([ent], False) await hass.async_block_till_done() assert len(hass.states.async_entity_ids()) == 1 assert not ent.update.called
def test_update_state_adds_entities_with_update_before_add_false(self): """Test if not call update before add to state machine.""" component = EntityComponent(_LOGGER, DOMAIN, self.hass) ent = MockEntity() ent.update = Mock(spec_set=True) component.add_entities([ent], False) self.hass.block_till_done() assert 1 == len(self.hass.states.entity_ids()) assert not ent.update.called
async def test_entity_disabled_by_integration(hass): """Test entity disabled by integration.""" component = EntityComponent(_LOGGER, DOMAIN, hass, timedelta(seconds=20)) entity_default = MockEntity(unique_id="default") entity_disabled = MockEntity(unique_id="disabled", entity_registry_enabled_default=False) await component.async_add_entities([entity_default, entity_disabled]) assert entity_default.hass is not None assert entity_default.platform is not None assert entity_disabled.hass is None assert entity_disabled.platform is None registry = await hass.helpers.entity_registry.async_get_registry() entry_default = registry.async_get_or_create(DOMAIN, DOMAIN, "default") assert entry_default.disabled_by is None entry_disabled = registry.async_get_or_create(DOMAIN, DOMAIN, "disabled") assert entry_disabled.disabled_by == "integration"
async def async_setup_entry(hass, config_entry, async_add_entities): """Mock setup entry method.""" async_add_entities([ # Invalid device info MockEntity(unique_id="abcd", device_info={}), # Valid device info MockEntity( unique_id="qwer", device_info={ "identifiers": {("hue", "1234")}, "connections": {("mac", "abcd")}, "manufacturer": "test-manuf", "model": "test-model", "name": "test-name", "sw_version": "test-sw", "entry_type": "service", "via_device": ("hue", "via-id"), }, ), ]) return True
async def test_extract_from_service_area_id(hass, area_mock): """Test the extraction using area ID as reference.""" entities = [ MockEntity(name="in_area", entity_id="light.in_area"), MockEntity(name="no_area", entity_id="light.no_area"), MockEntity(name="diff_area", entity_id="light.diff_area"), ] call = ha.ServiceCall("light", "turn_on", {"area_id": "test-area"}) extracted = await service.async_extract_entities(hass, entities, call) assert len(extracted) == 1 assert extracted[0].entity_id == "light.in_area" call = ha.ServiceCall("light", "turn_on", {"area_id": ["test-area", "diff-area"]}) extracted = await service.async_extract_entities(hass, entities, call) assert len(extracted) == 2 assert sorted(ent.entity_id for ent in extracted) == [ "light.diff_area", "light.in_area", ]
async def test_update_entity_require_restart(hass, client): """Test updating entity.""" config_entry = MockConfigEntry(domain="test_platform") config_entry.add_to_hass(hass) mock_registry( hass, { "test_domain.world": RegistryEntry( config_entry_id=config_entry.entry_id, entity_id="test_domain.world", unique_id="1234", # Using component.async_add_entities is equal to platform "domain" platform="test_platform", ) }, ) platform = MockEntityPlatform(hass) entity = MockEntity(unique_id="1234") await platform.async_add_entities([entity]) state = hass.states.get("test_domain.world") assert state is not None # UPDATE DISABLED_BY TO NONE await client.send_json( { "id": 8, "type": "config/entity_registry/update", "entity_id": "test_domain.world", "disabled_by": None, } ) msg = await client.receive_json() assert msg["result"] == { "entity_entry": { "config_entry_id": config_entry.entry_id, "device_id": None, "area_id": None, "disabled_by": None, "platform": "test_platform", "entity_id": "test_domain.world", "name": None, "icon": None, "original_name": None, "original_icon": None, "capabilities": None, "unique_id": "1234", }, "require_restart": True, }
async def test_update_entity_no_changes(hass, client): """Test update entity with no changes.""" mock_registry( hass, { "test_domain.world": RegistryEntry( entity_id="test_domain.world", unique_id="1234", # Using component.async_add_entities is equal to platform "domain" platform="test_platform", name="name of entity", ) }, ) platform = MockEntityPlatform(hass) entity = MockEntity(unique_id="1234") await platform.async_add_entities([entity]) state = hass.states.get("test_domain.world") assert state is not None assert state.name == "name of entity" await client.send_json( { "id": 6, "type": "config/entity_registry/update", "entity_id": "test_domain.world", "name": "name of entity", } ) msg = await client.receive_json() assert msg["result"] == { "entity_entry": { "config_entry_id": None, "device_id": None, "area_id": None, "disabled_by": None, "platform": "test_platform", "entity_id": "test_domain.world", "name": "name of entity", "icon": None, "original_name": None, "original_icon": None, "capabilities": None, "unique_id": "1234", } } state = hass.states.get("test_domain.world") assert state.name == "name of entity"
async def test_extract_from_service_no_group_expand(hass): """Test not expanding a group.""" component = EntityComponent(_LOGGER, DOMAIN, hass) await component.async_add_entities( [MockEntity(entity_id="group.test_group")]) call = ha.ServiceCall("test", "service", {"entity_id": ["group.test_group"]}) extracted = await component.async_extract_from_service(call, expand_group=False) assert len(extracted) == 1 assert extracted[0].entity_id == "group.test_group"
async def async_setup_entry(hass, config_entry, async_add_entities): """Mock setup entry method.""" async_add_entities([ # Valid device info, with homeassistant url MockEntity( unique_id="qwer", device_info={ "identifiers": {("mqtt", "1234")}, "configuration_url": None, }, ), ]) return True
async def test_extract_from_service_available_device(hass): """Test the extraction of entity from service and device is available.""" entities = [ MockEntity(name="test_1", entity_id="test_domain.test_1"), MockEntity(name="test_2", entity_id="test_domain.test_2", available=False), MockEntity(name="test_3", entity_id="test_domain.test_3"), MockEntity(name="test_4", entity_id="test_domain.test_4", available=False), ] call_1 = ha.ServiceCall("test", "service", data={"entity_id": ENTITY_MATCH_ALL}) assert ["test_domain.test_1", "test_domain.test_3"] == [ ent.entity_id for ent in (await service.async_extract_entities(hass, entities, call_1)) ] call_2 = ha.ServiceCall( "test", "service", data={"entity_id": ["test_domain.test_3", "test_domain.test_4"]}, ) assert ["test_domain.test_3"] == [ ent.entity_id for ent in (await service.async_extract_entities(hass, entities, call_2)) ] assert ( await service.async_extract_entities( hass, entities, ha.ServiceCall( "test", "service", data={"entity_id": ENTITY_MATCH_NONE}, ), ) == [] )
def test_name_which_conflict_with_registered(hass): """Test not generating conflicting entity ID based on name.""" component = EntityComponent(_LOGGER, DOMAIN, hass) registry = mock_registry(hass) # Register test_domain.world registry.async_get_or_create( DOMAIN, 'test', '1234', suggested_object_id='world') yield from component.async_add_entities([ MockEntity(name='world')]) assert 'test_domain.world_2' in hass.states.async_entity_ids()
def test_using_prescribed_entity_id_which_is_registered(hass): """Test not allowing predefined entity ID that already registered.""" component = EntityComponent(_LOGGER, DOMAIN, hass) registry = mock_registry(hass) # Register test_domain.world registry.async_get_or_create( DOMAIN, 'test', '1234', suggested_object_id='world') # This entity_id will be rewritten yield from component.async_add_entities([ MockEntity(entity_id='test_domain.world')]) assert 'test_domain.world_2' in hass.states.async_entity_ids()
async def async_setup_entry(hass, config_entry, async_add_entities): """Mock setup entry method.""" async_add_entities([ # Valid device info, but invalid url MockEntity( unique_id="qwer", device_info={ "identifiers": {("hue", "1234")}, "configuration_url": "foo://192.168.0.100/config", }, ), ]) return True
async def test_extract_from_service_fails_if_no_entity_id(opp): """Test the extraction of everything from service.""" component = EntityComponent(_LOGGER, DOMAIN, opp) await component.async_add_entities( [MockEntity(name="test_1"), MockEntity(name="test_2")] ) assert ( await component.async_extract_from_service(ha.ServiceCall("test", "service")) == [] ) assert ( await component.async_extract_from_service( ha.ServiceCall("test", "service", {"entity_id": ENTITY_MATCH_NONE}) ) == [] ) assert ( await component.async_extract_from_service( ha.ServiceCall("test", "service", {"area_id": ENTITY_MATCH_NONE}) ) == [] )
async def async_setup_entry(hass, config_entry, async_add_entities): """Mock setup entry method.""" async_add_entities([ # Invalid device info MockEntity(unique_id="abcd", device_info={}), # Valid device info MockEntity( unique_id="qwer", device_info={ "identifiers": {("hue", "1234")}, "configuration_url": "http://192.168.0.100/config", "connections": {(dr.CONNECTION_NETWORK_MAC, "abcd")}, "manufacturer": "test-manuf", "model": "test-model", "name": "test-name", "sw_version": "test-sw", "suggested_area": "Heliport", "entry_type": "service", "via_device": ("hue", "via-id"), }, ), ]) return True
async def test_update_entity(hass): """Test that we can update an entity with the helper.""" component = EntityComponent(_LOGGER, DOMAIN, hass) entity = MockEntity() entity.async_update_ha_state = Mock(return_value=mock_coro()) await component.async_add_entities([entity]) # Called as part of async_add_entities assert len(entity.async_update_ha_state.mock_calls) == 1 await hass.helpers.entity_component.async_update_entity(entity.entity_id) assert len(entity.async_update_ha_state.mock_calls) == 2 assert entity.async_update_ha_state.mock_calls[-1][1][0] is True
async def async_setup_entry(hass, config_entry, async_add_entities): """Mock setup entry method.""" async_add_entities([ MockEntity( unique_id="qwer", device_info={ "connections": {("mac", "abcd")}, "default_name": "default name 1", "default_model": "default model 1", "default_manufacturer": "default manufacturer 1", }, ) ]) return True
async def test_name_which_conflict_with_registered(hass): """Test not generating conflicting entity ID based on name.""" component = EntityComponent(_LOGGER, DOMAIN, hass) registry = mock_registry(hass) # Register test_domain.world registry.async_get_or_create(DOMAIN, "test", "1234", suggested_object_id="world") await component.async_add_entities([MockEntity(name="world")]) assert "test_domain.world_2" in hass.states.async_entity_ids()
async def test_raise_error_on_update(hass): """Test the add entity if they raise an error on update.""" updates = [] component = EntityComponent(_LOGGER, DOMAIN, hass) entity1 = MockEntity(name="test_1") entity2 = MockEntity(name="test_2") def _raise(): """Raise an exception.""" raise AssertionError entity1.update = _raise entity2.update = lambda: updates.append(1) await component.async_add_entities([entity1, entity2], True) assert len(updates) == 1 assert 1 in updates assert entity1.hass is None assert entity1.platform is None assert entity2.hass is not None assert entity2.platform is not None
def test_extract_from_service_available_device(hass): """Test the extraction of entity from service and device is available.""" component = EntityComponent(_LOGGER, DOMAIN, hass) yield from component.async_add_entities([ MockEntity(name='test_1'), MockEntity(name='test_2', available=False), MockEntity(name='test_3'), MockEntity(name='test_4', available=False), ]) call_1 = ha.ServiceCall('test', 'service') assert ['test_domain.test_1', 'test_domain.test_3'] == \ sorted(ent.entity_id for ent in component.async_extract_from_service(call_1)) call_2 = ha.ServiceCall('test', 'service', data={ 'entity_id': ['test_domain.test_3', 'test_domain.test_4'], }) assert ['test_domain.test_3'] == \ sorted(ent.entity_id for ent in component.async_extract_from_service(call_2))
async def test_using_prescribed_entity_id_which_is_registered(hass): """Test not allowing predefined entity ID that already registered.""" component = EntityComponent(_LOGGER, DOMAIN, hass) registry = mock_registry(hass) # Register test_domain.world registry.async_get_or_create(DOMAIN, "test", "1234", suggested_object_id="world") # This entity_id will be rewritten await component.async_add_entities( [MockEntity(entity_id="test_domain.world")]) assert "test_domain.world_2" in hass.states.async_entity_ids()
def test_polling_updates_entities_with_exception(self): """Test the updated entities that not break with an exception.""" component = EntityComponent(_LOGGER, DOMAIN, self.hass, timedelta(seconds=20)) update_ok = [] update_err = [] def update_mock(): """Mock normal update.""" update_ok.append(None) def update_mock_err(): """Mock error update.""" update_err.append(None) raise AssertionError("Fake error update") ent1 = MockEntity(should_poll=True) ent1.update = update_mock_err ent2 = MockEntity(should_poll=True) ent2.update = update_mock ent3 = MockEntity(should_poll=True) ent3.update = update_mock ent4 = MockEntity(should_poll=True) ent4.update = update_mock component.add_entities([ent1, ent2, ent3, ent4]) update_ok.clear() update_err.clear() fire_time_changed(self.hass, dt_util.utcnow() + timedelta(seconds=20)) self.hass.block_till_done() assert len(update_ok) == 3 assert len(update_err) == 1
async def async_setup_entry(hass, config_entry, async_add_entities): """Mock setup entry method.""" async_add_entities([ MockEntity( unique_id="qwer", device_info={ "identifiers": {("hue", "1234")}, "connections": {(dr.CONNECTION_NETWORK_MAC, "abcd")}, "name": "Device Bla", }, has_entity_name=has_entity_name, name=entity_name, ), ]) return True
async def test_update_entity(opp): """Test that we can update an entity with the helper.""" component = EntityComponent(_LOGGER, DOMAIN, opp) entity = MockEntity() entity.async_write_op_state = Mock() entity.async_update_op_state = AsyncMock(return_value=None) await component.async_add_entities([entity]) # Called as part of async_add_entities assert len(entity.async_write_op_state.mock_calls) == 1 await opp.helpers.entity_component.async_update_entity(entity.entity_id) assert len(entity.async_update_op_state.mock_calls) == 1 assert entity.async_update_op_state.mock_calls[-1][1][0] is True
async def test_register_entity_service(opp): """Test not expanding a group.""" entity = MockEntity(entity_id=f"{DOMAIN}.entity") calls = [] @ha.callback def appender(**kwargs): calls.append(kwargs) entity.async_called_by_service = appender component = EntityComponent(_LOGGER, DOMAIN, opp) await component.async_add_entities([entity]) component.async_register_entity_service( "hello", {"some": str}, "async_called_by_service" ) with pytest.raises(vol.Invalid): await opp.services.async_call( DOMAIN, "hello", {"entity_id": entity.entity_id, "invalid": "data"}, blocking=True, ) assert len(calls) == 0 await opp.services.async_call( DOMAIN, "hello", {"entity_id": entity.entity_id, "some": "data"}, blocking=True ) assert len(calls) == 1 assert calls[0] == {"some": "data"} await opp.services.async_call( DOMAIN, "hello", {"entity_id": ENTITY_MATCH_ALL, "some": "data"}, blocking=True ) assert len(calls) == 2 assert calls[1] == {"some": "data"} await opp.services.async_call( DOMAIN, "hello", {"entity_id": ENTITY_MATCH_NONE, "some": "data"}, blocking=True ) assert len(calls) == 2 await opp.services.async_call( DOMAIN, "hello", {"area_id": ENTITY_MATCH_NONE, "some": "data"}, blocking=True ) assert len(calls) == 2
async def test_update_entity_id(opp, client): """Test update entity id.""" mock_registry( opp, { "test_domain.world": RegistryEntry( entity_id="test_domain.world", unique_id="1234", # Using component.async_add_entities is equal to platform "domain" platform="test_platform", ) }, ) platform = MockEntityPlatform(opp) entity = MockEntity(unique_id="1234") await platform.async_add_entities([entity]) assert opp.states.get("test_domain.world") is not None await client.send_json({ "id": 6, "type": "config/entity_registry/update", "entity_id": "test_domain.world", "new_entity_id": "test_domain.planet", }) msg = await client.receive_json() assert msg["result"] == { "entity_entry": { "config_entry_id": None, "device_id": None, "area_id": None, "disabled_by": None, "platform": "test_platform", "entity_id": "test_domain.planet", "name": None, "icon": None, "original_name": None, "original_icon": None, "capabilities": None, "unique_id": "1234", } } assert opp.states.get("test_domain.world") is None assert opp.states.get("test_domain.planet") is not None
async def test_entity_registry_updates_invalid_entity_id(hass): """Test that we can't update to an invalid entity id.""" registry = mock_registry( hass, { "test_domain.world": er.RegistryEntry( entity_id="test_domain.world", unique_id="1234", # Using component.async_add_entities is equal to platform "domain" platform="test_platform", name="Some name", ), "test_domain.existing": er.RegistryEntry( entity_id="test_domain.existing", unique_id="5678", platform="test_platform", ), }, ) platform = MockEntityPlatform(hass) entity = MockEntity(unique_id="1234") await platform.async_add_entities([entity]) state = hass.states.get("test_domain.world") assert state is not None assert state.name == "Some name" with pytest.raises(ValueError): registry.async_update_entity( "test_domain.world", new_entity_id="test_domain.existing" ) with pytest.raises(ValueError): registry.async_update_entity( "test_domain.world", new_entity_id="invalid_entity_id" ) with pytest.raises(ValueError): registry.async_update_entity( "test_domain.world", new_entity_id="diff_domain.world" ) await hass.async_block_till_done() await hass.async_block_till_done() assert hass.states.get("test_domain.world") is not None assert hass.states.get("invalid_entity_id") is None assert hass.states.get("diff_domain.world") is None
async def test_update_entity_require_restart(hass, client): """Test updating entity.""" entity_id = "test_domain.test_platform_1234" config_entry = MockConfigEntry(domain="test_platform") config_entry.add_to_hass(hass) platform = MockEntityPlatform(hass) platform.config_entry = config_entry entity = MockEntity(unique_id="1234") await platform.async_add_entities([entity]) state = hass.states.get(entity_id) assert state is not None # UPDATE DISABLED_BY TO NONE await client.send_json( { "id": 8, "type": "config/entity_registry/update", "entity_id": entity_id, "disabled_by": None, } ) msg = await client.receive_json() assert msg["result"] == { "entity_entry": { "area_id": None, "capabilities": None, "config_entry_id": config_entry.entry_id, "device_class": None, "device_id": None, "disabled_by": None, "entity_category": None, "entity_id": entity_id, "icon": None, "hidden_by": None, "has_entity_name": False, "name": None, "options": {}, "original_device_class": None, "original_icon": None, "original_name": None, "platform": "test_platform", "unique_id": "1234", }, "require_restart": True, }
def test_registry_respect_entity_disabled(hass): """Test that the registry respects entity disabled.""" mock_registry(hass, { 'test_domain.world': entity_registry.RegistryEntry( entity_id='test_domain.world', unique_id='1234', # Using component.async_add_entities is equal to platform "domain" platform='test_platform', disabled_by=entity_registry.DISABLED_USER ) }) platform = MockEntityPlatform(hass) entity = MockEntity(unique_id='1234') yield from platform.async_add_entities([entity]) assert entity.entity_id is None assert hass.states.async_entity_ids() == []
async def test_enable_entity_disabled_device(hass, client, device_registry): """Test enabling entity of disabled device.""" config_entry = MockConfigEntry(domain="test_platform") config_entry.add_to_hass(hass) device = device_registry.async_get_or_create( config_entry_id="1234", connections={("ethernet", "12:34:56:78:90:AB:CD:EF")}, identifiers={("bridgeid", "0123")}, manufacturer="manufacturer", model="model", disabled_by=DISABLED_USER, ) mock_registry( hass, { "test_domain.world": RegistryEntry( config_entry_id=config_entry.entry_id, entity_id="test_domain.world", unique_id="1234", # Using component.async_add_entities is equal to platform "domain" platform="test_platform", device_id=device.id, ) }, ) platform = MockEntityPlatform(hass) entity = MockEntity(unique_id="1234") await platform.async_add_entities([entity]) state = hass.states.get("test_domain.world") assert state is not None # UPDATE DISABLED_BY TO NONE await client.send_json( { "id": 8, "type": "config/entity_registry/update", "entity_id": "test_domain.world", "disabled_by": None, } ) msg = await client.receive_json() assert not msg["success"]