async def test_entity_device_info_with_hub(hass, mqtt_mock): """Test MQTT sensor device registry integration.""" entry = MockConfigEntry(domain=mqtt.DOMAIN) entry.add_to_hass(hass) await async_start(hass, 'homeassistant', {}, entry) registry = await hass.helpers.device_registry.async_get_registry() hub = registry.async_get_or_create( config_entry_id='123', connections=set(), identifiers={('mqtt', 'hub-id')}, manufacturer='manufacturer', model='hub' ) data = json.dumps({ 'platform': 'mqtt', 'name': 'Test 1', 'state_topic': 'test-topic', 'device': { 'identifiers': ['helloworld'], 'via_hub': 'hub-id', }, 'unique_id': 'veryunique' }) async_fire_mqtt_message(hass, 'homeassistant/sensor/bla/config', data) await hass.async_block_till_done() await hass.async_block_till_done() device = registry.async_get_device({('mqtt', 'helloworld')}, set()) assert device is not None assert device.hub_device_id == hub.id
async def test_service_refresh_devices(hass): """Test that service can refresh devices.""" entry = MockConfigEntry(domain=deconz.DOMAIN, data={ 'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF' }) entry.add_to_hass(hass) mock_registry = Mock() with patch.object(deconz, 'DeconzGateway') as mock_gateway, \ patch('homeassistant.helpers.device_registry.async_get_registry', return_value=mock_coro(mock_registry)): mock_gateway.return_value.async_setup.return_value = mock_coro(True) assert await deconz.async_setup_entry(hass, entry) is True with patch.object(hass.data[deconz.DOMAIN].api, 'async_load_parameters', return_value=mock_coro(True)): await hass.services.async_call( 'deconz', 'device_refresh', service_data={}) await hass.async_block_till_done() with patch.object(hass.data[deconz.DOMAIN].api, 'async_load_parameters', return_value=mock_coro(False)): await hass.services.async_call( 'deconz', 'device_refresh', service_data={}) await hass.async_block_till_done()
async def test_remove_entry_handles_callback_error(hass, manager): """Test that exceptions in the remove callback are handled.""" mock_setup_entry = MagicMock(return_value=mock_coro(True)) mock_unload_entry = MagicMock(return_value=mock_coro(True)) mock_remove_entry = MagicMock( side_effect=lambda *args, **kwargs: mock_coro()) loader.set_component(hass, 'test', MockModule( 'test', async_setup_entry=mock_setup_entry, async_unload_entry=mock_unload_entry, async_remove_entry=mock_remove_entry )) entry = MockConfigEntry( domain='test', entry_id='test1', ) entry.add_to_manager(manager) # Check all config entries exist assert [item.entry_id for item in manager.async_entries()] == \ ['test1'] # Setup entry await entry.async_setup(hass) await hass.async_block_till_done() # Remove entry result = await manager.async_remove('test1') 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()] == []
async def test_config_passed_to_config_entry(hass): """Test that configured options for a host are loaded via config entry.""" entry = MockConfigEntry(domain=hue.DOMAIN, data={ 'host': '0.0.0.0', }) entry.add_to_hass(hass) with patch.object(hue, 'HueBridge') as mock_bridge: mock_bridge.return_value.async_setup.return_value = mock_coro(True) assert await async_setup_component(hass, hue.DOMAIN, { hue.DOMAIN: { hue.CONF_BRIDGES: { hue.CONF_HOST: '0.0.0.0', hue.CONF_FILENAME: 'bla.conf', hue.CONF_ALLOW_HUE_GROUPS: False, hue.CONF_ALLOW_UNREACHABLE: True } } }) is True assert len(mock_bridge.mock_calls) == 2 p_hass, p_entry, p_allow_unreachable, p_allow_groups = \ mock_bridge.mock_calls[0][1] assert p_hass is hass assert p_entry is entry assert p_allow_unreachable is True assert p_allow_groups is False
async def test_entry_options(hass, manager): """Test that we can set options on an entry.""" entry = MockConfigEntry( domain='test', data={'first': True}, options=None ) entry.add_to_manager(manager) class TestFlow: @staticmethod @callback def async_get_options_flow(config, options): class OptionsFlowHandler(data_entry_flow.FlowHandler): def __init__(self, config, options): pass return OptionsFlowHandler(config, options) config_entries.HANDLERS['test'] = TestFlow() flow = await manager.options._async_create_flow( entry.entry_id, context={'source': 'test'}, data=None) flow.handler = entry.entry_id # Used to keep reference to config entry await manager.options._async_finish_flow( flow, {'data': {'second': True}}) assert entry.data == { 'first': True } assert entry.options == { 'second': True }
async def test_import_already_configured(hass): """Test importing a device from .homekit that is already a ConfigEntry.""" discovery_info = { 'host': '127.0.0.1', 'port': 8080, 'properties': { 'md': 'TestDevice', 'id': '00:00:00:00:00:00', 'c#': 1, 'sf': 1, } } import_info = { 'AccessoryPairingID': '00:00:00:00:00:00', } config_entry = MockConfigEntry( domain='homekit_controller', data=import_info ) config_entry.add_to_hass(hass) flow = config_flow.HomekitControllerFlowHandler() flow.hass = hass result = await flow.async_import_legacy_pairing( discovery_info['properties'], import_info) assert result['type'] == 'abort' assert result['reason'] == 'already_configured'
async def test_entity_device_info_with_identifier(hass, mqtt_mock): """Test MQTT climate device registry integration.""" entry = MockConfigEntry(domain=mqtt.DOMAIN) entry.add_to_hass(hass) await async_start(hass, 'homeassistant', {}, entry) registry = await hass.helpers.device_registry.async_get_registry() data = json.dumps({ 'platform': 'mqtt', 'name': 'Test 1', 'device': { 'identifiers': ['helloworld'], 'connections': [ ["mac", "02:5b:26:a8:dc:12"], ], 'manufacturer': 'Whatever', 'name': 'Beer', 'model': 'Glass', 'sw_version': '0.1-beta', }, 'unique_id': 'veryunique' }) async_fire_mqtt_message(hass, 'homeassistant/climate/bla/config', data) await hass.async_block_till_done() await hass.async_block_till_done() device = registry.async_get_device({('mqtt', 'helloworld')}, set()) assert device is not None assert device.identifiers == {('mqtt', 'helloworld')} assert device.connections == {('mac', "02:5b:26:a8:dc:12")} assert device.manufacturer == 'Whatever' assert device.name == 'Beer' assert device.model == 'Glass' assert device.sw_version == '0.1-beta'
async def test_controller_no_mac(hass): """Test that configured options for a host are loaded via config entry.""" entry = MockConfigEntry(domain=unifi.DOMAIN, data={ 'controller': { 'host': '0.0.0.0', 'username': '******', 'password': '******', 'port': 80, 'site': 'default', 'verify_ssl': True }, 'poe_control': True }) entry.add_to_hass(hass) mock_registry = Mock() with patch.object(unifi, 'UniFiController') as mock_controller, \ patch('homeassistant.helpers.device_registry.async_get_registry', return_value=mock_coro(mock_registry)): mock_controller.return_value.async_setup.return_value = mock_coro(True) mock_controller.return_value.mac = None assert await unifi.async_setup_entry(hass, entry) is True assert len(mock_controller.mock_calls) == 2 assert len(mock_registry.mock_calls) == 0
async def test_entry_reload_error(hass, manager, state): """Test that we can reload an entry.""" entry = MockConfigEntry( domain='comp', state=state ) entry.add_to_hass(hass) async_setup = MagicMock(return_value=mock_coro(True)) async_setup_entry = MagicMock(return_value=mock_coro(True)) async_unload_entry = MagicMock(return_value=mock_coro(True)) loader.set_component(hass, 'comp', MockModule( 'comp', async_setup=async_setup, async_setup_entry=async_setup_entry, async_unload_entry=async_unload_entry )) with pytest.raises(config_entries.OperationNotAllowed): assert await manager.async_reload(entry.entry_id) assert len(async_unload_entry.mock_calls) == 0 assert len(async_setup.mock_calls) == 0 assert len(async_setup_entry.mock_calls) == 0 assert entry.state == state
async def test_unload_entry(hass): """Test being able to unload an entry.""" entry = MockConfigEntry(domain=unifi.DOMAIN, data={ 'controller': { 'host': '0.0.0.0', 'username': '******', 'password': '******', 'port': 80, 'site': 'default', 'verify_ssl': True }, 'poe_control': True }) entry.add_to_hass(hass) with patch.object(unifi, 'UniFiController') as mock_controller, \ patch('homeassistant.helpers.device_registry.async_get_registry', return_value=mock_coro(Mock())): mock_controller.return_value.async_setup.return_value = mock_coro(True) mock_controller.return_value.mac = '00:11:22:33:44:55' assert await unifi.async_setup_entry(hass, entry) is True assert len(mock_controller.return_value.mock_calls) == 1 mock_controller.return_value.async_reset.return_value = mock_coro(True) assert await unifi.async_unload_entry(hass, entry) assert len(mock_controller.return_value.async_reset.mock_calls) == 1 assert hass.data[unifi.DOMAIN] == {}
async def test_controller_site_already_configured(hass): """Test config flow.""" flow = unifi.UnifiFlowHandler() flow.hass = hass entry = MockConfigEntry(domain=unifi.DOMAIN, data={ 'controller': { 'host': '1.2.3.4', 'site': 'default', } }) entry.add_to_hass(hass) flow.config = { unifi.CONF_HOST: '1.2.3.4', unifi.CONF_USERNAME: '******', unifi.CONF_PASSWORD: '******', } flow.desc = 'site name' flow.sites = { 'site1': { 'name': 'default', 'role': 'admin', 'desc': 'site name' } } result = await flow.async_step_site() assert result['type'] == 'abort'
def test_setup_registered_zone_skips_home_zone(self): """Test that config entry named home should override hass home zone.""" entry = MockConfigEntry(domain=zone.DOMAIN, data={ zone.CONF_NAME: 'home' }) entry.add_to_hass(self.hass) assert setup.setup_component(self.hass, zone.DOMAIN, {'zone': None}) assert len(self.hass.states.entity_ids('zone')) == 0
async def test_remove_entry_unauth(hass, client, hass_admin_user): """Test removing an entry via the API.""" hass_admin_user.groups = [] entry = MockConfigEntry(domain='demo', state=core_ce.ENTRY_STATE_LOADED) entry.add_to_hass(hass) resp = await client.delete( '/api/config/config_entries/entry/{}'.format(entry.entry_id)) assert resp.status == 401 assert len(hass.config_entries.async_entries()) == 1
async def test_service_configure(hass): """Test that service invokes pydeconz with the correct path and data.""" entry = MockConfigEntry(domain=deconz.DOMAIN, data={ 'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF' }) entry.add_to_hass(hass) mock_registry = Mock() with patch.object(deconz, 'DeconzGateway') as mock_gateway, \ patch('homeassistant.helpers.device_registry.async_get_registry', return_value=mock_coro(mock_registry)): mock_gateway.return_value.async_setup.return_value = mock_coro(True) assert await deconz.async_setup_entry(hass, entry) is True hass.data[deconz.DOMAIN].deconz_ids = { 'light.test': '/light/1' } data = {'on': True, 'attr1': 10, 'attr2': 20} # only field with patch('pydeconz.DeconzSession.async_put_state', return_value=mock_coro(True)): await hass.services.async_call('deconz', 'configure', service_data={ 'field': '/light/42', 'data': data }) await hass.async_block_till_done() # only entity with patch('pydeconz.DeconzSession.async_put_state', return_value=mock_coro(True)): await hass.services.async_call('deconz', 'configure', service_data={ 'entity': 'light.test', 'data': data }) await hass.async_block_till_done() # entity + field with patch('pydeconz.DeconzSession.async_put_state', return_value=mock_coro(True)): await hass.services.async_call('deconz', 'configure', service_data={ 'entity': 'light.test', 'field': '/state', 'data': data}) await hass.async_block_till_done() # non-existing entity (or not from deCONZ) with patch('pydeconz.DeconzSession.async_put_state', return_value=mock_coro(True)): await hass.services.async_call('deconz', 'configure', service_data={ 'entity': 'light.nonexisting', 'field': '/state', 'data': data}) await hass.async_block_till_done() # field does not start with / with pytest.raises(vol.Invalid): with patch('pydeconz.DeconzSession.async_put_state', return_value=mock_coro(True)): await hass.services.async_call( 'deconz', 'configure', service_data={ 'entity': 'light.test', 'field': 'state', 'data': data}) await hass.async_block_till_done()
async def test_config_passed_to_config_entry(hass): """Test that configured options for a host are loaded via config entry.""" entry = MockConfigEntry(domain=hue.DOMAIN, data={ 'host': '0.0.0.0', }) entry.add_to_hass(hass) mock_registry = Mock() with patch.object(hue, 'HueBridge') as mock_bridge, \ patch('homeassistant.helpers.device_registry.async_get_registry', return_value=mock_coro(mock_registry)): mock_bridge.return_value.async_setup.return_value = mock_coro(True) mock_bridge.return_value.api.config = Mock( mac='mock-mac', bridgeid='mock-bridgeid', raw={ 'modelid': 'mock-modelid', 'swversion': 'mock-swversion', } ) # Can't set name via kwargs mock_bridge.return_value.api.config.name = 'mock-name' assert await async_setup_component(hass, hue.DOMAIN, { hue.DOMAIN: { hue.CONF_BRIDGES: { hue.CONF_HOST: '0.0.0.0', hue.CONF_FILENAME: 'bla.conf', hue.CONF_ALLOW_HUE_GROUPS: False, hue.CONF_ALLOW_UNREACHABLE: True } } }) is True assert len(mock_bridge.mock_calls) == 2 p_hass, p_entry, p_allow_unreachable, p_allow_groups = \ mock_bridge.mock_calls[0][1] assert p_hass is hass assert p_entry is entry assert p_allow_unreachable is True assert p_allow_groups is False assert len(mock_registry.mock_calls) == 1 assert mock_registry.mock_calls[0][2] == { 'config_entry_id': entry.entry_id, 'connections': { ('mac', 'mock-mac') }, 'identifiers': { ('hue', 'mock-bridgeid') }, 'manufacturer': 'Signify', 'name': 'mock-name', 'model': 'mock-modelid', 'sw_version': 'mock-swversion', }
def test_remove_entry(hass, client): """Test removing an entry via the API.""" entry = MockConfigEntry(domain='demo', state=core_ce.ENTRY_STATE_LOADED) entry.add_to_hass(hass) resp = yield from client.delete( '/api/config/config_entries/entry/{}'.format(entry.entry_id)) assert resp.status == 200 data = yield from resp.json() assert data == { 'require_restart': True } assert len(hass.config_entries.async_entries()) == 0
async def test_configured_devices(hass): """Test that configured devices works as expected.""" result = config_flow.configured_devices(hass) assert not result entry = MockConfigEntry(domain=axis.DOMAIN, data={axis.CONF_DEVICE: {axis.CONF_HOST: ''}}) entry.add_to_hass(hass) result = config_flow.configured_devices(hass) assert len(result) == 1
async def test_setup_entry_successful(hass): """Test setup entry is successful.""" entry = MockConfigEntry(domain=deconz.DOMAIN, data={ 'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF' }) entry.add_to_hass(hass) mock_registry = Mock() with patch.object(deconz, 'DeconzGateway') as mock_gateway, \ patch('homeassistant.helpers.device_registry.async_get_registry', return_value=mock_coro(mock_registry)): mock_gateway.return_value.async_setup.return_value = mock_coro(True) assert await deconz.async_setup_entry(hass, entry) is True assert hass.data[deconz.DOMAIN]
async def test_full_flow_implementation(hass): """Test registering an implementation and flow works.""" flow = ps4.PlayStation4FlowHandler() flow.hass = hass manager = hass.config_entries # User Step Started, results in Step Creds with patch('pyps4_homeassistant.Helper.port_bind', return_value=None): result = await flow.async_step_user() assert result['type'] == data_entry_flow.RESULT_TYPE_FORM assert result['step_id'] == 'creds' # Step Creds results with form in Step Mode. with patch('pyps4_homeassistant.Helper.get_creds', return_value=MOCK_CREDS): result = await flow.async_step_creds({}) assert result['type'] == data_entry_flow.RESULT_TYPE_FORM assert result['step_id'] == 'mode' # Step Mode with User Input which is not manual, results in Step Link. with patch('pyps4_homeassistant.Helper.has_devices', return_value=[{'host-ip': MOCK_HOST}]): result = await flow.async_step_mode(MOCK_AUTO) assert result['type'] == data_entry_flow.RESULT_TYPE_FORM assert result['step_id'] == 'link' # User Input results in created entry. with patch('pyps4_homeassistant.Helper.link', return_value=(True, True)), \ patch('pyps4_homeassistant.Helper.has_devices', return_value=[{'host-ip': MOCK_HOST}]): result = await flow.async_step_link(MOCK_CONFIG) assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY assert result['data'][CONF_TOKEN] == MOCK_CREDS assert result['data']['devices'] == [MOCK_DEVICE] assert result['title'] == MOCK_TITLE await hass.async_block_till_done() # Add entry using result data. mock_data = { CONF_TOKEN: result['data'][CONF_TOKEN], 'devices': result['data']['devices']} entry = MockConfigEntry(domain=ps4.DOMAIN, data=mock_data) entry.add_to_manager(manager) # Check if entry exists. assert len(manager.async_entries()) == 1 # Check if there is a device config in entry. assert len(entry.data['devices']) == 1
async def setup_push_receiver(hass, aioclient_mock): """Fixture that sets up a mocked push receiver.""" push_url = 'https://mobile-push.home-assistant.dev/push' from datetime import datetime, timedelta now = (datetime.now() + timedelta(hours=24)) iso_time = now.strftime("%Y-%m-%dT%H:%M:%SZ") aioclient_mock.post(push_url, json={ 'rateLimits': { 'attempts': 1, 'successful': 1, 'errors': 0, 'total': 1, 'maximum': 150, 'remaining': 149, 'resetsAt': iso_time } }) entry = MockConfigEntry( connection_class="cloud_push", data={ "app_data": { "push_token": "PUSH_TOKEN", "push_url": push_url }, "app_id": "io.homeassistant.mobile_app", "app_name": "mobile_app tests", "app_version": "1.0", "device_id": "4d5e6f", "device_name": "Test", "manufacturer": "Home Assistant", "model": "mobile_app", "os_name": "Linux", "os_version": "5.0.6", "secret": "123abc", "supports_encryption": False, "user_id": "1a2b3c", "webhook_id": "webhook_id" }, domain=DOMAIN, source="registration", title="mobile_app test entry", version=1 ) entry.add_to_hass(hass) await async_setup_component(hass, DOMAIN, {DOMAIN: {}}) await hass.async_block_till_done()
async def test_populate_options(hass): """Test successful populate options.""" entry = MockConfigEntry(domain=axis.DOMAIN, data={'device': {}}) entry.add_to_hass(hass) with patch.object(axis, 'get_device', return_value=mock_coro(Mock())): await axis.async_populate_options(hass, entry) assert entry.options == { axis.CONF_CAMERA: True, axis.CONF_EVENTS: True, axis.CONF_TRIGGER_TIME: axis.DEFAULT_TRIGGER_TIME }
async def test_updating_entry_data(manager): """Test that we can update an entry data.""" entry = MockConfigEntry( domain='test', data={'first': True}, ) entry.add_to_manager(manager) manager.async_update_entry(entry, data={ 'second': True }) assert entry.data == { 'second': True }
async def test_entity_device_info_update(hass, mqtt_mock): """Test device registry update.""" entry = MockConfigEntry(domain=mqtt.DOMAIN) entry.add_to_hass(hass) await async_start(hass, 'homeassistant', {}, entry) registry = await hass.helpers.device_registry.async_get_registry() config = { 'platform': 'mqtt', 'name': 'Test 1', 'schema': 'template', 'state_topic': 'test-topic', 'command_topic': 'test-command-topic', 'command_on_template': 'on,{{ transition }}', 'command_off_template': 'off,{{ transition|d }}', 'device': { 'identifiers': ['helloworld'], 'connections': [ ["mac", "02:5b:26:a8:dc:12"], ], 'manufacturer': 'Whatever', 'name': 'Beer', 'model': 'Glass', 'sw_version': '0.1-beta', }, 'unique_id': 'veryunique' } data = json.dumps(config) async_fire_mqtt_message(hass, 'homeassistant/light/bla/config', data) await hass.async_block_till_done() await hass.async_block_till_done() device = registry.async_get_device({('mqtt', 'helloworld')}, set()) assert device is not None assert device.name == 'Beer' config['device']['name'] = 'Milk' data = json.dumps(config) async_fire_mqtt_message(hass, 'homeassistant/light/bla/config', data) await hass.async_block_till_done() await hass.async_block_till_done() device = registry.async_get_device({('mqtt', 'helloworld')}, set()) assert device is not None assert device.name == 'Milk'
async def test_call_async_migrate_entry_failure_not_supported(hass): """Test migration fails if async_migrate_entry not implemented.""" entry = MockConfigEntry(domain='comp') entry.version = 2 entry.add_to_hass(hass) mock_setup_entry = MagicMock(return_value=mock_coro(True)) loader.set_component( hass, 'comp', MockModule('comp', async_setup_entry=mock_setup_entry)) result = await async_setup_component(hass, 'comp', {}) assert result assert len(mock_setup_entry.mock_calls) == 0 assert entry.state == config_entries.ENTRY_STATE_MIGRATION_ERROR
def test_setup_registered_zone_skips_configured_zone(self): """Test if config entry will override configured zone.""" entry = MockConfigEntry(domain=zone.DOMAIN, data={ zone.CONF_NAME: 'Test Zone' }) entry.add_to_hass(self.hass) info = { 'name': 'Test Zone', 'latitude': 1.1, 'longitude': -2.2, } assert setup.setup_component(self.hass, zone.DOMAIN, {'zone': info}) assert len(self.hass.states.entity_ids('zone')) == 1 state = self.hass.states.get('zone.test_zone') assert not state
async def test_unload_entry(hass): """Test being able to unload an entry.""" entry = MockConfigEntry(domain=hue.DOMAIN, data={ 'host': '0.0.0.0', }) entry.add_to_hass(hass) with patch.object(hue, 'HueBridge') as mock_bridge: mock_bridge.return_value.async_setup.return_value = mock_coro(True) assert await async_setup_component(hass, hue.DOMAIN, {}) is True assert len(mock_bridge.return_value.mock_calls) == 1 mock_bridge.return_value.async_reset.return_value = mock_coro(True) assert await hue.async_unload_entry(hass, entry) assert len(mock_bridge.return_value.async_reset.mock_calls) == 1 assert hass.data[hue.DOMAIN] == {}
async def test_flow_fails_already_configured(hass): """Test that config flow fails on already configured device.""" flow = config_flow.AxisFlowHandler() flow.hass = hass entry = MockConfigEntry(domain=axis.DOMAIN, data={axis.CONF_DEVICE: { axis.CONF_HOST: '1.2.3.4' }}) entry.add_to_hass(hass) result = await flow.async_step_user(user_input={ config_flow.CONF_HOST: '1.2.3.4', config_flow.CONF_USERNAME: '******', config_flow.CONF_PASSWORD: '******', config_flow.CONF_PORT: 81 }) assert result['errors'] == {'base': 'already_configured'}
async def test_entry_unload_failed_to_load(hass, manager, state): """Test that we can unload an entry.""" entry = MockConfigEntry( domain='comp', state=state, ) entry.add_to_hass(hass) async_unload_entry = MagicMock(return_value=mock_coro(True)) loader.set_component(hass, 'comp', MockModule( 'comp', async_unload_entry=async_unload_entry )) assert await manager.async_unload(entry.entry_id) assert len(async_unload_entry.mock_calls) == 0 assert entry.state == config_entries.ENTRY_STATE_NOT_LOADED
async def test_discovery_flow_already_configured(hass): """Test that discovery doesn't setup already configured devices.""" flow = config_flow.AxisFlowHandler() flow.hass = hass entry = MockConfigEntry(domain=axis.DOMAIN, data={axis.CONF_DEVICE: { axis.CONF_HOST: '1.2.3.4' }}) entry.add_to_hass(hass) result = await flow.async_step_discovery(discovery_info={ config_flow.CONF_HOST: '1.2.3.4', config_flow.CONF_USERNAME: '******', config_flow.CONF_PASSWORD: '******', config_flow.CONF_PORT: 81 }) print(result) assert result['type'] == 'abort'
async def test_call_setup_entry(hass): """Test we call <component>.setup_entry.""" entry = MockConfigEntry(domain='comp') entry.add_to_hass(hass) mock_setup_entry = MagicMock(return_value=mock_coro(True)) mock_migrate_entry = MagicMock(return_value=mock_coro(True)) loader.set_component( hass, 'comp', MockModule('comp', async_setup_entry=mock_setup_entry, async_migrate_entry=mock_migrate_entry)) result = await async_setup_component(hass, 'comp', {}) assert result assert len(mock_migrate_entry.mock_calls) == 0 assert len(mock_setup_entry.mock_calls) == 1 assert entry.state == config_entries.ENTRY_STATE_LOADED
async def test_v5_meter(hass, dsmr_connection_fixture): """Test if v5 meter is correctly parsed.""" (connection_factory, transport, protocol) = dsmr_connection_fixture from dsmr_parser.obis_references import ( ELECTRICITY_ACTIVE_TARIFF, HOURLY_GAS_METER_READING, ) from dsmr_parser.objects import CosemObject, MBusObject entry_data = { "port": "/dev/ttyUSB0", "dsmr_version": "5", "precision": 4, "reconnect_interval": 30, "serial_id": "1234", "serial_id_gas": "5678", } entry_options = { "time_between_update": 0, } telegram = { HOURLY_GAS_METER_READING: MBusObject([ { "value": datetime.datetime.fromtimestamp(1551642213) }, { "value": Decimal(745.695), "unit": "m3" }, ]), ELECTRICITY_ACTIVE_TARIFF: CosemObject([{ "value": "0001", "unit": "" }]), } mock_entry = MockConfigEntry(domain="dsmr", unique_id="/dev/ttyUSB0", data=entry_data, options=entry_options) mock_entry.add_to_hass(hass) await hass.config_entries.async_setup(mock_entry.entry_id) await hass.async_block_till_done() telegram_callback = connection_factory.call_args_list[0][0][2] # simulate a telegram pushed from the smartmeter and parsed by dsmr_parser telegram_callback(telegram) # after receiving telegram entities need to have the chance to update await asyncio.sleep(0) # tariff should be translated in human readable and have no unit active_tariff = hass.states.get("sensor.electricity_meter_active_tariff") assert active_tariff.state == "low" assert active_tariff.attributes.get(ATTR_DEVICE_CLASS) is None assert active_tariff.attributes.get(ATTR_ICON) == "mdi:flash" assert active_tariff.attributes.get(ATTR_STATE_CLASS) is None assert active_tariff.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "" # check if gas consumption is parsed correctly gas_consumption = hass.states.get("sensor.gas_meter_gas_consumption") assert gas_consumption.state == "745.695" assert gas_consumption.attributes.get( ATTR_DEVICE_CLASS) == SensorDeviceClass.GAS assert (gas_consumption.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.TOTAL_INCREASING) assert (gas_consumption.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == VOLUME_CUBIC_METERS)
async def test_open_close_update(gogogate2api_mock, hass: HomeAssistant) -> None: """Test open and close and data update.""" def info_response(door_status: DoorStatus) -> GogoGate2InfoResponse: return GogoGate2InfoResponse( user="******", gogogatename="gogogatename0", model="", apiversion="", remoteaccessenabled=False, remoteaccess="abc123.blah.blah", firmwareversion="", apicode="", door1=GogoGate2Door( door_id=1, permission=True, name="Door1", gate=False, mode=DoorMode.GARAGE, status=door_status, sensor=True, sensorid=None, camera=False, events=2, temperature=None, voltage=40, ), door2=GogoGate2Door( door_id=2, permission=True, name=None, gate=True, mode=DoorMode.GARAGE, status=DoorStatus.UNDEFINED, sensor=True, sensorid=None, camera=False, events=0, temperature=None, voltage=40, ), door3=GogoGate2Door( door_id=3, permission=True, name=None, gate=False, mode=DoorMode.GARAGE, status=DoorStatus.UNDEFINED, sensor=True, sensorid=None, camera=False, events=0, temperature=None, voltage=40, ), outputs=Outputs(output1=True, output2=False, output3=True), network=Network(ip=""), wifi=Wifi(SSID="", linkquality="", signal=""), ) api = MagicMock(GogoGate2Api) api.activate.return_value = GogoGate2ActivateResponse(result=True) api.info.return_value = info_response(DoorStatus.OPENED) gogogate2api_mock.return_value = api config_entry = MockConfigEntry( domain=DOMAIN, source=SOURCE_USER, data={ CONF_IP_ADDRESS: "127.0.0.1", CONF_USERNAME: "******", CONF_PASSWORD: "******", }, ) config_entry.add_to_hass(hass) assert hass.states.get("cover.door1") is None assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert hass.states.get("cover.door1").state == STATE_OPEN api.info.return_value = info_response(DoorStatus.CLOSED) await hass.services.async_call( COVER_DOMAIN, "close_cover", service_data={"entity_id": "cover.door1"}, ) async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("cover.door1").state == STATE_CLOSED api.close_door.assert_called_with(1) api.info.return_value = info_response(DoorStatus.OPENED) await hass.services.async_call( COVER_DOMAIN, "open_cover", service_data={"entity_id": "cover.door1"}, ) async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("cover.door1").state == STATE_OPEN api.open_door.assert_called_with(1) api.info.return_value = info_response(DoorStatus.UNDEFINED) async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("cover.door1").state == STATE_UNKNOWN assert await hass.config_entries.async_unload(config_entry.entry_id) assert not hass.states.async_entity_ids(DOMAIN)
async def test_media_lookups(hass): """Test media lookups to Plex server.""" entry = MockConfigEntry( domain=DOMAIN, data=DEFAULT_DATA, options=DEFAULT_OPTIONS, unique_id=DEFAULT_DATA["server_id"], ) mock_plex_server = MockPlexServer(config_entry=entry) with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch( "homeassistant.components.plex.PlexWebsocket.listen" ): entry.add_to_hass(hass) assert await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() server_id = mock_plex_server.machineIdentifier loaded_server = hass.data[DOMAIN][SERVERS][server_id] # Plex Key searches async_dispatcher_send(hass, PLEX_UPDATE_PLATFORMS_SIGNAL.format(server_id)) await hass.async_block_till_done() media_player_id = hass.states.async_entity_ids("media_player")[0] with patch("homeassistant.components.plex.PlexServer.create_playqueue"): assert await hass.services.async_call( MP_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: DOMAIN, ATTR_MEDIA_CONTENT_ID: 123, }, True, ) with patch.object(MockPlexServer, "fetchItem", side_effect=NotFound): assert await hass.services.async_call( MP_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: DOMAIN, ATTR_MEDIA_CONTENT_ID: 123, }, True, ) # TV show searches with patch.object(MockPlexLibrary, "section", side_effect=NotFound): assert ( loaded_server.lookup_media( MEDIA_TYPE_EPISODE, library_name="Not a Library", show_name="A TV Show" ) is None ) with patch.object(MockPlexLibrarySection, "get", side_effect=NotFound): assert ( loaded_server.lookup_media( MEDIA_TYPE_EPISODE, library_name="TV Shows", show_name="Not a TV Show" ) is None ) assert ( loaded_server.lookup_media( MEDIA_TYPE_EPISODE, library_name="TV Shows", episode_name="An Episode" ) is None ) assert loaded_server.lookup_media( MEDIA_TYPE_EPISODE, library_name="TV Shows", show_name="A TV Show" ) assert loaded_server.lookup_media( MEDIA_TYPE_EPISODE, library_name="TV Shows", show_name="A TV Show", season_number=2, ) assert loaded_server.lookup_media( MEDIA_TYPE_EPISODE, library_name="TV Shows", show_name="A TV Show", season_number=2, episode_number=3, ) with patch.object(MockPlexMediaItem, "season", side_effect=NotFound): assert ( loaded_server.lookup_media( MEDIA_TYPE_EPISODE, library_name="TV Shows", show_name="A TV Show", season_number=2, ) is None ) with patch.object(MockPlexMediaItem, "episode", side_effect=NotFound): assert ( loaded_server.lookup_media( MEDIA_TYPE_EPISODE, library_name="TV Shows", show_name="A TV Show", season_number=2, episode_number=1, ) is None ) # Music searches assert ( loaded_server.lookup_media( MEDIA_TYPE_MUSIC, library_name="Music", album_name="An Album" ) is None ) assert loaded_server.lookup_media( MEDIA_TYPE_MUSIC, library_name="Music", artist_name="An Artist" ) assert loaded_server.lookup_media( MEDIA_TYPE_MUSIC, library_name="Music", artist_name="An Artist", track_name="A Track", ) assert loaded_server.lookup_media( MEDIA_TYPE_MUSIC, library_name="Music", artist_name="An Artist", album_name="An Album", ) with patch.object(MockPlexLibrarySection, "get", side_effect=NotFound): assert ( loaded_server.lookup_media( MEDIA_TYPE_MUSIC, library_name="Music", artist_name="Not an Artist", album_name="An Album", ) is None ) with patch.object(MockPlexArtist, "album", side_effect=NotFound): assert ( loaded_server.lookup_media( MEDIA_TYPE_MUSIC, library_name="Music", artist_name="An Artist", album_name="Not an Album", ) is None ) with patch.object(MockPlexMediaItem, "track", side_effect=NotFound): assert ( loaded_server.lookup_media( MEDIA_TYPE_MUSIC, library_name="Music", artist_name="An Artist", album_name="An Album", track_name="Not a Track", ) is None ) with patch.object(MockPlexArtist, "get", side_effect=NotFound): assert ( loaded_server.lookup_media( MEDIA_TYPE_MUSIC, library_name="Music", artist_name="An Artist", track_name="Not a Track", ) is None ) assert loaded_server.lookup_media( MEDIA_TYPE_MUSIC, library_name="Music", artist_name="An Artist", album_name="An Album", track_number=3, ) assert ( loaded_server.lookup_media( MEDIA_TYPE_MUSIC, library_name="Music", artist_name="An Artist", album_name="An Album", track_number=30, ) is None ) assert loaded_server.lookup_media( MEDIA_TYPE_MUSIC, library_name="Music", artist_name="An Artist", album_name="An Album", track_name="A Track", ) # Playlist searches assert loaded_server.lookup_media(MEDIA_TYPE_PLAYLIST, playlist_name="A Playlist") assert loaded_server.lookup_media(MEDIA_TYPE_PLAYLIST) is None with patch.object(MockPlexServer, "playlist", side_effect=NotFound): assert ( loaded_server.lookup_media( MEDIA_TYPE_PLAYLIST, playlist_name="Not a Playlist" ) is None ) # Movie searches assert loaded_server.lookup_media(MEDIA_TYPE_VIDEO, video_name="A Movie") is None assert loaded_server.lookup_media(MEDIA_TYPE_VIDEO, library_name="Movies") is None assert loaded_server.lookup_media( MEDIA_TYPE_VIDEO, library_name="Movies", video_name="A Movie" ) with patch.object(MockPlexLibrarySection, "get", side_effect=NotFound): assert ( loaded_server.lookup_media( MEDIA_TYPE_VIDEO, library_name="Movies", video_name="Not a Movie" ) is None )
async def test_websocket_get_action_capabilities(hass, hass_ws_client, device_reg, entity_reg): """Test we get the expected action capabilities for an alarm through websocket.""" await async_setup_component(hass, "device_automation", {}) config_entry = MockConfigEntry(domain="test", data={}) config_entry.add_to_hass(hass) device_entry = device_reg.async_get_or_create( config_entry_id=config_entry.entry_id, connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) entity_reg.async_get_or_create("alarm_control_panel", "test", "5678", device_id=device_entry.id) hass.states.async_set("alarm_control_panel.test_5678", "attributes", {"supported_features": 15}) expected_capabilities = { "arm_away": { "extra_fields": [] }, "arm_home": { "extra_fields": [] }, "arm_night": { "extra_fields": [] }, "disarm": { "extra_fields": [{ "name": "code", "optional": True, "type": "string" }] }, "trigger": { "extra_fields": [] }, } client = await hass_ws_client(hass) await client.send_json({ "id": 1, "type": "device_automation/action/list", "device_id": device_entry.id }) msg = await client.receive_json() assert msg["id"] == 1 assert msg["type"] == TYPE_RESULT assert msg["success"] actions = msg["result"] id = 2 assert len(actions) == 5 for action in actions: await client.send_json({ "id": id, "type": "device_automation/action/capabilities", "action": action, }) msg = await client.receive_json() assert msg["id"] == id assert msg["type"] == TYPE_RESULT assert msg["success"] capabilities = msg["result"] assert capabilities == expected_capabilities[action["type"]] id = id + 1
async def test_setup_with_cloudhook(hass): """Test if set up with active cloud subscription and cloud hook.""" config_entry = MockConfigEntry( domain="netatmo", data={ "auth_implementation": "cloud", "cloudhook_url": "https://hooks.nabu.casa/ABCD", "token": { "refresh_token": "mock-refresh-token", "access_token": "mock-access-token", "type": "Bearer", "expires_in": 60, "expires_at": time() + 1000, "scope": ALL_SCOPES, }, }, ) config_entry.add_to_hass(hass) await mock_cloud(hass) await hass.async_block_till_done() with patch( "homeassistant.components.cloud.async_is_logged_in", return_value=True ), patch( "homeassistant.components.cloud.async_active_subscription", return_value=True ), patch( "homeassistant.components.cloud.async_create_cloudhook", return_value="https://hooks.nabu.casa/ABCD", ) as fake_create_cloudhook, patch( "homeassistant.components.cloud.async_delete_cloudhook" ) as fake_delete_cloudhook, patch( "homeassistant.components.netatmo.api.AsyncConfigEntryNetatmoAuth" ) as mock_auth, patch( "homeassistant.components.netatmo.PLATFORMS", [] ), patch( "homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation", ), patch( "homeassistant.components.webhook.async_generate_url" ): mock_auth.return_value.async_post_request.side_effect = fake_post_request mock_auth.return_value.async_addwebhook.side_effect = AsyncMock() mock_auth.return_value.async_dropwebhook.side_effect = AsyncMock() assert await async_setup_component(hass, "netatmo", {}) assert hass.components.cloud.async_active_subscription() is True assert ( hass.config_entries.async_entries("netatmo")[0].data["cloudhook_url"] == "https://hooks.nabu.casa/ABCD" ) await hass.async_block_till_done() assert hass.config_entries.async_entries(DOMAIN) fake_create_cloudhook.assert_not_called() for config_entry in hass.config_entries.async_entries("netatmo"): await hass.config_entries.async_remove(config_entry.entry_id) fake_delete_cloudhook.assert_called_once() await hass.async_block_till_done() assert not hass.config_entries.async_entries(DOMAIN)
})) authorisation_response = json.loads( json.dumps({ JWT: "fakekeyhere", USER_ID: 12345, TTL: 145656758, ERROR: "false", STATUS: 200, })) entry = MockConfigEntry( domain=DOMAIN, data={ CONF_USERNAME: "******", CONF_PASSWORD: "******", CONF_STATION: "12345", }, entry_id="testEntry", ) async def setup_integration(hass: HomeAssistant) -> None: """Test wallbox sensor class setup.""" entry.add_to_hass(hass) with requests_mock.Mocker() as mock_request: mock_request.get( "https://api.wall-box.com/auth/token/user", json=authorisation_response,
MOCK_DATA = {CONF_TOKEN: MOCK_CREDS, "devices": [MOCK_DEVICE]} MOCK_FLOW_RESULT = { "version": VERSION, "handler": DOMAIN, "type": data_entry_flow.RESULT_TYPE_CREATE_ENTRY, "title": "test_ps4", "data": MOCK_DATA, "options": {}, } MOCK_ENTRY_ID = "SomeID" MOCK_CONFIG = MockConfigEntry(domain=DOMAIN, data=MOCK_DATA, entry_id=MOCK_ENTRY_ID) MOCK_LOCATION = location.LocationInfo( "0.0.0.0", "US", "CA", "California", "San Diego", "92122", "America/Los_Angeles", 32.8594, -117.2073, True, )
async def test_options_flow(hass: HomeAssistant) -> None: """Test we can edit options.""" config_entry = MockConfigEntry( domain=DOMAIN, data={}, options={ CONF_HOSTS: "192.168.1.0/24", CONF_HOME_INTERVAL: 3, CONF_OPTIONS: DEFAULT_OPTIONS, CONF_EXCLUDE: "4.4.4.4", }, ) config_entry.add_to_hass(hass) hass.state = CoreState.stopped assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() result = await hass.config_entries.options.async_init(config_entry.entry_id ) await hass.async_block_till_done() assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["step_id"] == "init" assert result["data_schema"]({}) == { CONF_EXCLUDE: "4.4.4.4", CONF_HOME_INTERVAL: 3, CONF_HOSTS: "192.168.1.0/24", CONF_CONSIDER_HOME: 180, CONF_SCAN_INTERVAL: 120, CONF_OPTIONS: "-F -T4 --min-rate 10 --host-timeout 5s", } with patch( "homeassistant.components.nmap_tracker.async_setup_entry", return_value=True, ) as mock_setup_entry: result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ CONF_HOSTS: "192.168.1.0/24, 192.168.2.0/24", CONF_HOME_INTERVAL: 5, CONF_CONSIDER_HOME: 500, CONF_OPTIONS: "-sn", CONF_EXCLUDE: "4.4.4.4, 5.5.5.5", CONF_SCAN_INTERVAL: 10, }, ) await hass.async_block_till_done() assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY assert config_entry.options == { CONF_HOSTS: "192.168.1.0/24,192.168.2.0/24", CONF_HOME_INTERVAL: 5, CONF_CONSIDER_HOME: 500, CONF_OPTIONS: "-sn", CONF_EXCLUDE: "4.4.4.4,5.5.5.5", CONF_SCAN_INTERVAL: 10, } assert len(mock_setup_entry.mock_calls) == 1
async def setup_push_receiver(hass, aioclient_mock): """Fixture that sets up a mocked push receiver.""" push_url = "https://mobile-push.home-assistant.dev/push" from datetime import datetime, timedelta now = datetime.now() + timedelta(hours=24) iso_time = now.strftime("%Y-%m-%dT%H:%M:%SZ") aioclient_mock.post( push_url, json={ "rateLimits": { "attempts": 1, "successful": 1, "errors": 0, "total": 1, "maximum": 150, "remaining": 149, "resetsAt": iso_time, } }, ) entry = MockConfigEntry( connection_class="cloud_push", data={ "app_data": {"push_token": "PUSH_TOKEN", "push_url": push_url}, "app_id": "io.homeassistant.mobile_app", "app_name": "mobile_app tests", "app_version": "1.0", "device_id": "4d5e6f", "device_name": "Test", "manufacturer": "Home Assistant", "model": "mobile_app", "os_name": "Linux", "os_version": "5.0.6", "secret": "123abc", "supports_encryption": False, "user_id": "1a2b3c", "webhook_id": "webhook_id", }, domain=DOMAIN, source="registration", title="mobile_app test entry", version=1, ) entry.add_to_hass(hass) await async_setup_component(hass, DOMAIN, {DOMAIN: {}}) await hass.async_block_till_done() loaded_late_entry = MockConfigEntry( connection_class="cloud_push", data={ "app_data": {"push_token": "PUSH_TOKEN2", "push_url": f"{push_url}2"}, "app_id": "io.homeassistant.mobile_app", "app_name": "mobile_app tests", "app_version": "1.0", "device_id": "4d5e6f2", "device_name": "Loaded Late", "manufacturer": "Home Assistant", "model": "mobile_app", "os_name": "Linux", "os_version": "5.0.6", "secret": "123abc2", "supports_encryption": False, "user_id": "1a2b3c2", "webhook_id": "webhook_id_2", }, domain=DOMAIN, source="registration", title="mobile_app 2 test entry", version=1, ) loaded_late_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(loaded_late_entry.entry_id) await hass.async_block_till_done() assert hass.services.has_service("notify", "mobile_app_loaded_late") assert await hass.config_entries.async_remove(loaded_late_entry.entry_id) await hass.async_block_till_done() assert hass.services.has_service("notify", "mobile_app_test") assert not hass.services.has_service("notify", "mobile_app_loaded_late") loaded_late_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(loaded_late_entry.entry_id) await hass.async_block_till_done() assert hass.services.has_service("notify", "mobile_app_test") assert hass.services.has_service("notify", "mobile_app_loaded_late")
async def setup_unifi_integration( hass, config=ENTRY_CONFIG, options=ENTRY_OPTIONS, sites=SITES, clients_response=None, devices_response=None, clients_all_response=None, wlans_response=None, known_wireless_clients=None, controllers=None, ): """Create the UniFi controller.""" configuration = {} if controllers: configuration = {unifi.DOMAIN: {unifi.CONF_CONTROLLERS: controllers}} assert await async_setup_component(hass, unifi.DOMAIN, configuration) config_entry = MockConfigEntry( domain=unifi.DOMAIN, data=deepcopy(config), options=deepcopy(options), entry_id=1, ) config_entry.add_to_hass(hass) if known_wireless_clients: hass.data[UNIFI_WIRELESS_CLIENTS].update_data(known_wireless_clients, config_entry) mock_client_responses = deque() if clients_response: mock_client_responses.append(clients_response) mock_device_responses = deque() if devices_response: mock_device_responses.append(devices_response) mock_client_all_responses = deque() if clients_all_response: mock_client_all_responses.append(clients_all_response) mock_wlans_responses = deque() if wlans_response: mock_wlans_responses.append(wlans_response) mock_requests = [] async def mock_request(self, method, path, json=None): mock_requests.append({"method": method, "path": path, "json": json}) if path == "s/{site}/stat/sta" and mock_client_responses: return mock_client_responses.popleft() if path == "s/{site}/stat/device" and mock_device_responses: return mock_device_responses.popleft() if path == "s/{site}/rest/user" and mock_client_all_responses: return mock_client_all_responses.popleft() if path == "s/{site}/rest/wlanconf" and mock_wlans_responses: return mock_wlans_responses.popleft() return {} # "aiounifi.Controller.start_websocket", return_value=True with patch("aiounifi.Controller.login", return_value=True), patch("aiounifi.Controller.sites", return_value=sites), patch( "aiounifi.Controller.request", new=mock_request), patch.object( aiounifi.websocket.WSClient, "start", return_value=True): await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() controller_id = unifi.get_controller_id_from_config_entry(config_entry) if controller_id not in hass.data[unifi.DOMAIN]: return None controller = hass.data[unifi.DOMAIN][controller_id] controller.mock_client_responses = mock_client_responses controller.mock_device_responses = mock_device_responses controller.mock_client_all_responses = mock_client_all_responses controller.mock_wlans_responses = mock_wlans_responses controller.mock_requests = mock_requests return controller
def setup_config_entry(hass: HomeAssistant, config_entry: MockConfigEntry) -> MockConfigEntry: """Fixture to initialize the config entry.""" config_entry.add_to_hass(hass)
async def test_sensor_availability(hass, caplog, legacy_patchable_time, pvpc_aioclient_mock: AiohttpClientMocker): """Test sensor availability and handling of cloud access.""" hass.config.time_zone = dt_util.get_time_zone("Europe/Madrid") config_entry = MockConfigEntry(domain=DOMAIN, data={ CONF_NAME: "test_dst", ATTR_TARIFF: "discrimination" }) config_entry.add_to_hass(hass) assert len(hass.config_entries.async_entries(DOMAIN)) == 1 mock_data = { "return_time": datetime(2019, 10, 27, 20, 0, 0, tzinfo=date_util.UTC) } def mock_now(): return mock_data["return_time"] with patch("homeassistant.util.dt.utcnow", new=mock_now): assert await hass.config_entries.async_setup(config_entry.entry_id) # check migration current_entries = hass.config_entries.async_entries(DOMAIN) assert len(current_entries) == 1 migrated_entry = current_entries[0] assert migrated_entry.version == 1 assert migrated_entry.data[ATTR_POWER] == migrated_entry.data[ ATTR_POWER_P3] assert migrated_entry.data[ATTR_TARIFF] == TARIFFS[0] await hass.async_block_till_done() caplog.clear() assert pvpc_aioclient_mock.call_count == 2 await _process_time_step(hass, mock_data, "price_21h", 0.13896) await _process_time_step(hass, mock_data, "price_22h", 0.06893) assert pvpc_aioclient_mock.call_count == 4 await _process_time_step(hass, mock_data, "price_23h", 0.06935) assert pvpc_aioclient_mock.call_count == 5 # sensor has no more prices, state is "unavailable" from now on await _process_time_step(hass, mock_data, value="unavailable") await _process_time_step(hass, mock_data, value="unavailable") num_errors = sum(1 for x in caplog.records if x.levelno == logging.ERROR and "unknown job listener" not in x.msg) num_warnings = sum(1 for x in caplog.records if x.levelno == logging.WARNING) assert num_warnings == 1 assert num_errors == 0 assert pvpc_aioclient_mock.call_count == 9 # check that it is silent until it becomes available again caplog.clear() with caplog.at_level(logging.WARNING): # silent mode for _ in range(21): await _process_time_step(hass, mock_data, value="unavailable") assert pvpc_aioclient_mock.call_count == 30 assert len(caplog.messages) == 0 # warning about data access recovered await _process_time_step(hass, mock_data, value="unavailable") assert pvpc_aioclient_mock.call_count == 31 assert len(caplog.messages) == 1 assert caplog.records[0].levelno == logging.WARNING # working ok again await _process_time_step(hass, mock_data, "price_00h", value=0.06821) assert pvpc_aioclient_mock.call_count == 32 await _process_time_step(hass, mock_data, "price_01h", value=0.06627) assert pvpc_aioclient_mock.call_count == 33 assert len(caplog.messages) == 1 assert caplog.records[0].levelno == logging.WARNING
async def test_multi_sensor_migration( hass, caplog, legacy_patchable_time, pvpc_aioclient_mock: AiohttpClientMocker): """Test tariff migration when there are >1 old sensors.""" entity_reg = mock_registry(hass) hass.config.time_zone = dt_util.get_time_zone("Europe/Madrid") uid_1 = "discrimination" uid_2 = "normal" old_conf_1 = {CONF_NAME: "test_pvpc_1", ATTR_TARIFF: uid_1} old_conf_2 = {CONF_NAME: "test_pvpc_2", ATTR_TARIFF: uid_2} config_entry_1 = MockConfigEntry(domain=DOMAIN, data=old_conf_1, unique_id=uid_1) config_entry_1.add_to_hass(hass) entity1 = entity_reg.async_get_or_create( domain="sensor", platform=DOMAIN, unique_id=uid_1, config_entry=config_entry_1, suggested_object_id="test_pvpc_1", ) config_entry_2 = MockConfigEntry(domain=DOMAIN, data=old_conf_2, unique_id=uid_2) config_entry_2.add_to_hass(hass) entity2 = entity_reg.async_get_or_create( domain="sensor", platform=DOMAIN, unique_id=uid_2, config_entry=config_entry_2, suggested_object_id="test_pvpc_2", ) assert len(hass.config_entries.async_entries(DOMAIN)) == 2 assert len(entity_reg.entities) == 2 mock_data = { "return_time": datetime(2019, 10, 27, 20, tzinfo=date_util.UTC) } def mock_now(): return mock_data["return_time"] caplog.clear() with caplog.at_level(logging.WARNING): with patch("homeassistant.util.dt.utcnow", new=mock_now): assert await hass.config_entries.async_setup( config_entry_1.entry_id) assert len(caplog.messages) == 2 # check migration with removal of extra sensors assert len(entity_reg.entities) == 1 assert entity1.entity_id in entity_reg.entities assert entity2.entity_id not in entity_reg.entities current_entries = hass.config_entries.async_entries(DOMAIN) assert len(current_entries) == 1 migrated_entry = current_entries[0] assert migrated_entry.version == 1 assert migrated_entry.data[ATTR_POWER] == migrated_entry.data[ ATTR_POWER_P3] assert migrated_entry.data[ATTR_TARIFF] == TARIFFS[0] await hass.async_block_till_done() assert pvpc_aioclient_mock.call_count == 2
async def setup_mock_component(opp): """Set up Mock Media Player.""" entry = MockConfigEntry(domain=ps4.DOMAIN, data=MOCK_DATA, version=VERSION) entry.add_to_manager(opp.config_entries) await async_setup_component(opp, DOMAIN, {DOMAIN: {}}) await opp.async_block_till_done()
async def test_luxembourg_meter(hass, dsmr_connection_fixture): """Test if v5 meter is correctly parsed.""" (connection_factory, transport, protocol) = dsmr_connection_fixture from dsmr_parser.obis_references import ( ELECTRICITY_EXPORTED_TOTAL, ELECTRICITY_IMPORTED_TOTAL, HOURLY_GAS_METER_READING, ) from dsmr_parser.objects import CosemObject, MBusObject entry_data = { "port": "/dev/ttyUSB0", "dsmr_version": "5L", "precision": 4, "reconnect_interval": 30, "serial_id": "1234", "serial_id_gas": "5678", } entry_options = { "time_between_update": 0, } telegram = { HOURLY_GAS_METER_READING: MBusObject([ { "value": datetime.datetime.fromtimestamp(1551642213) }, { "value": Decimal(745.695), "unit": "m3" }, ]), ELECTRICITY_IMPORTED_TOTAL: CosemObject([{ "value": Decimal(123.456), "unit": ENERGY_KILO_WATT_HOUR }]), ELECTRICITY_EXPORTED_TOTAL: CosemObject([{ "value": Decimal(654.321), "unit": ENERGY_KILO_WATT_HOUR }]), } mock_entry = MockConfigEntry(domain="dsmr", unique_id="/dev/ttyUSB0", data=entry_data, options=entry_options) mock_entry.add_to_hass(hass) await hass.config_entries.async_setup(mock_entry.entry_id) await hass.async_block_till_done() telegram_callback = connection_factory.call_args_list[0][0][2] # simulate a telegram pushed from the smartmeter and parsed by dsmr_parser telegram_callback(telegram) # after receiving telegram entities need to have the chance to update await asyncio.sleep(0) active_tariff = hass.states.get( "sensor.electricity_meter_energy_consumption_total") assert active_tariff.state == "123.456" assert active_tariff.attributes.get( ATTR_DEVICE_CLASS) == SensorDeviceClass.ENERGY assert active_tariff.attributes.get(ATTR_ICON) is None assert (active_tariff.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.TOTAL_INCREASING) assert (active_tariff.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == ENERGY_KILO_WATT_HOUR) active_tariff = hass.states.get( "sensor.electricity_meter_energy_production_total") assert active_tariff.state == "654.321" assert active_tariff.attributes.get( "unit_of_measurement") == ENERGY_KILO_WATT_HOUR # check if gas consumption is parsed correctly gas_consumption = hass.states.get("sensor.gas_meter_gas_consumption") assert gas_consumption.state == "745.695" assert gas_consumption.attributes.get( ATTR_DEVICE_CLASS) == SensorDeviceClass.GAS assert (gas_consumption.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.TOTAL_INCREASING) assert (gas_consumption.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == VOLUME_CUBIC_METERS)
async def test_default_setup(hass, dsmr_connection_fixture): """Test the default setup.""" (connection_factory, transport, protocol) = dsmr_connection_fixture from dsmr_parser.obis_references import ( CURRENT_ELECTRICITY_USAGE, ELECTRICITY_ACTIVE_TARIFF, GAS_METER_READING, ) from dsmr_parser.objects import CosemObject, MBusObject entry_data = { "port": "/dev/ttyUSB0", "dsmr_version": "2.2", "precision": 4, "reconnect_interval": 30, "serial_id": "1234", "serial_id_gas": "5678", } entry_options = { "time_between_update": 0, } telegram = { CURRENT_ELECTRICITY_USAGE: CosemObject([{ "value": Decimal("0.0"), "unit": ENERGY_KILO_WATT_HOUR }]), ELECTRICITY_ACTIVE_TARIFF: CosemObject([{ "value": "0001", "unit": "" }]), GAS_METER_READING: MBusObject([ { "value": datetime.datetime.fromtimestamp(1551642213) }, { "value": Decimal(745.695), "unit": VOLUME_CUBIC_METERS }, ]), } mock_entry = MockConfigEntry(domain="dsmr", unique_id="/dev/ttyUSB0", data=entry_data, options=entry_options) mock_entry.add_to_hass(hass) await hass.config_entries.async_setup(mock_entry.entry_id) await hass.async_block_till_done() registry = await hass.helpers.entity_registry.async_get_registry() entry = registry.async_get("sensor.power_consumption") assert entry assert entry.unique_id == "1234_Power_Consumption" entry = registry.async_get("sensor.gas_consumption") assert entry assert entry.unique_id == "5678_Gas_Consumption" telegram_callback = connection_factory.call_args_list[0][0][2] # make sure entities have been created and return 'unknown' state power_consumption = hass.states.get("sensor.power_consumption") assert power_consumption.state == "unknown" assert power_consumption.attributes.get("unit_of_measurement") is None # simulate a telegram pushed from the smartmeter and parsed by dsmr_parser telegram_callback(telegram) # after receiving telegram entities need to have the chance to update await asyncio.sleep(0) # ensure entities have new state value after incoming telegram power_consumption = hass.states.get("sensor.power_consumption") assert power_consumption.state == "0.0" assert (power_consumption.attributes.get("unit_of_measurement") == ENERGY_KILO_WATT_HOUR) # tariff should be translated in human readable and have no unit power_tariff = hass.states.get("sensor.power_tariff") assert power_tariff.state == "low" assert power_tariff.attributes.get("unit_of_measurement") == "" # check if gas consumption is parsed correctly gas_consumption = hass.states.get("sensor.gas_consumption") assert gas_consumption.state == "745.695" assert gas_consumption.attributes.get( "unit_of_measurement") == VOLUME_CUBIC_METERS
async def test_easymeter(hass, dsmr_connection_fixture): """Test if Q3D meter is correctly parsed.""" (connection_factory, transport, protocol) = dsmr_connection_fixture from dsmr_parser.obis_references import ( ELECTRICITY_EXPORTED_TOTAL, ELECTRICITY_IMPORTED_TOTAL, ) from dsmr_parser.objects import CosemObject entry_data = { "port": "/dev/ttyUSB0", "dsmr_version": "Q3D", "precision": 4, "reconnect_interval": 30, "serial_id": None, "serial_id_gas": None, } entry_options = { "time_between_update": 0, } telegram = { ELECTRICITY_IMPORTED_TOTAL: CosemObject([{ "value": Decimal(54184.6316), "unit": ENERGY_KILO_WATT_HOUR }]), ELECTRICITY_EXPORTED_TOTAL: CosemObject([{ "value": Decimal(19981.1069), "unit": ENERGY_KILO_WATT_HOUR }]), } mock_entry = MockConfigEntry( domain="dsmr", unique_id="/dev/ttyUSB0", data=entry_data, options=entry_options, ) mock_entry.add_to_hass(hass) await hass.config_entries.async_setup(mock_entry.entry_id) await hass.async_block_till_done() telegram_callback = connection_factory.call_args_list[0][0][2] # simulate a telegram pushed from the smartmeter and parsed by dsmr_parser telegram_callback(telegram) # after receiving telegram entities need to have the chance to update await asyncio.sleep(0) active_tariff = hass.states.get( "sensor.electricity_meter_energy_consumption_total") assert active_tariff.state == "54184.6316" assert active_tariff.attributes.get( ATTR_DEVICE_CLASS) == SensorDeviceClass.ENERGY assert active_tariff.attributes.get(ATTR_ICON) is None assert (active_tariff.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.TOTAL_INCREASING) assert (active_tariff.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == ENERGY_KILO_WATT_HOUR) active_tariff = hass.states.get( "sensor.electricity_meter_energy_production_total") assert active_tariff.state == "19981.1069" assert (active_tariff.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.TOTAL_INCREASING) assert (active_tariff.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == ENERGY_KILO_WATT_HOUR)
async def test_homekit_ignored_missing_devices( hass, hk_driver, debounce_patcher, device_reg, entity_reg ): """Test HomeKit handles a device in the entity registry but missing from the device registry.""" entry = await async_init_integration(hass) homekit = HomeKit( hass, None, None, None, {}, {"light.demo": {}}, DEFAULT_SAFE_MODE, advertise_ip=None, entry_id=entry.entry_id, ) homekit.driver = hk_driver # pylint: disable=protected-access homekit._filter = Mock(return_value=True) homekit.bridge = HomeBridge(hass, hk_driver, "mock_bridge") config_entry = MockConfigEntry(domain="test", data={}) config_entry.add_to_hass(hass) device_entry = device_reg.async_get_or_create( config_entry_id=config_entry.entry_id, sw_version="0.16.0", model="Powerwall 2", manufacturer="Tesla", connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) entity_reg.async_get_or_create( "binary_sensor", "powerwall", "battery_charging", device_id=device_entry.id, device_class=DEVICE_CLASS_BATTERY_CHARGING, ) entity_reg.async_get_or_create( "sensor", "powerwall", "battery", device_id=device_entry.id, device_class=DEVICE_CLASS_BATTERY, ) light = entity_reg.async_get_or_create( "light", "powerwall", "demo", device_id=device_entry.id ) # Delete the device to make sure we fallback # to using the platform device_reg.async_remove_device(device_entry.id) hass.states.async_set(light.entity_id, STATE_ON) def _mock_get_accessory(*args, **kwargs): return [None, "acc", None] with patch.object(homekit.bridge, "add_accessory"), patch( f"{PATH_HOMEKIT}.show_setup_message" ), patch(f"{PATH_HOMEKIT}.get_accessory") as mock_get_acc, patch( "pyhap.accessory_driver.AccessoryDriver.start" ): await homekit.async_start() await hass.async_block_till_done() mock_get_acc.assert_called_with( hass, hk_driver, ANY, ANY, { "platform": "Tesla Powerwall", "linked_battery_charging_sensor": "binary_sensor.powerwall_battery_charging", "linked_battery_sensor": "sensor.powerwall_battery", }, )
async def test_belgian_meter(hass, dsmr_connection_fixture): """Test if Belgian meter is correctly parsed.""" (connection_factory, transport, protocol) = dsmr_connection_fixture from dsmr_parser.obis_references import ( BELGIUM_HOURLY_GAS_METER_READING, ELECTRICITY_ACTIVE_TARIFF, ) from dsmr_parser.objects import CosemObject, MBusObject entry_data = { "port": "/dev/ttyUSB0", "dsmr_version": "5B", "precision": 4, "reconnect_interval": 30, "serial_id": "1234", "serial_id_gas": "5678", } entry_options = { "time_between_update": 0, } telegram = { BELGIUM_HOURLY_GAS_METER_READING: MBusObject([ { "value": datetime.datetime.fromtimestamp(1551642213) }, { "value": Decimal(745.695), "unit": VOLUME_CUBIC_METERS }, ]), ELECTRICITY_ACTIVE_TARIFF: CosemObject([{ "value": "0001", "unit": "" }]), } mock_entry = MockConfigEntry(domain="dsmr", unique_id="/dev/ttyUSB0", data=entry_data, options=entry_options) mock_entry.add_to_hass(hass) await hass.config_entries.async_setup(mock_entry.entry_id) await hass.async_block_till_done() telegram_callback = connection_factory.call_args_list[0][0][2] # simulate a telegram pushed from the smartmeter and parsed by dsmr_parser telegram_callback(telegram) # after receiving telegram entities need to have the chance to update await asyncio.sleep(0) # tariff should be translated in human readable and have no unit power_tariff = hass.states.get("sensor.power_tariff") assert power_tariff.state == "normal" assert power_tariff.attributes.get("unit_of_measurement") == "" # check if gas consumption is parsed correctly gas_consumption = hass.states.get("sensor.gas_consumption") assert gas_consumption.state == "745.695" assert gas_consumption.attributes.get( "unit_of_measurement") == VOLUME_CUBIC_METERS
async def test_unique_id_migration(mock_hc, hass, mock_write_config): """Test migration of switch unique ids to stable ones.""" entry = MockConfigEntry( domain=DOMAIN, data={CONF_HOST: "192.0.2.0", CONF_NAME: HUB_NAME} ) entry.add_to_hass(hass) mock_registry( hass, { # old format ENTITY_WATCH_TV: er.RegistryEntry( entity_id=ENTITY_WATCH_TV, unique_id="123443-Watch TV", platform="harmony", config_entry_id=entry.entry_id, ), # old format, activity name with - ENTITY_NILE_TV: er.RegistryEntry( entity_id=ENTITY_NILE_TV, unique_id="123443-Nile-TV", platform="harmony", config_entry_id=entry.entry_id, ), # new format ENTITY_PLAY_MUSIC: er.RegistryEntry( entity_id=ENTITY_PLAY_MUSIC, unique_id=f"activity_{PLAY_MUSIC_ACTIVITY_ID}", platform="harmony", config_entry_id=entry.entry_id, ), # old entity which no longer has a matching activity on the hub. skipped. "switch.some_other_activity": er.RegistryEntry( entity_id="switch.some_other_activity", unique_id="123443-Some Other Activity", platform="harmony", config_entry_id=entry.entry_id, ), # select entity ENTITY_SELECT: er.RegistryEntry( entity_id=ENTITY_SELECT, unique_id=f"{HUB_NAME}_activities", platform="harmony", config_entry_id=entry.entry_id, ), }, ) assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() ent_reg = er.async_get(hass) switch_tv = ent_reg.async_get(ENTITY_WATCH_TV) assert switch_tv.unique_id == f"activity_{WATCH_TV_ACTIVITY_ID}" switch_nile = ent_reg.async_get(ENTITY_NILE_TV) assert switch_nile.unique_id == f"activity_{NILE_TV_ACTIVITY_ID}" switch_music = ent_reg.async_get(ENTITY_PLAY_MUSIC) assert switch_music.unique_id == f"activity_{PLAY_MUSIC_ACTIVITY_ID}" select_activities = ent_reg.async_get(ENTITY_SELECT) assert select_activities.unique_id == f"{HUB_NAME}_activities"
async def test_service_calls(hass: HomeAssistant) -> None: """Test service calls to cover.""" await async_setup_component(hass, "switch", {"switch": [{ "platform": "demo" }]}) config_entry = MockConfigEntry( data={}, domain=DOMAIN, options={ CONF_ENTITY_ID: "switch.decorative_lights", CONF_TARGET_DOMAIN: Platform.COVER, }, title="garage_door", ) config_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert hass.states.get("cover.garage_door").state == STATE_OPEN await hass.services.async_call( COVER_DOMAIN, SERVICE_TOGGLE, {CONF_ENTITY_ID: "cover.garage_door"}, blocking=True, ) assert hass.states.get("switch.decorative_lights").state == STATE_OFF assert hass.states.get("cover.garage_door").state == STATE_CLOSED await hass.services.async_call( COVER_DOMAIN, SERVICE_OPEN_COVER, {CONF_ENTITY_ID: "cover.garage_door"}, blocking=True, ) assert hass.states.get("switch.decorative_lights").state == STATE_ON assert hass.states.get("cover.garage_door").state == STATE_OPEN await hass.services.async_call( COVER_DOMAIN, SERVICE_CLOSE_COVER, {CONF_ENTITY_ID: "cover.garage_door"}, blocking=True, ) assert hass.states.get("switch.decorative_lights").state == STATE_OFF assert hass.states.get("cover.garage_door").state == STATE_CLOSED await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_ON, {CONF_ENTITY_ID: "switch.decorative_lights"}, blocking=True, ) assert hass.states.get("switch.decorative_lights").state == STATE_ON assert hass.states.get("cover.garage_door").state == STATE_OPEN await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, {CONF_ENTITY_ID: "switch.decorative_lights"}, blocking=True, ) assert hass.states.get("switch.decorative_lights").state == STATE_OFF assert hass.states.get("cover.garage_door").state == STATE_CLOSED await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TOGGLE, {CONF_ENTITY_ID: "switch.decorative_lights"}, blocking=True, ) assert hass.states.get("switch.decorative_lights").state == STATE_ON assert hass.states.get("cover.garage_door").state == STATE_OPEN
async def test_homekit_finds_linked_motion_sensors( hass, hk_driver, debounce_patcher, device_reg, entity_reg ): """Test HomeKit start method.""" entry = await async_init_integration(hass) homekit = HomeKit( hass, None, None, None, {}, {"camera.camera_demo": {}}, DEFAULT_SAFE_MODE, advertise_ip=None, entry_id=entry.entry_id, ) homekit.driver = hk_driver # pylint: disable=protected-access homekit._filter = Mock(return_value=True) homekit.bridge = HomeBridge(hass, hk_driver, "mock_bridge") config_entry = MockConfigEntry(domain="test", data={}) config_entry.add_to_hass(hass) device_entry = device_reg.async_get_or_create( config_entry_id=config_entry.entry_id, sw_version="0.16.0", model="Camera Server", manufacturer="Ubq", connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) binary_motion_sensor = entity_reg.async_get_or_create( "binary_sensor", "camera", "motion_sensor", device_id=device_entry.id, device_class=DEVICE_CLASS_MOTION, ) camera = entity_reg.async_get_or_create( "camera", "camera", "demo", device_id=device_entry.id ) hass.states.async_set( binary_motion_sensor.entity_id, STATE_ON, {ATTR_DEVICE_CLASS: DEVICE_CLASS_MOTION}, ) hass.states.async_set(camera.entity_id, STATE_ON) def _mock_get_accessory(*args, **kwargs): return [None, "acc", None] with patch.object(homekit.bridge, "add_accessory"), patch( f"{PATH_HOMEKIT}.show_setup_message" ), patch(f"{PATH_HOMEKIT}.get_accessory") as mock_get_acc, patch( "pyhap.accessory_driver.AccessoryDriver.start" ): await homekit.async_start() await hass.async_block_till_done() mock_get_acc.assert_called_with( hass, hk_driver, ANY, ANY, { "manufacturer": "Ubq", "model": "Camera Server", "sw_version": "0.16.0", "linked_motion_sensor": "binary_sensor.camera_motion_sensor", }, )
def config_entry_fixture(): """Create a mock Sonos config entry.""" return MockConfigEntry(domain=DOMAIN, title="Sonos")
async def test_setup_entry_platform_not_exist(hass): """Test setup entry fails if platform doesnt exist.""" component = EntityComponent(_LOGGER, DOMAIN, hass) entry = MockConfigEntry(domain='non_existing') assert (await component.async_setup_entry(entry)) is False
async def test_one_weather_site_running(hass, requests_mock, legacy_patchable_time): """Test the Met Office weather platform.""" # all metoffice test data encapsulated in here mock_json = json.loads(load_fixture("metoffice.json")) all_sites = json.dumps(mock_json["all_sites"]) wavertree_hourly = json.dumps(mock_json["wavertree_hourly"]) wavertree_daily = json.dumps(mock_json["wavertree_daily"]) requests_mock.get("/public/data/val/wxfcs/all/json/sitelist/", text=all_sites) requests_mock.get( "/public/data/val/wxfcs/all/json/354107?res=3hourly", text=wavertree_hourly, ) requests_mock.get( "/public/data/val/wxfcs/all/json/354107?res=daily", text=wavertree_daily, ) entry = MockConfigEntry( domain=DOMAIN, data=METOFFICE_CONFIG_WAVERTREE, ) entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() dev_reg = get_dev_reg(hass) assert len(dev_reg.devices) == 1 device_wavertree = dev_reg.async_get_device( identifiers=DEVICE_KEY_WAVERTREE) assert device_wavertree.name == "Met Office Wavertree" # Wavertree 3-hourly weather platform expected results weather = hass.states.get("weather.met_office_wavertree_3_hourly") assert weather assert weather.state == "sunny" assert weather.attributes.get("temperature") == 17 assert weather.attributes.get("wind_speed") == 9 assert weather.attributes.get("wind_bearing") == "SSE" assert weather.attributes.get("visibility") == "Good - 10-20" assert weather.attributes.get("humidity") == 50 # Forecasts added - just pick out 1 entry to check assert len(weather.attributes.get("forecast")) == 35 assert (weather.attributes.get("forecast")[26]["datetime"] == "2020-04-28T21:00:00+00:00") assert weather.attributes.get("forecast")[26]["condition"] == "cloudy" assert weather.attributes.get( "forecast")[26]["precipitation_probability"] == 9 assert weather.attributes.get("forecast")[26]["temperature"] == 10 assert weather.attributes.get("forecast")[26]["wind_speed"] == 4 assert weather.attributes.get("forecast")[26]["wind_bearing"] == "NNE" # Wavertree daily weather platform expected results weather = hass.states.get("weather.met_office_wavertree_daily") assert weather assert weather.state == "sunny" assert weather.attributes.get("temperature") == 19 assert weather.attributes.get("wind_speed") == 9 assert weather.attributes.get("wind_bearing") == "SSE" assert weather.attributes.get("visibility") == "Good - 10-20" assert weather.attributes.get("humidity") == 50 # Also has Forecasts added - again, just pick out 1 entry to check assert len(weather.attributes.get("forecast")) == 8 assert (weather.attributes.get("forecast")[7]["datetime"] == "2020-04-29T12:00:00+00:00") assert weather.attributes.get("forecast")[7]["condition"] == "rainy" assert weather.attributes.get( "forecast")[7]["precipitation_probability"] == 59 assert weather.attributes.get("forecast")[7]["temperature"] == 13 assert weather.attributes.get("forecast")[7]["wind_speed"] == 13 assert weather.attributes.get("forecast")[7]["wind_bearing"] == "SE"
async def test_discovery_with_existing_device_present(hass: HomeAssistant): """Test setting up discovery.""" config_entry = MockConfigEntry( domain=DOMAIN, data={CONF_ID: "0x000000000099999", CONF_HOST: "4.4.4.4"} ) config_entry.add_to_hass(hass) alternate_bulb = _mocked_bulb() alternate_bulb.capabilities["id"] = "0x000000000099999" alternate_bulb.capabilities["location"] = "yeelight://4.4.4.4" with _patch_discovery(), _patch_discovery_timeout(), _patch_discovery_interval(), patch( f"{MODULE}.AsyncBulb", return_value=alternate_bulb ): await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() await hass.async_block_till_done() result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) assert result["type"] == "form" assert result["step_id"] == "user" assert not result["errors"] with _patch_discovery(), _patch_discovery_timeout(), _patch_discovery_interval(): result2 = await hass.config_entries.flow.async_configure(result["flow_id"], {}) await hass.async_block_till_done() await hass.async_block_till_done() assert result2["type"] == "form" assert result2["step_id"] == "pick_device" assert not result2["errors"] # Now abort and make sure we can start over result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) assert result["type"] == "form" assert result["step_id"] == "user" assert not result["errors"] with _patch_discovery(), _patch_discovery_interval(): result2 = await hass.config_entries.flow.async_configure(result["flow_id"], {}) assert result2["type"] == "form" assert result2["step_id"] == "pick_device" assert not result2["errors"] with _patch_discovery(), _patch_discovery_interval(), patch( f"{MODULE}.AsyncBulb", return_value=_mocked_bulb() ): result3 = await hass.config_entries.flow.async_configure( result["flow_id"], {CONF_DEVICE: ID} ) assert result3["type"] == "create_entry" assert result3["title"] == UNIQUE_FRIENDLY_NAME assert result3["data"] == { CONF_ID: ID, CONF_HOST: IP_ADDRESS, CONF_MODEL: MODEL, } await hass.async_block_till_done() await hass.async_block_till_done() # ignore configured devices result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) assert result["type"] == "form" assert result["step_id"] == "user" assert not result["errors"] with _patch_discovery(), _patch_discovery_interval(): result2 = await hass.config_entries.flow.async_configure(result["flow_id"], {}) assert result2["type"] == "abort" assert result2["reason"] == "no_devices_found"
async def test_setup_imported(hass): """Test async_setup with imported config options.""" legacy_persist_file_path = hass.config.path(HOMEKIT_FILE) legacy_aid_storage_path = hass.config.path(STORAGE_DIR, "homekit.aids") legacy_homekit_state_contents = {"homekit.state": 1} legacy_homekit_aids_contents = {"homekit.aids": 1} await hass.async_add_executor_job( _write_data, legacy_persist_file_path, legacy_homekit_state_contents ) await hass.async_add_executor_job( _write_data, legacy_aid_storage_path, legacy_homekit_aids_contents ) entry = MockConfigEntry( domain=DOMAIN, source=SOURCE_IMPORT, data={CONF_NAME: BRIDGE_NAME, CONF_PORT: DEFAULT_PORT, CONF_ENTRY_INDEX: 0}, options={}, ) entry.add_to_hass(hass) with patch(f"{PATH_HOMEKIT}.HomeKit") as mock_homekit: mock_homekit.return_value = homekit = Mock() type(homekit).async_start = AsyncMock() assert await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() mock_homekit.assert_any_call( hass, BRIDGE_NAME, DEFAULT_PORT, None, ANY, {}, DEFAULT_SAFE_MODE, None, entry.entry_id, ) assert mock_homekit().setup.called is True # Test auto start enabled mock_homekit.reset_mock() hass.bus.async_fire(EVENT_HOMEASSISTANT_START) await hass.async_block_till_done() mock_homekit().async_start.assert_called() migrated_persist_file_path = get_persist_fullpath_for_entry_id(hass, entry.entry_id) assert ( await hass.async_add_executor_job( json_util.load_json, migrated_persist_file_path ) == legacy_homekit_state_contents ) os.unlink(migrated_persist_file_path) migrated_aid_file_path = get_aid_storage_fullpath_for_entry_id(hass, entry.entry_id) assert ( await hass.async_add_executor_job(json_util.load_json, migrated_aid_file_path) == legacy_homekit_aids_contents ) os.unlink(migrated_aid_file_path)
async def test_two_weather_sites_running(hass, requests_mock, legacy_patchable_time): """Test we handle two different weather sites both running.""" # all metoffice test data encapsulated in here mock_json = json.loads(load_fixture("metoffice.json")) all_sites = json.dumps(mock_json["all_sites"]) wavertree_hourly = json.dumps(mock_json["wavertree_hourly"]) wavertree_daily = json.dumps(mock_json["wavertree_daily"]) kingslynn_hourly = json.dumps(mock_json["kingslynn_hourly"]) kingslynn_daily = json.dumps(mock_json["kingslynn_daily"]) requests_mock.get("/public/data/val/wxfcs/all/json/sitelist/", text=all_sites) requests_mock.get("/public/data/val/wxfcs/all/json/354107?res=3hourly", text=wavertree_hourly) requests_mock.get("/public/data/val/wxfcs/all/json/354107?res=daily", text=wavertree_daily) requests_mock.get("/public/data/val/wxfcs/all/json/322380?res=3hourly", text=kingslynn_hourly) requests_mock.get("/public/data/val/wxfcs/all/json/322380?res=daily", text=kingslynn_daily) entry = MockConfigEntry( domain=DOMAIN, data=METOFFICE_CONFIG_WAVERTREE, ) entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) entry2 = MockConfigEntry( domain=DOMAIN, data=METOFFICE_CONFIG_KINGSLYNN, ) entry2.add_to_hass(hass) await hass.config_entries.async_setup(entry2.entry_id) await hass.async_block_till_done() dev_reg = get_dev_reg(hass) assert len(dev_reg.devices) == 2 device_kingslynn = dev_reg.async_get_device( identifiers=DEVICE_KEY_KINGSLYNN) assert device_kingslynn.name == "Met Office King's Lynn" device_wavertree = dev_reg.async_get_device( identifiers=DEVICE_KEY_WAVERTREE) assert device_wavertree.name == "Met Office Wavertree" # Wavertree 3-hourly weather platform expected results weather = hass.states.get("weather.met_office_wavertree_3_hourly") assert weather assert weather.state == "sunny" assert weather.attributes.get("temperature") == 17 assert weather.attributes.get("wind_speed") == 9 assert weather.attributes.get("wind_bearing") == "SSE" assert weather.attributes.get("visibility") == "Good - 10-20" assert weather.attributes.get("humidity") == 50 # Forecasts added - just pick out 1 entry to check assert len(weather.attributes.get("forecast")) == 35 assert (weather.attributes.get("forecast")[18]["datetime"] == "2020-04-27T21:00:00+00:00") assert weather.attributes.get("forecast")[18]["condition"] == "clear-night" assert weather.attributes.get( "forecast")[18]["precipitation_probability"] == 1 assert weather.attributes.get("forecast")[18]["temperature"] == 9 assert weather.attributes.get("forecast")[18]["wind_speed"] == 4 assert weather.attributes.get("forecast")[18]["wind_bearing"] == "NW" # Wavertree daily weather platform expected results weather = hass.states.get("weather.met_office_wavertree_daily") assert weather assert weather.state == "sunny" assert weather.attributes.get("temperature") == 19 assert weather.attributes.get("wind_speed") == 9 assert weather.attributes.get("wind_bearing") == "SSE" assert weather.attributes.get("visibility") == "Good - 10-20" assert weather.attributes.get("humidity") == 50 # Also has Forecasts added - again, just pick out 1 entry to check assert len(weather.attributes.get("forecast")) == 8 assert (weather.attributes.get("forecast")[7]["datetime"] == "2020-04-29T12:00:00+00:00") assert weather.attributes.get("forecast")[7]["condition"] == "rainy" assert weather.attributes.get( "forecast")[7]["precipitation_probability"] == 59 assert weather.attributes.get("forecast")[7]["temperature"] == 13 assert weather.attributes.get("forecast")[7]["wind_speed"] == 13 assert weather.attributes.get("forecast")[7]["wind_bearing"] == "SE" # King's Lynn 3-hourly weather platform expected results weather = hass.states.get("weather.met_office_king_s_lynn_3_hourly") assert weather assert weather.state == "sunny" assert weather.attributes.get("temperature") == 14 assert weather.attributes.get("wind_speed") == 2 assert weather.attributes.get("wind_bearing") == "E" assert weather.attributes.get("visibility") == "Very Good - 20-40" assert weather.attributes.get("humidity") == 60 # Also has Forecast added - just pick out 1 entry to check assert len(weather.attributes.get("forecast")) == 35 assert (weather.attributes.get("forecast")[18]["datetime"] == "2020-04-27T21:00:00+00:00") assert weather.attributes.get("forecast")[18]["condition"] == "cloudy" assert weather.attributes.get( "forecast")[18]["precipitation_probability"] == 9 assert weather.attributes.get("forecast")[18]["temperature"] == 10 assert weather.attributes.get("forecast")[18]["wind_speed"] == 7 assert weather.attributes.get("forecast")[18]["wind_bearing"] == "SE" # King's Lynn daily weather platform expected results weather = hass.states.get("weather.met_office_king_s_lynn_daily") assert weather assert weather.state == "cloudy" assert weather.attributes.get("temperature") == 9 assert weather.attributes.get("wind_speed") == 4 assert weather.attributes.get("wind_bearing") == "ESE" assert weather.attributes.get("visibility") == "Very Good - 20-40" assert weather.attributes.get("humidity") == 75 # All should have Forecast added - again, just picking out 1 entry to check assert len(weather.attributes.get("forecast")) == 8 assert (weather.attributes.get("forecast")[5]["datetime"] == "2020-04-28T12:00:00+00:00") assert weather.attributes.get("forecast")[5]["condition"] == "cloudy" assert weather.attributes.get( "forecast")[5]["precipitation_probability"] == 14 assert weather.attributes.get("forecast")[5]["temperature"] == 11 assert weather.attributes.get("forecast")[5]["wind_speed"] == 7 assert weather.attributes.get("forecast")[5]["wind_bearing"] == "ESE"
async def test_addon_installed_already_configured( opp, supervisor, addon_installed, addon_options, set_addon_options, start_addon, get_addon_discovery_info, ): """Test that only one unique instance is allowed when add-on is installed.""" entry = MockConfigEntry( domain=DOMAIN, data={ "url": "ws://localhost:3000", "usb_path": "/test", "network_key": "abc123", }, title=TITLE, unique_id=1234, ) entry.add_to_opp(opp) await setup.async_setup_component(opp, "persistent_notification", {}) result = await opp.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER}) assert result["type"] == "form" assert result["step_id"] == "on_supervisor" result = await opp.config_entries.flow.async_configure( result["flow_id"], {"use_addon": True}) assert result["type"] == "form" assert result["step_id"] == "configure_addon" result = await opp.config_entries.flow.async_configure( result["flow_id"], { "usb_path": "/test_new", "network_key": "def456" }) assert set_addon_options.call_args == call( opp, "core_zwave_js", {"options": { "device": "/test_new", "network_key": "def456" }}, ) assert result["type"] == "progress" assert result["step_id"] == "start_addon" await opp.async_block_till_done() result = await opp.config_entries.flow.async_configure(result["flow_id"]) assert start_addon.call_args == call(opp, "core_zwave_js") assert result["type"] == "abort" assert result["reason"] == "already_configured" assert entry.data["url"] == "ws://host1:3001" assert entry.data["usb_path"] == "/test_new" assert entry.data["network_key"] == "def456"
async def test_two_step_options_flow(hass, client): """Test we can finish a two step options flow.""" mock_integration( hass, MockModule('test', async_setup_entry=mock_coro_func(True))) class TestFlow(core_ce.ConfigFlow): @staticmethod @callback def async_get_options_flow(config, options): class OptionsFlowHandler(data_entry_flow.FlowHandler): def __init__(self, config, options): self.config = config self.options = options async def async_step_init(self, user_input=None): return self.async_show_form(step_id='finish', data_schema=vol.Schema( {'enabled': bool})) async def async_step_finish(self, user_input=None): return self.async_create_entry(title='Enable disable', data=user_input) return OptionsFlowHandler(config, options) MockConfigEntry( domain='test', entry_id='test1', source='bla', connection_class=core_ce.CONN_CLASS_LOCAL_POLL, ).add_to_hass(hass) entry = hass.config_entries._entries[0] with patch.dict(HANDLERS, {'test': TestFlow}): url = '/api/config/config_entries/entry/option/flow' resp = await client.post(url, json={'handler': entry.entry_id}) assert resp.status == 200 data = await resp.json() flow_id = data.pop('flow_id') assert data == { 'type': 'form', 'handler': 'test1', 'step_id': 'finish', 'data_schema': [{ 'name': 'enabled', 'type': 'boolean' }], 'description_placeholders': None, 'errors': None } with patch.dict(HANDLERS, {'test': TestFlow}): resp = await client.post( '/api/config/config_entries/options/flow/{}'.format(flow_id), json={'enabled': True}) assert resp.status == 200 data = await resp.json() data.pop('flow_id') assert data == { 'handler': 'test1', 'type': 'create_entry', 'title': 'Enable disable', 'version': 1, 'description': None, 'description_placeholders': None, }