From 7dbe8070f7823c9fa65827b4b9cfb376eaaf609c Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Thu, 2 Sep 2021 20:44:50 +0200 Subject: [PATCH] Mock out network.util.async_get_source_ip in tests (#55592) --- .../emulated_roku/test_config_flow.py | 4 +- tests/components/emulated_roku/test_init.py | 4 +- tests/components/fritz/test_config_flow.py | 44 +++++++++++------ tests/components/homekit/test_config_flow.py | 32 +++++++------ tests/components/homekit/test_homekit.py | 9 +++- .../nmap_tracker/test_config_flow.py | 18 +++---- tests/components/ssdp/test_init.py | 46 +++++++++++------- tests/components/upnp/test_config_flow.py | 16 +++---- tests/components/upnp/test_init.py | 2 +- .../yamaha_musiccast/test_config_flow.py | 47 ++++++++++++++----- tests/components/yeelight/conftest.py | 7 +++ tests/conftest.py | 10 ++++ 12 files changed, 159 insertions(+), 80 deletions(-) diff --git a/tests/components/emulated_roku/test_config_flow.py b/tests/components/emulated_roku/test_config_flow.py index 23c807cbfa3..3d1438dafb9 100644 --- a/tests/components/emulated_roku/test_config_flow.py +++ b/tests/components/emulated_roku/test_config_flow.py @@ -5,7 +5,7 @@ from homeassistant.components.emulated_roku import config_flow from tests.common import MockConfigEntry -async def test_flow_works(hass): +async def test_flow_works(hass, mock_get_source_ip): """Test that config flow works.""" result = await hass.config_entries.flow.async_init( config_flow.DOMAIN, @@ -18,7 +18,7 @@ async def test_flow_works(hass): assert result["data"] == {"name": "Emulated Roku Test", "listen_port": 8060} -async def test_flow_already_registered_entry(hass): +async def test_flow_already_registered_entry(hass, mock_get_source_ip): """Test that config flow doesn't allow existing names.""" MockConfigEntry( domain="emulated_roku", data={"name": "Emulated Roku Test", "listen_port": 8062} diff --git a/tests/components/emulated_roku/test_init.py b/tests/components/emulated_roku/test_init.py index d69df5a1fbe..93db9124414 100644 --- a/tests/components/emulated_roku/test_init.py +++ b/tests/components/emulated_roku/test_init.py @@ -5,7 +5,7 @@ from homeassistant.components import emulated_roku from homeassistant.setup import async_setup_component -async def test_config_required_fields(hass): +async def test_config_required_fields(hass, mock_get_source_ip): """Test that configuration is successful with required fields.""" with patch.object(emulated_roku, "configured_servers", return_value=[]), patch( "homeassistant.components.emulated_roku.binding.EmulatedRokuServer", @@ -30,7 +30,7 @@ async def test_config_required_fields(hass): ) -async def test_config_already_registered_not_configured(hass): +async def test_config_already_registered_not_configured(hass, mock_get_source_ip): """Test that an already registered name causes the entry to be ignored.""" with patch( "homeassistant.components.emulated_roku.binding.EmulatedRokuServer", diff --git a/tests/components/fritz/test_config_flow.py b/tests/components/fritz/test_config_flow.py index 1551a508277..1b2a89f0450 100644 --- a/tests/components/fritz/test_config_flow.py +++ b/tests/components/fritz/test_config_flow.py @@ -67,7 +67,7 @@ def fc_class_mock(): yield result -async def test_user(hass: HomeAssistant, fc_class_mock): +async def test_user(hass: HomeAssistant, fc_class_mock, mock_get_source_ip): """Test starting a flow by user.""" with patch( "homeassistant.components.fritz.common.FritzConnection", @@ -108,7 +108,9 @@ async def test_user(hass: HomeAssistant, fc_class_mock): assert mock_setup_entry.called -async def test_user_already_configured(hass: HomeAssistant, fc_class_mock): +async def test_user_already_configured( + hass: HomeAssistant, fc_class_mock, mock_get_source_ip +): """Test starting a flow by user with an already configured device.""" mock_config = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) @@ -142,7 +144,7 @@ async def test_user_already_configured(hass: HomeAssistant, fc_class_mock): assert result["errors"]["base"] == "already_configured" -async def test_exception_security(hass: HomeAssistant): +async def test_exception_security(hass: HomeAssistant, mock_get_source_ip): """Test starting a flow by user with invalid credentials.""" result = await hass.config_entries.flow.async_init( @@ -165,7 +167,7 @@ async def test_exception_security(hass: HomeAssistant): assert result["errors"]["base"] == ERROR_AUTH_INVALID -async def test_exception_connection(hass: HomeAssistant): +async def test_exception_connection(hass: HomeAssistant, mock_get_source_ip): """Test starting a flow by user with a connection error.""" result = await hass.config_entries.flow.async_init( @@ -188,7 +190,7 @@ async def test_exception_connection(hass: HomeAssistant): assert result["errors"]["base"] == ERROR_CANNOT_CONNECT -async def test_exception_unknown(hass: HomeAssistant): +async def test_exception_unknown(hass: HomeAssistant, mock_get_source_ip): """Test starting a flow by user with an unknown exception.""" result = await hass.config_entries.flow.async_init( @@ -211,7 +213,9 @@ async def test_exception_unknown(hass: HomeAssistant): assert result["errors"]["base"] == ERROR_UNKNOWN -async def test_reauth_successful(hass: HomeAssistant, fc_class_mock): +async def test_reauth_successful( + hass: HomeAssistant, fc_class_mock, mock_get_source_ip +): """Test starting a reauthentication flow.""" mock_config = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) @@ -256,7 +260,9 @@ async def test_reauth_successful(hass: HomeAssistant, fc_class_mock): assert mock_setup_entry.called -async def test_reauth_not_successful(hass: HomeAssistant, fc_class_mock): +async def test_reauth_not_successful( + hass: HomeAssistant, fc_class_mock, mock_get_source_ip +): """Test starting a reauthentication flow but no connection found.""" mock_config = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) @@ -289,7 +295,9 @@ async def test_reauth_not_successful(hass: HomeAssistant, fc_class_mock): assert result["errors"]["base"] == "cannot_connect" -async def test_ssdp_already_configured(hass: HomeAssistant, fc_class_mock): +async def test_ssdp_already_configured( + hass: HomeAssistant, fc_class_mock, mock_get_source_ip +): """Test starting a flow from discovery with an already configured device.""" mock_config = MockConfigEntry( @@ -311,7 +319,9 @@ async def test_ssdp_already_configured(hass: HomeAssistant, fc_class_mock): assert result["reason"] == "already_configured" -async def test_ssdp_already_configured_host(hass: HomeAssistant, fc_class_mock): +async def test_ssdp_already_configured_host( + hass: HomeAssistant, fc_class_mock, mock_get_source_ip +): """Test starting a flow from discovery with an already configured host.""" mock_config = MockConfigEntry( @@ -333,7 +343,9 @@ async def test_ssdp_already_configured_host(hass: HomeAssistant, fc_class_mock): assert result["reason"] == "already_configured" -async def test_ssdp_already_configured_host_uuid(hass: HomeAssistant, fc_class_mock): +async def test_ssdp_already_configured_host_uuid( + hass: HomeAssistant, fc_class_mock, mock_get_source_ip +): """Test starting a flow from discovery with an already configured uuid.""" mock_config = MockConfigEntry( @@ -355,7 +367,9 @@ async def test_ssdp_already_configured_host_uuid(hass: HomeAssistant, fc_class_m assert result["reason"] == "already_configured" -async def test_ssdp_already_in_progress_host(hass: HomeAssistant, fc_class_mock): +async def test_ssdp_already_in_progress_host( + hass: HomeAssistant, fc_class_mock, mock_get_source_ip +): """Test starting a flow from discovery twice.""" with patch( "homeassistant.components.fritz.common.FritzConnection", @@ -377,7 +391,7 @@ async def test_ssdp_already_in_progress_host(hass: HomeAssistant, fc_class_mock) assert result["reason"] == "already_in_progress" -async def test_ssdp(hass: HomeAssistant, fc_class_mock): +async def test_ssdp(hass: HomeAssistant, fc_class_mock, mock_get_source_ip): """Test starting a flow from discovery.""" with patch( "homeassistant.components.fritz.common.FritzConnection", @@ -417,7 +431,7 @@ async def test_ssdp(hass: HomeAssistant, fc_class_mock): assert mock_setup_entry.called -async def test_ssdp_exception(hass: HomeAssistant): +async def test_ssdp_exception(hass: HomeAssistant, mock_get_source_ip): """Test starting a flow from discovery but no device found.""" with patch( "homeassistant.components.fritz.common.FritzConnection", @@ -442,7 +456,7 @@ async def test_ssdp_exception(hass: HomeAssistant): assert result["step_id"] == "confirm" -async def test_import(hass: HomeAssistant, fc_class_mock): +async def test_import(hass: HomeAssistant, fc_class_mock, mock_get_source_ip): """Test importing.""" with patch( "homeassistant.components.fritz.common.FritzConnection", @@ -473,7 +487,7 @@ async def test_import(hass: HomeAssistant, fc_class_mock): assert mock_setup_entry.called -async def test_options_flow(hass: HomeAssistant, fc_class_mock): +async def test_options_flow(hass: HomeAssistant, fc_class_mock, mock_get_source_ip): """Test options flow.""" mock_config = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) diff --git a/tests/components/homekit/test_config_flow.py b/tests/components/homekit/test_config_flow.py index af803d50cf4..b2e9af3816a 100644 --- a/tests/components/homekit/test_config_flow.py +++ b/tests/components/homekit/test_config_flow.py @@ -33,7 +33,7 @@ def _mock_config_entry_with_options_populated(): ) -async def test_setup_in_bridge_mode(hass): +async def test_setup_in_bridge_mode(hass, mock_get_source_ip): """Test we can setup a new instance in bridge mode.""" await setup.async_setup_component(hass, "persistent_notification", {}) result = await hass.config_entries.flow.async_init( @@ -83,7 +83,7 @@ async def test_setup_in_bridge_mode(hass): assert len(mock_setup_entry.mock_calls) == 1 -async def test_setup_in_bridge_mode_name_taken(hass): +async def test_setup_in_bridge_mode_name_taken(hass, mock_get_source_ip): """Test we can setup a new instance in bridge mode when the name is taken.""" await setup.async_setup_component(hass, "persistent_notification", {}) @@ -141,7 +141,9 @@ async def test_setup_in_bridge_mode_name_taken(hass): assert len(mock_setup_entry.mock_calls) == 2 -async def test_setup_creates_entries_for_accessory_mode_devices(hass): +async def test_setup_creates_entries_for_accessory_mode_devices( + hass, mock_get_source_ip +): """Test we can setup a new instance and we create entries for accessory mode devices.""" hass.states.async_set("camera.one", "on") hass.states.async_set("camera.existing", "on") @@ -231,7 +233,7 @@ async def test_setup_creates_entries_for_accessory_mode_devices(hass): assert len(mock_setup_entry.mock_calls) == 7 -async def test_import(hass): +async def test_import(hass, mock_get_source_ip): """Test we can import instance.""" await setup.async_setup_component(hass, "persistent_notification", {}) @@ -275,7 +277,7 @@ async def test_import(hass): @pytest.mark.parametrize("auto_start", [True, False]) -async def test_options_flow_exclude_mode_advanced(auto_start, hass): +async def test_options_flow_exclude_mode_advanced(auto_start, hass, mock_get_source_ip): """Test config flow options in exclude mode with advanced options.""" config_entry = _mock_config_entry_with_options_populated() @@ -326,7 +328,7 @@ async def test_options_flow_exclude_mode_advanced(auto_start, hass): } -async def test_options_flow_exclude_mode_basic(hass): +async def test_options_flow_exclude_mode_basic(hass, mock_get_source_ip): """Test config flow options in exclude mode.""" config_entry = _mock_config_entry_with_options_populated() @@ -368,7 +370,7 @@ async def test_options_flow_exclude_mode_basic(hass): async def test_options_flow_devices( - mock_hap, hass, demo_cleanup, device_reg, entity_reg + mock_hap, hass, demo_cleanup, device_reg, entity_reg, mock_get_source_ip ): """Test devices can be bridged.""" config_entry = _mock_config_entry_with_options_populated() @@ -431,7 +433,9 @@ async def test_options_flow_devices( } -async def test_options_flow_devices_preserved_when_advanced_off(mock_hap, hass): +async def test_options_flow_devices_preserved_when_advanced_off( + mock_hap, hass, mock_get_source_ip +): """Test devices are preserved if they were added in advanced mode but it was turned off.""" config_entry = MockConfigEntry( domain=DOMAIN, @@ -499,7 +503,7 @@ async def test_options_flow_devices_preserved_when_advanced_off(mock_hap, hass): } -async def test_options_flow_include_mode_basic(hass): +async def test_options_flow_include_mode_basic(hass, mock_get_source_ip): """Test config flow options in include mode.""" config_entry = _mock_config_entry_with_options_populated() @@ -542,7 +546,7 @@ async def test_options_flow_include_mode_basic(hass): } -async def test_options_flow_exclude_mode_with_cameras(hass): +async def test_options_flow_exclude_mode_with_cameras(hass, mock_get_source_ip): """Test config flow options in exclude mode with cameras.""" config_entry = _mock_config_entry_with_options_populated() @@ -645,7 +649,7 @@ async def test_options_flow_exclude_mode_with_cameras(hass): } -async def test_options_flow_include_mode_with_cameras(hass): +async def test_options_flow_include_mode_with_cameras(hass, mock_get_source_ip): """Test config flow options in include mode with cameras.""" config_entry = _mock_config_entry_with_options_populated() @@ -772,7 +776,7 @@ async def test_options_flow_include_mode_with_cameras(hass): } -async def test_options_flow_blocked_when_from_yaml(hass): +async def test_options_flow_blocked_when_from_yaml(hass, mock_get_source_ip): """Test config flow options.""" config_entry = MockConfigEntry( @@ -812,7 +816,7 @@ async def test_options_flow_blocked_when_from_yaml(hass): assert result2["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY -async def test_options_flow_include_mode_basic_accessory(hass): +async def test_options_flow_include_mode_basic_accessory(hass, mock_get_source_ip): """Test config flow options in include mode with a single accessory.""" config_entry = _mock_config_entry_with_options_populated() @@ -867,7 +871,7 @@ async def test_options_flow_include_mode_basic_accessory(hass): } -async def test_converting_bridge_to_accessory_mode(hass, hk_driver): +async def test_converting_bridge_to_accessory_mode(hass, hk_driver, mock_get_source_ip): """Test we can convert a bridge to accessory mode.""" await setup.async_setup_component(hass, "persistent_notification", {}) result = await hass.config_entries.flow.async_init( diff --git a/tests/components/homekit/test_homekit.py b/tests/components/homekit/test_homekit.py index 4976985fa15..b1ea2ab2a1d 100644 --- a/tests/components/homekit/test_homekit.py +++ b/tests/components/homekit/test_homekit.py @@ -102,6 +102,13 @@ def always_patch_driver(hk_driver): """Load the hk_driver fixture.""" +@pytest.fixture(autouse=True) +def patch_source_ip(mock_get_source_ip): + """Patch homeassistant and pyhap functions for getting local address.""" + with patch("pyhap.util.get_local_address", return_value="10.10.10.10"): + yield + + def _mock_homekit(hass, entry, homekit_mode, entity_filter=None, devices=None): return HomeKit( hass=hass, @@ -1301,7 +1308,7 @@ async def test_homekit_uses_system_zeroconf(hass, hk_driver, mock_zeroconf): with patch("pyhap.accessory_driver.AccessoryDriver.async_start"), patch( f"{PATH_HOMEKIT}.HomeKit.async_stop" - ): + ), patch(f"{PATH_HOMEKIT}.port_is_available"): entry.add_to_hass(hass) assert await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() diff --git a/tests/components/nmap_tracker/test_config_flow.py b/tests/components/nmap_tracker/test_config_flow.py index 74997df5a4f..0c6e8f8f7e8 100644 --- a/tests/components/nmap_tracker/test_config_flow.py +++ b/tests/components/nmap_tracker/test_config_flow.py @@ -23,7 +23,7 @@ from tests.common import MockConfigEntry @pytest.mark.parametrize( "hosts", ["1.1.1.1", "192.168.1.0/24", "192.168.1.0/24,192.168.2.0/24"] ) -async def test_form(hass: HomeAssistant, hosts: str) -> None: +async def test_form(hass: HomeAssistant, hosts: str, mock_get_source_ip) -> None: """Test we get the form.""" await setup.async_setup_component(hass, "persistent_notification", {}) result = await hass.config_entries.flow.async_init( @@ -62,7 +62,7 @@ async def test_form(hass: HomeAssistant, hosts: str) -> None: assert len(mock_setup_entry.mock_calls) == 1 -async def test_form_range(hass: HomeAssistant) -> None: +async def test_form_range(hass: HomeAssistant, mock_get_source_ip) -> None: """Test we get the form and can take an ip range.""" await setup.async_setup_component(hass, "persistent_notification", {}) result = await hass.config_entries.flow.async_init( @@ -98,7 +98,7 @@ async def test_form_range(hass: HomeAssistant) -> None: assert len(mock_setup_entry.mock_calls) == 1 -async def test_form_invalid_hosts(hass: HomeAssistant) -> None: +async def test_form_invalid_hosts(hass: HomeAssistant, mock_get_source_ip) -> None: """Test invalid hosts passed in.""" await setup.async_setup_component(hass, "persistent_notification", {}) result = await hass.config_entries.flow.async_init( @@ -122,7 +122,7 @@ async def test_form_invalid_hosts(hass: HomeAssistant) -> None: assert result2["errors"] == {CONF_HOSTS: "invalid_hosts"} -async def test_form_already_configured(hass: HomeAssistant) -> None: +async def test_form_already_configured(hass: HomeAssistant, mock_get_source_ip) -> None: """Test duplicate host list.""" await setup.async_setup_component(hass, "persistent_notification", {}) config_entry = MockConfigEntry( @@ -157,7 +157,7 @@ async def test_form_already_configured(hass: HomeAssistant) -> None: assert result2["reason"] == "already_configured" -async def test_form_invalid_excludes(hass: HomeAssistant) -> None: +async def test_form_invalid_excludes(hass: HomeAssistant, mock_get_source_ip) -> None: """Test invalid excludes passed in.""" await setup.async_setup_component(hass, "persistent_notification", {}) result = await hass.config_entries.flow.async_init( @@ -181,7 +181,7 @@ async def test_form_invalid_excludes(hass: HomeAssistant) -> None: assert result2["errors"] == {CONF_EXCLUDE: "invalid_hosts"} -async def test_options_flow(hass: HomeAssistant) -> None: +async def test_options_flow(hass: HomeAssistant, mock_get_source_ip) -> None: """Test we can edit options.""" config_entry = MockConfigEntry( @@ -243,7 +243,7 @@ async def test_options_flow(hass: HomeAssistant) -> None: assert len(mock_setup_entry.mock_calls) == 1 -async def test_import(hass: HomeAssistant) -> None: +async def test_import(hass: HomeAssistant, mock_get_source_ip) -> None: """Test we can import from yaml.""" await setup.async_setup_component(hass, "persistent_notification", {}) with patch( @@ -278,7 +278,9 @@ async def test_import(hass: HomeAssistant) -> None: assert len(mock_setup_entry.mock_calls) == 1 -async def test_import_aborts_if_matching(hass: HomeAssistant) -> None: +async def test_import_aborts_if_matching( + hass: HomeAssistant, mock_get_source_ip +) -> None: """Test we can import from yaml.""" config_entry = MockConfigEntry( domain=DOMAIN, diff --git a/tests/components/ssdp/test_init.py b/tests/components/ssdp/test_init.py index 43b7fd98cd0..c50d71ed4c7 100644 --- a/tests/components/ssdp/test_init.py +++ b/tests/components/ssdp/test_init.py @@ -64,7 +64,7 @@ async def _async_run_mocked_scan(hass, mock_ssdp_response, mock_get_ssdp): return mock_init -async def test_scan_match_st(hass, caplog): +async def test_scan_match_st(hass, caplog, mock_get_source_ip): """Test matching based on ST.""" mock_ssdp_response = { "st": "mock-st", @@ -91,7 +91,7 @@ async def test_scan_match_st(hass, caplog): assert "Failed to fetch ssdp data" not in caplog.text -async def test_partial_response(hass, caplog): +async def test_partial_response(hass, caplog, mock_get_source_ip): """Test location and st missing.""" mock_ssdp_response = { "usn": "mock-usn", @@ -107,7 +107,9 @@ async def test_partial_response(hass, caplog): @pytest.mark.parametrize( "key", (ssdp.ATTR_UPNP_MANUFACTURER, ssdp.ATTR_UPNP_DEVICE_TYPE) ) -async def test_scan_match_upnp_devicedesc(hass, aioclient_mock, key): +async def test_scan_match_upnp_devicedesc( + hass, aioclient_mock, key, mock_get_source_ip +): """Test matching based on UPnP device description data.""" aioclient_mock.get( "http://1.1.1.1", @@ -134,7 +136,7 @@ async def test_scan_match_upnp_devicedesc(hass, aioclient_mock, key): } -async def test_scan_not_all_present(hass, aioclient_mock): +async def test_scan_not_all_present(hass, aioclient_mock, mock_get_source_ip): """Test match fails if some specified attributes are not present.""" aioclient_mock.get( "http://1.1.1.1", @@ -163,7 +165,7 @@ async def test_scan_not_all_present(hass, aioclient_mock): assert not mock_init.mock_calls -async def test_scan_not_all_match(hass, aioclient_mock): +async def test_scan_not_all_match(hass, aioclient_mock, mock_get_source_ip): """Test match fails if some specified attribute values differ.""" aioclient_mock.get( "http://1.1.1.1", @@ -194,7 +196,9 @@ async def test_scan_not_all_match(hass, aioclient_mock): @pytest.mark.parametrize("exc", [asyncio.TimeoutError, aiohttp.ClientError]) -async def test_scan_description_fetch_fail(hass, aioclient_mock, exc): +async def test_scan_description_fetch_fail( + hass, aioclient_mock, exc, mock_get_source_ip +): """Test failing to fetch description.""" aioclient_mock.get("http://1.1.1.1", exc=exc) mock_ssdp_response = { @@ -224,7 +228,7 @@ async def test_scan_description_fetch_fail(hass, aioclient_mock, exc): ] -async def test_scan_description_parse_fail(hass, aioclient_mock): +async def test_scan_description_parse_fail(hass, aioclient_mock, mock_get_source_ip): """Test invalid XML.""" aioclient_mock.get( "http://1.1.1.1", @@ -250,7 +254,7 @@ async def test_scan_description_parse_fail(hass, aioclient_mock): assert not mock_init.mock_calls -async def test_invalid_characters(hass, aioclient_mock): +async def test_invalid_characters(hass, aioclient_mock, mock_get_source_ip): """Test that we replace bad characters with placeholders.""" aioclient_mock.get( "http://1.1.1.1", @@ -295,7 +299,7 @@ async def test_invalid_characters(hass, aioclient_mock): @patch("homeassistant.components.ssdp.SSDPListener.async_search") @patch("homeassistant.components.ssdp.SSDPListener.async_stop") async def test_start_stop_scanner( - async_stop_mock, async_search_mock, async_start_mock, hass + async_stop_mock, async_search_mock, async_start_mock, hass, mock_get_source_ip ): """Test we start and stop the scanner.""" assert await async_setup_component(hass, ssdp.DOMAIN, {ssdp.DOMAIN: {}}) @@ -318,7 +322,9 @@ async def test_start_stop_scanner( assert async_stop_mock.call_count == 1 -async def test_unexpected_exception_while_fetching(hass, aioclient_mock, caplog): +async def test_unexpected_exception_while_fetching( + hass, aioclient_mock, caplog, mock_get_source_ip +): """Test unexpected exception while fetching.""" aioclient_mock.get( "http://1.1.1.1", @@ -355,7 +361,9 @@ async def test_unexpected_exception_while_fetching(hass, aioclient_mock, caplog) assert "Failed to fetch ssdp data from: http://1.1.1.1" in caplog.text -async def test_scan_with_registered_callback(hass, aioclient_mock, caplog): +async def test_scan_with_registered_callback( + hass, aioclient_mock, caplog, mock_get_source_ip +): """Test matching based on callback.""" aioclient_mock.get( "http://1.1.1.1", @@ -490,7 +498,9 @@ async def test_scan_with_registered_callback(hass, aioclient_mock, caplog): assert "Failed to callback info" in caplog.text -async def test_unsolicited_ssdp_registered_callback(hass, aioclient_mock, caplog): +async def test_unsolicited_ssdp_registered_callback( + hass, aioclient_mock, caplog, mock_get_source_ip +): """Test matching based on callback can handle unsolicited ssdp traffic without st.""" aioclient_mock.get( "http://10.6.9.12:1400/xml/device_description.xml", @@ -578,7 +588,7 @@ async def test_unsolicited_ssdp_registered_callback(hass, aioclient_mock, caplog assert "Failed to callback info" not in caplog.text -async def test_scan_second_hit(hass, aioclient_mock, caplog): +async def test_scan_second_hit(hass, aioclient_mock, caplog, mock_get_source_ip): """Test matching on second scan.""" aioclient_mock.get( "http://1.1.1.1", @@ -752,7 +762,7 @@ _ADAPTERS_WITH_MANUAL_CONFIG = [ ] -async def test_async_detect_interfaces_setting_empty_route(hass): +async def test_async_detect_interfaces_setting_empty_route(hass, mock_get_source_ip): """Test without default interface config and the route returns nothing.""" mock_get_ssdp = { "mock-domain": [ @@ -803,7 +813,7 @@ async def test_async_detect_interfaces_setting_empty_route(hass): } -async def test_bind_failure_skips_adapter(hass, caplog): +async def test_bind_failure_skips_adapter(hass, caplog, mock_get_source_ip): """Test that an adapter with a bind failure is skipped.""" mock_get_ssdp = { "mock-domain": [ @@ -872,7 +882,7 @@ async def test_bind_failure_skips_adapter(hass, caplog): } -async def test_ipv4_does_additional_search_for_sonos(hass, caplog): +async def test_ipv4_does_additional_search_for_sonos(hass, caplog, mock_get_source_ip): """Test that only ipv4 does an additional search for Sonos.""" mock_get_ssdp = { "mock-domain": [ @@ -928,7 +938,9 @@ async def test_ipv4_does_additional_search_for_sonos(hass, caplog): } -async def test_location_change_evicts_prior_location_from_cache(hass, aioclient_mock): +async def test_location_change_evicts_prior_location_from_cache( + hass, aioclient_mock, mock_get_source_ip +): """Test that a location change for a UDN will evict the prior location from the cache.""" mock_get_ssdp = { "hue": [{"manufacturer": "Signify", "modelName": "Philips hue bridge 2015"}] diff --git a/tests/components/upnp/test_config_flow.py b/tests/components/upnp/test_config_flow.py index 907fa709c84..a83b9ac41dd 100644 --- a/tests/components/upnp/test_config_flow.py +++ b/tests/components/upnp/test_config_flow.py @@ -34,7 +34,7 @@ from .mock_upnp_device import mock_upnp_device # noqa: F401 from tests.common import MockConfigEntry, async_fire_time_changed -@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_upnp_device") +@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_upnp_device", "mock_get_source_ip") async def test_flow_ssdp_discovery( hass: HomeAssistant, ): @@ -70,7 +70,7 @@ async def test_flow_ssdp_discovery( } -@pytest.mark.usefixtures("mock_ssdp_scanner") +@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_get_source_ip") async def test_flow_ssdp_incomplete_discovery(hass: HomeAssistant): """Test config flow: incomplete discovery through ssdp.""" # Discovered via step ssdp. @@ -88,7 +88,7 @@ async def test_flow_ssdp_incomplete_discovery(hass: HomeAssistant): assert result["reason"] == "incomplete_discovery" -@pytest.mark.usefixtures("mock_ssdp_scanner") +@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_get_source_ip") async def test_flow_ssdp_discovery_ignored(hass: HomeAssistant): """Test config flow: discovery through ssdp, but ignored, as hostname is used by existing config entry.""" # Existing entry. @@ -113,7 +113,7 @@ async def test_flow_ssdp_discovery_ignored(hass: HomeAssistant): assert result["reason"] == "discovery_ignored" -@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_upnp_device") +@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_upnp_device", "mock_get_source_ip") async def test_flow_user(hass: HomeAssistant): """Test config flow: discovered + configured through user.""" # Ensure we have a ssdp Scanner. @@ -145,7 +145,7 @@ async def test_flow_user(hass: HomeAssistant): } -@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_upnp_device") +@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_upnp_device", "mock_get_source_ip") async def test_flow_import(hass: HomeAssistant): """Test config flow: configured through configuration.yaml.""" # Ensure we have a ssdp Scanner. @@ -169,7 +169,7 @@ async def test_flow_import(hass: HomeAssistant): } -@pytest.mark.usefixtures("mock_ssdp_scanner") +@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_get_source_ip") async def test_flow_import_already_configured(hass: HomeAssistant): """Test config flow: configured through configuration.yaml, but existing config entry.""" # Existing entry. @@ -193,7 +193,7 @@ async def test_flow_import_already_configured(hass: HomeAssistant): assert result["reason"] == "already_configured" -@pytest.mark.usefixtures("mock_ssdp_scanner") +@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_get_source_ip") async def test_flow_import_no_devices_found(hass: HomeAssistant): """Test config flow: no devices found, configured through configuration.yaml.""" # Ensure we have a ssdp Scanner. @@ -213,7 +213,7 @@ async def test_flow_import_no_devices_found(hass: HomeAssistant): assert result["reason"] == "no_devices_found" -@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_upnp_device") +@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_upnp_device", "mock_get_source_ip") async def test_options_flow(hass: HomeAssistant): """Test options flow.""" # Ensure we have a ssdp Scanner. diff --git a/tests/components/upnp/test_init.py b/tests/components/upnp/test_init.py index 9ccdbf02f4b..6f0aa438310 100644 --- a/tests/components/upnp/test_init.py +++ b/tests/components/upnp/test_init.py @@ -19,7 +19,7 @@ from .mock_upnp_device import mock_upnp_device # noqa: F401 from tests.common import MockConfigEntry -@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_upnp_device") +@pytest.mark.usefixtures("mock_ssdp_scanner", "mock_upnp_device", "mock_get_source_ip") async def test_async_setup_entry_default(hass: HomeAssistant): """Test async_setup_entry.""" entry = MockConfigEntry( diff --git a/tests/components/yamaha_musiccast/test_config_flow.py b/tests/components/yamaha_musiccast/test_config_flow.py index 08900b1dfad..0e52d598bf6 100644 --- a/tests/components/yamaha_musiccast/test_config_flow.py +++ b/tests/components/yamaha_musiccast/test_config_flow.py @@ -104,7 +104,9 @@ def mock_empty_discovery_information(): # User Flows -async def test_user_input_device_not_found(hass, mock_get_device_info_mc_exception): +async def test_user_input_device_not_found( + hass, mock_get_device_info_mc_exception, mock_get_source_ip +): """Test when user specifies a non-existing device.""" result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} @@ -120,7 +122,9 @@ async def test_user_input_device_not_found(hass, mock_get_device_info_mc_excepti assert result2["errors"] == {"base": "cannot_connect"} -async def test_user_input_non_yamaha_device_found(hass, mock_get_device_info_invalid): +async def test_user_input_non_yamaha_device_found( + hass, mock_get_device_info_invalid, mock_get_source_ip +): """Test when user specifies an existing device, which does not provide the musiccast API.""" result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} @@ -136,7 +140,9 @@ async def test_user_input_non_yamaha_device_found(hass, mock_get_device_info_inv assert result2["errors"] == {"base": "no_musiccast_device"} -async def test_user_input_device_already_existing(hass, mock_get_device_info_valid): +async def test_user_input_device_already_existing( + hass, mock_get_device_info_valid, mock_get_source_ip +): """Test when user specifies an existing device.""" mock_entry = MockConfigEntry( domain=DOMAIN, @@ -158,7 +164,9 @@ async def test_user_input_device_already_existing(hass, mock_get_device_info_val assert result2["reason"] == "already_configured" -async def test_user_input_unknown_error(hass, mock_get_device_info_exception): +async def test_user_input_unknown_error( + hass, mock_get_device_info_exception, mock_get_source_ip +): """Test when user specifies an existing device, which does not provide the musiccast API.""" result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} @@ -175,7 +183,10 @@ async def test_user_input_unknown_error(hass, mock_get_device_info_exception): async def test_user_input_device_found( - hass, mock_get_device_info_valid, mock_valid_discovery_information + hass, + mock_get_device_info_valid, + mock_valid_discovery_information, + mock_get_source_ip, ): """Test when user specifies an existing device.""" result = await hass.config_entries.flow.async_init( @@ -198,7 +209,10 @@ async def test_user_input_device_found( async def test_user_input_device_found_no_ssdp( - hass, mock_get_device_info_valid, mock_empty_discovery_information + hass, + mock_get_device_info_valid, + mock_empty_discovery_information, + mock_get_source_ip, ): """Test when user specifies an existing device, which no discovery data are present for.""" result = await hass.config_entries.flow.async_init( @@ -220,7 +234,9 @@ async def test_user_input_device_found_no_ssdp( } -async def test_import_device_already_existing(hass, mock_get_device_info_valid): +async def test_import_device_already_existing( + hass, mock_get_device_info_valid, mock_get_source_ip +): """Test when the configurations.yaml contains an existing device.""" mock_entry = MockConfigEntry( domain=DOMAIN, @@ -239,7 +255,7 @@ async def test_import_device_already_existing(hass, mock_get_device_info_valid): assert result["reason"] == "already_configured" -async def test_import_error(hass, mock_get_device_info_exception): +async def test_import_error(hass, mock_get_device_info_exception, mock_get_source_ip): """Test when in the configuration.yaml a device is configured, which cannot be added..""" config = {"platform": "yamaha_musiccast", "host": "192.168.188.18", "port": 5006} @@ -252,7 +268,10 @@ async def test_import_error(hass, mock_get_device_info_exception): async def test_import_device_successful( - hass, mock_get_device_info_valid, mock_valid_discovery_information + hass, + mock_get_device_info_valid, + mock_valid_discovery_information, + mock_get_source_ip, ): """Test when the device was imported successfully.""" config = {"platform": "yamaha_musiccast", "host": "127.0.0.1", "port": 5006} @@ -273,7 +292,7 @@ async def test_import_device_successful( # SSDP Flows -async def test_ssdp_discovery_failed(hass, mock_ssdp_no_yamaha): +async def test_ssdp_discovery_failed(hass, mock_ssdp_no_yamaha, mock_get_source_ip): """Test when an SSDP discovered device is not a musiccast device.""" result = await hass.config_entries.flow.async_init( DOMAIN, @@ -289,7 +308,9 @@ async def test_ssdp_discovery_failed(hass, mock_ssdp_no_yamaha): assert result["reason"] == "yxc_control_url_missing" -async def test_ssdp_discovery_successful_add_device(hass, mock_ssdp_yamaha): +async def test_ssdp_discovery_successful_add_device( + hass, mock_ssdp_yamaha, mock_get_source_ip +): """Test when the SSDP discovered device is a musiccast device and the user confirms it.""" result = await hass.config_entries.flow.async_init( DOMAIN, @@ -319,7 +340,9 @@ async def test_ssdp_discovery_successful_add_device(hass, mock_ssdp_yamaha): } -async def test_ssdp_discovery_existing_device_update(hass, mock_ssdp_yamaha): +async def test_ssdp_discovery_existing_device_update( + hass, mock_ssdp_yamaha, mock_get_source_ip +): """Test when the SSDP discovered device is a musiccast device, but it already exists with another IP.""" mock_entry = MockConfigEntry( domain=DOMAIN, diff --git a/tests/components/yeelight/conftest.py b/tests/components/yeelight/conftest.py index f418e90e848..9a9b9d19ec2 100644 --- a/tests/components/yeelight/conftest.py +++ b/tests/components/yeelight/conftest.py @@ -1,2 +1,9 @@ """yeelight conftest.""" +import pytest + from tests.components.light.conftest import mock_light_profiles # noqa: F401 + + +@pytest.fixture(autouse=True) +def yeelight_mock_get_source_ip(mock_get_source_ip): + """Mock network util's async_get_source_ip.""" diff --git a/tests/conftest.py b/tests/conftest.py index c437b70d965..0b3db0bf832 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -488,6 +488,16 @@ async def mqtt_mock(hass, mqtt_client_mock, mqtt_config): return component +@pytest.fixture +def mock_get_source_ip(): + """Mock network util's async_get_source_ip.""" + with patch( + "homeassistant.components.network.util.async_get_source_ip", + return_value="10.10.10.10", + ): + yield + + @pytest.fixture def mock_zeroconf(): """Mock zeroconf."""