async def test_platform_warn_slow_setup(hass): """Warn we log when platform setup takes a long time.""" platform = MockPlatform() mock_entity_platform(hass, 'test_domain.platform', platform) component = EntityComponent(_LOGGER, DOMAIN, hass) with patch.object(hass.loop, 'call_later', MagicMock()) \ as mock_call: await component.async_setup({DOMAIN: { 'platform': 'platform', }}) assert mock_call.called # mock_calls[0] is the warning message for component setup # mock_calls[3] is the warning message for platform setup timeout, logger_method = mock_call.mock_calls[3][1][:2] assert timeout == entity_platform.SLOW_SETUP_WARNING assert logger_method == _LOGGER.warning assert mock_call().cancel.called
def test_setup_loads_platforms(self): """Test the loading of the platforms.""" component_setup = Mock(return_value=True) platform_setup = Mock(return_value=None) loader.set_component( 'test_component', MockModule('test_component', setup=component_setup)) loader.set_component('test_domain.mod2', MockPlatform(platform_setup, ['test_component'])) component = EntityComponent(_LOGGER, DOMAIN, self.hass) assert not component_setup.called assert not platform_setup.called component.setup({ DOMAIN: { 'platform': 'mod2', } }) assert component_setup.called assert platform_setup.called
async def test_reset_cancels_retry_setup_when_not_started(hass): """Test that resetting a platform will cancel scheduled a setup retry when not yet started.""" hass.state = CoreState.starting async_setup_entry = Mock(side_effect=PlatformNotReady) initial_listeners = hass.bus.async_listeners()[EVENT_HOMEASSISTANT_STARTED] platform = MockPlatform(async_setup_entry=async_setup_entry) config_entry = MockConfigEntry() ent_platform = MockEntityPlatform( hass, platform_name=config_entry.domain, platform=platform ) assert not await ent_platform.async_setup_entry(config_entry) await hass.async_block_till_done() assert ( hass.bus.async_listeners()[EVENT_HOMEASSISTANT_STARTED] == initial_listeners + 1 ) assert ent_platform._async_cancel_retry_setup is not None await ent_platform.async_reset() await hass.async_block_till_done() assert hass.bus.async_listeners()[EVENT_HOMEASSISTANT_STARTED] == initial_listeners assert ent_platform._async_cancel_retry_setup is None
async def test_setup_entry(hass): """Test we can setup an entry.""" registry = mock_registry(hass) async def async_setup_entry(hass, config_entry, async_add_entities): """Mock setup entry method.""" async_add_entities([MockEntity(name="test1", unique_id="unique")]) return True platform = MockPlatform(async_setup_entry=async_setup_entry) config_entry = MockConfigEntry(entry_id="super-mock-id") entity_platform = MockEntityPlatform(hass, platform_name=config_entry.domain, platform=platform) assert await entity_platform.async_setup_entry(config_entry) await hass.async_block_till_done() full_name = f"{entity_platform.domain}.{config_entry.domain}" assert full_name in hass.config.components assert len(hass.states.async_entity_ids()) == 1 assert len(registry.entities) == 1 assert registry.entities[ "test_domain.test1"].config_entry_id == "super-mock-id"
async def test_setup_entry_platform_not_ready_from_exception(hass, caplog): """Test when an entry is not ready yet that includes the causing exception string.""" original_exception = HomeAssistantError("The device dropped the connection") platform_exception = PlatformNotReady() platform_exception.__cause__ = original_exception async_setup_entry = Mock(side_effect=platform_exception) platform = MockPlatform(async_setup_entry=async_setup_entry) config_entry = MockConfigEntry() ent_platform = MockEntityPlatform( hass, platform_name=config_entry.domain, platform=platform ) with patch.object(entity_platform, "async_call_later") as mock_call_later: assert not await ent_platform.async_setup_entry(config_entry) full_name = f"{ent_platform.domain}.{config_entry.domain}" assert full_name not in hass.config.components assert len(async_setup_entry.mock_calls) == 1 assert "Platform test not ready yet" in caplog.text assert "The device dropped the connection" in caplog.text assert len(mock_call_later.mock_calls) == 1
async def test_parallel_updates_sync_platform(hass): """Test sync platform parallel_updates default set to 1.""" platform = MockPlatform() mock_entity_platform(hass, "test_domain.platform", platform) component = EntityComponent(_LOGGER, DOMAIN, hass) component._platforms = {} await component.async_setup({DOMAIN: {"platform": "platform"}}) await hass.async_block_till_done() handle = list(component._platforms.values())[-1] class SyncEntity(MockEntity): """Mock entity that has update.""" async def update(self): pass entity = SyncEntity() await handle.async_add_entities([entity]) assert entity.parallel_updates is not None assert entity.parallel_updates._value == 1
async def test_setup_entry(hass): """Test we can setup an entry.""" registry = mock_registry(hass) async def async_setup_entry(hass, config_entry, async_add_devices): """Mock setup entry method.""" async_add_devices([MockEntity(name='test1', unique_id='unique')]) return True platform = MockPlatform(async_setup_entry=async_setup_entry) config_entry = MockConfigEntry(entry_id='super-mock-id') entity_platform = MockEntityPlatform(hass, platform_name=config_entry.domain, platform=platform) assert await entity_platform.async_setup_entry(config_entry) await hass.async_block_till_done() full_name = '{}.{}'.format(entity_platform.domain, config_entry.domain) assert full_name in hass.config.components assert len(hass.states.async_entity_ids()) == 1 assert len(registry.entities) == 1 assert registry.entities['test_domain.test1'].config_entry_id == \ 'super-mock-id'
def test_platform_warn_slow_setup(hass): """Warn we log when platform setup takes a long time.""" platform = MockPlatform() loader.set_component('test_domain.platform', platform) component = EntityComponent(_LOGGER, DOMAIN, hass) with patch.object(hass.loop, 'call_later', MagicMock()) \ as mock_call: yield from component.async_setup({ DOMAIN: { 'platform': 'platform', } }) assert mock_call.called timeout, logger_method = mock_call.mock_calls[0][1][:2] assert timeout == SLOW_SETUP_WARNING assert logger_method == _LOGGER.warning assert mock_call().cancel.called
async def test_parallel_updates_async_platform(hass): """Test async platform does not have parallel_updates limit by default.""" platform = MockPlatform() mock_entity_platform(hass, "test_domain.platform", platform) component = EntityComponent(_LOGGER, DOMAIN, hass) component._platforms = {} await component.async_setup({DOMAIN: {"platform": "platform"}}) await hass.async_block_till_done() handle = list(component._platforms.values())[-1] assert handle.parallel_updates is None class AsyncEntity(MockEntity): """Mock entity that has async_update.""" async def async_update(self): pass entity = AsyncEntity() await handle.async_add_entities([entity]) assert entity.parallel_updates is None
def test_parallel_updates_async_platform_with_constant(hass): """Warn we log when platform setup takes a long time.""" platform = MockPlatform() @asyncio.coroutine def mock_update(*args, **kwargs): pass platform.async_setup_platform = mock_update platform.PARALLEL_UPDATES = 1 loader.set_component('test_domain.platform', platform) component = EntityComponent(_LOGGER, DOMAIN, hass) component._platforms = {} yield from component.async_setup({DOMAIN: { 'platform': 'platform', }}) handle = list(component._platforms.values())[-1] assert handle.parallel_updates is not None
def test_component_setup_with_validation_and_dependency(self): """Test all config is passed to dependencies.""" def config_check_setup(hass, config): """Setup method that tests config is passed in.""" if config.get('comp_a', {}).get('valid', False): return True raise Exception('Config not passed in: {}'.format(config)) loader.set_component('comp_a', MockModule('comp_a', setup=config_check_setup)) loader.set_component('switch.platform_a', MockPlatform('comp_b', ['comp_a'])) bootstrap.setup_component(self.hass, 'switch', { 'comp_a': { 'valid': True }, 'switch': { 'platform': 'platform_a', } }) assert 'comp_a' in self.hass.config.components
def test_set_entity_namespace_via_config(self): """Test setting an entity namespace.""" def platform_setup(hass, config, add_devices, discovery_info=None): """Test the platform setup.""" add_devices([ EntityTest(name='beer'), EntityTest(name=None), ]) platform = MockPlatform(platform_setup) loader.set_component('test_domain.platform', platform) component = EntityComponent(_LOGGER, DOMAIN, self.hass) component.setup( {DOMAIN: { 'platform': 'platform', 'entity_namespace': 'yummy' }}) assert sorted(self.hass.states.entity_ids()) == \ ['test_domain.yummy_beer', 'test_domain.yummy_unnamed_device']
async def test_parallel_updates_sync_platform_with_constant(hass): """Test sync platform can set parallel_updates limit.""" platform = MockPlatform() platform.PARALLEL_UPDATES = 2 mock_entity_platform(hass, "test_domain.platform", platform) component = EntityComponent(_LOGGER, DOMAIN, hass) component._platforms = {} await component.async_setup({DOMAIN: {"platform": "platform"}}) handle = list(component._platforms.values())[-1] class SyncEntity(MockEntity): """Mock entity that has update.""" async def update(self): pass entity = SyncEntity() await handle.async_add_entities([entity]) assert entity.parallel_updates is not None assert entity.parallel_updates._value == 2
async def test_setup_loads_platforms(hass): """Test the loading of the platforms.""" component_setup = Mock(return_value=True) platform_setup = Mock(return_value=None) mock_integration(hass, MockModule('test_component', setup=component_setup)) # mock the dependencies mock_integration(hass, MockModule('mod2', dependencies=['test_component'])) mock_entity_platform(hass, 'test_domain.mod2', MockPlatform(platform_setup)) component = EntityComponent(_LOGGER, DOMAIN, hass) assert not component_setup.called assert not platform_setup.called component.setup({DOMAIN: { 'platform': 'mod2', }}) await hass.async_block_till_done() assert component_setup.called assert platform_setup.called
async def test_platform_not_ready(opp, legacy_patchable_time): """Test that we retry when platform not ready.""" platform1_setup = Mock(side_effect=[PlatformNotReady, PlatformNotReady, None]) mock_integration(opp, MockModule("mod1")) mock_entity_platform(opp, "test_domain.mod1", MockPlatform(platform1_setup)) component = EntityComponent(_LOGGER, DOMAIN, opp) await component.async_setup({DOMAIN: {"platform": "mod1"}}) await opp.async_block_till_done() assert len(platform1_setup.mock_calls) == 1 assert "test_domain.mod1" not in opp.config.components utcnow = dt_util.utcnow() with patch("openpeerpower.util.dt.utcnow", return_value=utcnow): # Should not trigger attempt 2 async_fire_time_changed(opp, utcnow + timedelta(seconds=29)) await opp.async_block_till_done() assert len(platform1_setup.mock_calls) == 1 # Should trigger attempt 2 async_fire_time_changed(opp, utcnow + timedelta(seconds=30)) await opp.async_block_till_done() assert len(platform1_setup.mock_calls) == 2 assert "test_domain.mod1" not in opp.config.components # This should not trigger attempt 3 async_fire_time_changed(opp, utcnow + timedelta(seconds=59)) await opp.async_block_till_done() assert len(platform1_setup.mock_calls) == 2 # Trigger attempt 3, which succeeds async_fire_time_changed(opp, utcnow + timedelta(seconds=60)) await opp.async_block_till_done() assert len(platform1_setup.mock_calls) == 3 assert "test_domain.mod1" in opp.config.components
def test_platform_not_ready(hass): """Test that we retry when platform not ready.""" platform1_setup = Mock( side_effect=[PlatformNotReady, PlatformNotReady, None]) loader.set_component('test_domain.mod1', MockPlatform(platform1_setup)) component = EntityComponent(_LOGGER, DOMAIN, hass) yield from component.async_setup({DOMAIN: {'platform': 'mod1'}}) assert len(platform1_setup.mock_calls) == 1 assert 'test_domain.mod1' not in hass.config.components utcnow = dt_util.utcnow() with patch('homeassistant.util.dt.utcnow', return_value=utcnow): # Should not trigger attempt 2 async_fire_time_changed(hass, utcnow + timedelta(seconds=29)) yield from hass.async_block_till_done() assert len(platform1_setup.mock_calls) == 1 # Should trigger attempt 2 async_fire_time_changed(hass, utcnow + timedelta(seconds=30)) yield from hass.async_block_till_done() assert len(platform1_setup.mock_calls) == 2 assert 'test_domain.mod1' not in hass.config.components # This should not trigger attempt 3 async_fire_time_changed(hass, utcnow + timedelta(seconds=59)) yield from hass.async_block_till_done() assert len(platform1_setup.mock_calls) == 2 # Trigger attempt 3, which succeeds async_fire_time_changed(hass, utcnow + timedelta(seconds=60)) yield from hass.async_block_till_done() assert len(platform1_setup.mock_calls) == 3 assert 'test_domain.mod1' in hass.config.components
def test_setup_dependencies_platform(hass): """Test we setup the dependencies of a platform. We're explictely testing that we process dependencies even if a component with the same name has already been loaded. """ loader.set_component('test_component', MockModule('test_component')) loader.set_component('test_component2', MockModule('test_component2')) loader.set_component( 'test_domain.test_component', MockPlatform(dependencies=['test_component', 'test_component2'])) component = EntityComponent(_LOGGER, DOMAIN, hass) yield from async_setup_component(hass, 'test_component', {}) yield from component.async_setup( {DOMAIN: { 'platform': 'test_component', }}) assert 'test_component' in hass.config.components assert 'test_component2' in hass.config.components assert 'test_domain.test_component' in hass.config.components
async def test_reset_cancels_retry_setup(hass): """Test that resetting a platform will cancel scheduled a setup retry.""" async_setup_entry = Mock(side_effect=PlatformNotReady) platform = MockPlatform( async_setup_entry=async_setup_entry ) config_entry = MockConfigEntry() ent_platform = MockEntityPlatform( hass, platform_name=config_entry.domain, platform=platform ) with patch.object(entity_platform, 'async_call_later') as mock_call_later: assert not await ent_platform.async_setup_entry(config_entry) assert len(mock_call_later.mock_calls) == 1 assert len(mock_call_later.return_value.mock_calls) == 0 assert ent_platform._async_cancel_retry_setup is not None await ent_platform.async_reset() assert len(mock_call_later.return_value.mock_calls) == 1 assert ent_platform._async_cancel_retry_setup is None
async def test_validate_platform_config_2(hass, caplog): """Test component PLATFORM_SCHEMA_BASE prio over PLATFORM_SCHEMA.""" platform_schema = PLATFORM_SCHEMA.extend({"hello": str}) platform_schema_base = PLATFORM_SCHEMA_BASE.extend({"hello": "world"}) mock_integration( hass, MockModule( "platform_conf", platform_schema=platform_schema, platform_schema_base=platform_schema_base, ), ) mock_entity_platform( hass, "platform_conf.whatever", MockPlatform("whatever", platform_schema=platform_schema), ) with assert_setup_component(1): assert await setup.async_setup_component( hass, "platform_conf", { # pass "platform_conf": { "platform": "whatever", "hello": "world" }, # fail: key hello violates component platform_schema_base "platform_conf 2": { "platform": "whatever", "hello": "there" }, }, )
async def test_entity_disabled_by_device(hass: HomeAssistant): """Test entity disabled by device.""" connections = {(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")} entity_disabled = MockEntity( unique_id="disabled", device_info=DeviceInfo(connections=connections) ) async def async_setup_entry(hass, config_entry, async_add_entities): """Mock setup entry method.""" async_add_entities([entity_disabled]) return True platform = MockPlatform(async_setup_entry=async_setup_entry) config_entry = MockConfigEntry(entry_id="super-mock-id", domain=DOMAIN) entity_platform = MockEntityPlatform( hass, platform_name=config_entry.domain, platform=platform ) device_registry = dr.async_get(hass) device_registry.async_get_or_create( config_entry_id=config_entry.entry_id, connections=connections, disabled_by=dr.DeviceEntryDisabler.USER, ) assert await entity_platform.async_setup_entry(config_entry) await hass.async_block_till_done() assert entity_disabled.hass is None assert entity_disabled.platform is None registry = er.async_get(hass) entry_disabled = registry.async_get_or_create(DOMAIN, DOMAIN, "disabled") assert entry_disabled.disabled_by is er.RegistryEntryDisabler.DEVICE
async def test_set_entity_namespace_via_config(hass): """Test setting an entity namespace.""" def platform_setup(hass, config, add_entities, discovery_info=None): """Test the platform setup.""" add_entities([MockEntity(name="beer"), MockEntity(name=None)]) platform = MockPlatform(platform_setup) mock_entity_platform(hass, "test_domain.platform", platform) component = EntityComponent(_LOGGER, DOMAIN, hass) component.setup( {DOMAIN: { "platform": "platform", "entity_namespace": "yummy" }}) await hass.async_block_till_done() assert sorted(hass.states.async_entity_ids()) == [ "test_domain.yummy_beer", "test_domain.yummy_unnamed_device", ]
async def test_remove_entry(hass, manager): """Test that we can remove an entry.""" async def mock_setup_entry(hass, entry): """Mock setting up entry.""" hass.async_create_task(hass.config_entries.async_forward_entry_setup( entry, 'light')) return True async def mock_unload_entry(hass, entry): """Mock unloading an entry.""" result = await hass.config_entries.async_forward_entry_unload( entry, 'light') assert result return result mock_remove_entry = MagicMock( side_effect=lambda *args, **kwargs: mock_coro()) entity = MockEntity( unique_id='1234', name='Test Entity', ) async def mock_setup_entry_platform(hass, entry, async_add_entities): """Mock setting up platform.""" async_add_entities([entity]) mock_integration(hass, MockModule( 'test', async_setup_entry=mock_setup_entry, async_unload_entry=mock_unload_entry, async_remove_entry=mock_remove_entry )) mock_entity_platform( hass, 'light.test', MockPlatform(async_setup_entry=mock_setup_entry_platform)) mock_entity_platform(hass, 'config_flow.test', None) MockConfigEntry( domain='test_other', entry_id='test1' ).add_to_manager(manager) entry = MockConfigEntry( domain='test', entry_id='test2', ) entry.add_to_manager(manager) MockConfigEntry( domain='test_other', entry_id='test3' ).add_to_manager(manager) # Check all config entries exist assert [item.entry_id for item in manager.async_entries()] == \ ['test1', 'test2', 'test3'] # Setup entry await entry.async_setup(hass) await hass.async_block_till_done() # Check entity state got added assert hass.states.get('light.test_entity') is not None # Group all_lights, light.test_entity assert len(hass.states.async_all()) == 2 # Check entity got added to entity registry ent_reg = await hass.helpers.entity_registry.async_get_registry() assert len(ent_reg.entities) == 1 entity_entry = list(ent_reg.entities.values())[0] assert entity_entry.config_entry_id == entry.entry_id # Remove entry result = await manager.async_remove('test2') await hass.async_block_till_done() # Check that unload went well and so no need to restart assert result == { 'require_restart': False } # Check the remove callback was invoked. assert mock_remove_entry.call_count == 1 # Check that config entry was removed. assert [item.entry_id for item in manager.async_entries()] == \ ['test1', 'test3'] # Check that entity state has been removed assert hass.states.get('light.test_entity') is None # Just Group all_lights assert len(hass.states.async_all()) == 1 # Check that entity registry entry no longer references config_entry_id entity_entry = list(ent_reg.entities.values())[0] assert entity_entry.config_entry_id is None
async def test_validate_platform_config(hass, caplog): """Test validating platform configuration.""" platform_schema = PLATFORM_SCHEMA.extend({"hello": str}) platform_schema_base = PLATFORM_SCHEMA_BASE.extend({}) mock_integration( hass, MockModule("platform_conf", platform_schema_base=platform_schema_base), ) mock_entity_platform( hass, "platform_conf.whatever", MockPlatform(platform_schema=platform_schema), ) with assert_setup_component(0): assert await setup.async_setup_component( hass, "platform_conf", {"platform_conf": { "platform": "not_existing", "hello": "world" }}, ) hass.data.pop(setup.DATA_SETUP) hass.config.components.remove("platform_conf") with assert_setup_component(1): assert await setup.async_setup_component( hass, "platform_conf", {"platform_conf": { "platform": "whatever", "hello": "world" }}, ) hass.data.pop(setup.DATA_SETUP) hass.config.components.remove("platform_conf") with assert_setup_component(1): assert await setup.async_setup_component( hass, "platform_conf", {"platform_conf": [{ "platform": "whatever", "hello": "world" }]}, ) hass.data.pop(setup.DATA_SETUP) hass.config.components.remove("platform_conf") # Any falsey platform config will be ignored (None, {}, etc) with assert_setup_component(0) as config: assert await setup.async_setup_component(hass, "platform_conf", {"platform_conf": None}) assert "platform_conf" in hass.config.components assert not config["platform_conf"] # empty assert await setup.async_setup_component(hass, "platform_conf", {"platform_conf": {}}) assert "platform_conf" in hass.config.components assert not config["platform_conf"] # empty
def test_validate_platform_config(self): """Test validating platform configuration.""" platform_schema = PLATFORM_SCHEMA.extend({ 'hello': str, }) loader.set_component( 'platform_conf', MockModule('platform_conf', platform_schema=platform_schema)) loader.set_component('platform_conf.whatever', MockPlatform('whatever')) with assert_setup_component(0): assert bootstrap._setup_component( self.hass, 'platform_conf', {'platform_conf': { 'hello': 'world', 'invalid': 'extra', }}) self.hass.config.components.remove('platform_conf') with assert_setup_component(1): assert bootstrap._setup_component( self.hass, 'platform_conf', { 'platform_conf': { 'platform': 'whatever', 'hello': 'world', }, 'platform_conf 2': { 'invalid': True } }) self.hass.config.components.remove('platform_conf') with assert_setup_component(0): assert bootstrap._setup_component(self.hass, 'platform_conf', { 'platform_conf': { 'platform': 'not_existing', 'hello': 'world', } }) self.hass.config.components.remove('platform_conf') with assert_setup_component(1): assert bootstrap._setup_component(self.hass, 'platform_conf', { 'platform_conf': { 'platform': 'whatever', 'hello': 'world', } }) self.hass.config.components.remove('platform_conf') with assert_setup_component(1): assert bootstrap._setup_component(self.hass, 'platform_conf', { 'platform_conf': [{ 'platform': 'whatever', 'hello': 'world', }] }) self.hass.config.components.remove('platform_conf') # Any falsey platform config will be ignored (None, {}, etc) with assert_setup_component(0) as config: assert bootstrap._setup_component(self.hass, 'platform_conf', {'platform_conf': None}) assert 'platform_conf' in self.hass.config.components assert not config['platform_conf'] # empty assert bootstrap._setup_component(self.hass, 'platform_conf', {'platform_conf': {}}) assert 'platform_conf' in self.hass.config.components assert not config['platform_conf'] # empty
async def test_connected_device_registered(hass): """Test dispatch on connected device being registered.""" registry = mock_registry(hass) dispatches = [] @callback def _save_dispatch(msg): dispatches.append(msg) unsub = async_dispatcher_connect(hass, ce.CONNECTED_DEVICE_REGISTERED, _save_dispatch) class MockScannerEntity(ce.ScannerEntity): """Mock a scanner entity.""" @property def ip_address(self) -> str: return "5.4.3.2" @property def unique_id(self) -> str: return self.mac_address class MockDisconnectedScannerEntity(MockScannerEntity): """Mock a disconnected scanner entity.""" @property def mac_address(self) -> str: return "aa:bb:cc:dd:ee:ff" @property def is_connected(self) -> bool: return True @property def hostname(self) -> str: return "connected" class MockConnectedScannerEntity(MockScannerEntity): """Mock a disconnected scanner entity.""" @property def mac_address(self) -> str: return "aa:bb:cc:dd:ee:00" @property def is_connected(self) -> bool: return False @property def hostname(self) -> str: return "disconnected" async def async_setup_entry(hass, config_entry, async_add_entities): """Mock setup entry method.""" async_add_entities( [MockConnectedScannerEntity(), MockDisconnectedScannerEntity()]) return True platform = MockPlatform(async_setup_entry=async_setup_entry) config_entry = MockConfigEntry(entry_id="super-mock-id") entity_platform = MockEntityPlatform(hass, platform_name=config_entry.domain, platform=platform) assert await entity_platform.async_setup_entry(config_entry) await hass.async_block_till_done() full_name = f"{entity_platform.domain}.{config_entry.domain}" assert full_name in hass.config.components assert len(hass.states.async_entity_ids()) == 0 # should be disabled assert len(registry.entities) == 2 assert (registry.entities["test_domain.test_aa_bb_cc_dd_ee_ff"]. config_entry_id == "super-mock-id") unsub() assert dispatches == [{ "ip": "5.4.3.2", "mac": "aa:bb:cc:dd:ee:ff", "host_name": "connected" }]
async def test_device_info_called(hass): """Test device info is forwarded correctly.""" registry = dr.async_get(hass) via = registry.async_get_or_create( config_entry_id="123", connections=set(), identifiers={("hue", "via-id")}, manufacturer="manufacturer", model="via", ) 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", "hw_version": "test-hw", "suggested_area": "Heliport", "entry_type": dr.DeviceEntryType.SERVICE, "via_device": ("hue", "via-id"), }, ), ] ) return True platform = MockPlatform(async_setup_entry=async_setup_entry) config_entry = MockConfigEntry(entry_id="super-mock-id") entity_platform = MockEntityPlatform( hass, platform_name=config_entry.domain, platform=platform ) assert await entity_platform.async_setup_entry(config_entry) await hass.async_block_till_done() assert len(hass.states.async_entity_ids()) == 2 device = registry.async_get_device({("hue", "1234")}) assert device is not None assert device.identifiers == {("hue", "1234")} assert device.configuration_url == "http://192.168.0.100/config" assert device.connections == {(dr.CONNECTION_NETWORK_MAC, "abcd")} assert device.entry_type is dr.DeviceEntryType.SERVICE assert device.manufacturer == "test-manuf" assert device.model == "test-model" assert device.name == "test-name" assert device.suggested_area == "Heliport" assert device.sw_version == "test-sw" assert device.hw_version == "test-hw" assert device.via_device_id == via.id
async def test_remove_entry(hass, manager): """Test that we can remove an entry.""" async def mock_setup_entry(hass, entry): """Mock setting up entry.""" hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "light")) return True async def mock_unload_entry(hass, entry): """Mock unloading an entry.""" result = await hass.config_entries.async_forward_entry_unload( entry, "light") assert result return result mock_remove_entry = MagicMock( side_effect=lambda *args, **kwargs: mock_coro()) entity = MockEntity(unique_id="1234", name="Test Entity") async def mock_setup_entry_platform(hass, entry, async_add_entities): """Mock setting up platform.""" async_add_entities([entity]) mock_integration( hass, MockModule( "test", async_setup_entry=mock_setup_entry, async_unload_entry=mock_unload_entry, async_remove_entry=mock_remove_entry, ), ) mock_entity_platform( hass, "light.test", MockPlatform(async_setup_entry=mock_setup_entry_platform)) mock_entity_platform(hass, "config_flow.test", None) MockConfigEntry(domain="test_other", entry_id="test1").add_to_manager(manager) entry = MockConfigEntry(domain="test", entry_id="test2") entry.add_to_manager(manager) MockConfigEntry(domain="test_other", entry_id="test3").add_to_manager(manager) # Check all config entries exist assert [item.entry_id for item in manager.async_entries()] == [ "test1", "test2", "test3", ] # Setup entry await entry.async_setup(hass) await hass.async_block_till_done() # Check entity state got added assert hass.states.get("light.test_entity") is not None assert len(hass.states.async_all()) == 1 # Check entity got added to entity registry ent_reg = await hass.helpers.entity_registry.async_get_registry() assert len(ent_reg.entities) == 1 entity_entry = list(ent_reg.entities.values())[0] assert entity_entry.config_entry_id == entry.entry_id # Remove entry result = await manager.async_remove("test2") await hass.async_block_till_done() # Check that unload went well and so no need to restart assert result == {"require_restart": False} # Check the remove callback was invoked. assert mock_remove_entry.call_count == 1 # Check that config entry was removed. assert [item.entry_id for item in manager.async_entries()] == ["test1", "test3"] # Check that entity state has been removed assert hass.states.get("light.test_entity") is None assert len(hass.states.async_all()) == 0 # Check that entity registry entry has been removed entity_entry_list = list(ent_reg.entities.values()) assert not entity_entry_list
def test_validate_platform_config(self, caplog): """Test validating platform configuration.""" platform_schema = PLATFORM_SCHEMA.extend({ 'hello': str, }) platform_schema_base = PLATFORM_SCHEMA_BASE.extend({ }) mock_integration( self.hass, MockModule('platform_conf', platform_schema_base=platform_schema_base), ) mock_entity_platform( self.hass, 'platform_conf.whatever', MockPlatform(platform_schema=platform_schema)) with assert_setup_component(1): assert setup.setup_component(self.hass, 'platform_conf', { 'platform_conf': { 'platform': 'whatever', 'hello': 'world', 'invalid': 'extra', } }) assert caplog.text.count('Your configuration contains ' 'extra keys') == 1 self.hass.data.pop(setup.DATA_SETUP) self.hass.config.components.remove('platform_conf') with assert_setup_component(2): assert setup.setup_component(self.hass, 'platform_conf', { 'platform_conf': { 'platform': 'whatever', 'hello': 'world', }, 'platform_conf 2': { 'platform': 'whatever', 'invalid': True } }) assert caplog.text.count('Your configuration contains ' 'extra keys') == 2 self.hass.data.pop(setup.DATA_SETUP) self.hass.config.components.remove('platform_conf') with assert_setup_component(0): assert setup.setup_component(self.hass, 'platform_conf', { 'platform_conf': { 'platform': 'not_existing', 'hello': 'world', } }) self.hass.data.pop(setup.DATA_SETUP) self.hass.config.components.remove('platform_conf') with assert_setup_component(1): assert setup.setup_component(self.hass, 'platform_conf', { 'platform_conf': { 'platform': 'whatever', 'hello': 'world', } }) self.hass.data.pop(setup.DATA_SETUP) self.hass.config.components.remove('platform_conf') with assert_setup_component(1): assert setup.setup_component(self.hass, 'platform_conf', { 'platform_conf': [{ 'platform': 'whatever', 'hello': 'world', }] }) self.hass.data.pop(setup.DATA_SETUP) self.hass.config.components.remove('platform_conf') # Any falsey platform config will be ignored (None, {}, etc) with assert_setup_component(0) as config: assert setup.setup_component(self.hass, 'platform_conf', { 'platform_conf': None }) assert 'platform_conf' in self.hass.config.components assert not config['platform_conf'] # empty assert setup.setup_component(self.hass, 'platform_conf', { 'platform_conf': {} }) assert 'platform_conf' in self.hass.config.components assert not config['platform_conf'] # empty