Mock out network.util.async_get_source_ip in tests (#55592)

This commit is contained in:
Erik Montnemery 2021-09-02 20:44:50 +02:00 committed by GitHub
parent 363320eedb
commit 7dbe8070f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 159 additions and 80 deletions

View file

@ -5,7 +5,7 @@ from homeassistant.components.emulated_roku import config_flow
from tests.common import MockConfigEntry 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.""" """Test that config flow works."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, config_flow.DOMAIN,
@ -18,7 +18,7 @@ async def test_flow_works(hass):
assert result["data"] == {"name": "Emulated Roku Test", "listen_port": 8060} 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.""" """Test that config flow doesn't allow existing names."""
MockConfigEntry( MockConfigEntry(
domain="emulated_roku", data={"name": "Emulated Roku Test", "listen_port": 8062} domain="emulated_roku", data={"name": "Emulated Roku Test", "listen_port": 8062}

View file

@ -5,7 +5,7 @@ from homeassistant.components import emulated_roku
from homeassistant.setup import async_setup_component 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.""" """Test that configuration is successful with required fields."""
with patch.object(emulated_roku, "configured_servers", return_value=[]), patch( with patch.object(emulated_roku, "configured_servers", return_value=[]), patch(
"homeassistant.components.emulated_roku.binding.EmulatedRokuServer", "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.""" """Test that an already registered name causes the entry to be ignored."""
with patch( with patch(
"homeassistant.components.emulated_roku.binding.EmulatedRokuServer", "homeassistant.components.emulated_roku.binding.EmulatedRokuServer",

View file

@ -67,7 +67,7 @@ def fc_class_mock():
yield result 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.""" """Test starting a flow by user."""
with patch( with patch(
"homeassistant.components.fritz.common.FritzConnection", "homeassistant.components.fritz.common.FritzConnection",
@ -108,7 +108,9 @@ async def test_user(hass: HomeAssistant, fc_class_mock):
assert mock_setup_entry.called 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.""" """Test starting a flow by user with an already configured device."""
mock_config = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) 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" 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.""" """Test starting a flow by user with invalid credentials."""
result = await hass.config_entries.flow.async_init( 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 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.""" """Test starting a flow by user with a connection error."""
result = await hass.config_entries.flow.async_init( 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 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.""" """Test starting a flow by user with an unknown exception."""
result = await hass.config_entries.flow.async_init( 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 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.""" """Test starting a reauthentication flow."""
mock_config = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) 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 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.""" """Test starting a reauthentication flow but no connection found."""
mock_config = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) 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" 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.""" """Test starting a flow from discovery with an already configured device."""
mock_config = MockConfigEntry( mock_config = MockConfigEntry(
@ -311,7 +319,9 @@ async def test_ssdp_already_configured(hass: HomeAssistant, fc_class_mock):
assert result["reason"] == "already_configured" 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.""" """Test starting a flow from discovery with an already configured host."""
mock_config = MockConfigEntry( mock_config = MockConfigEntry(
@ -333,7 +343,9 @@ async def test_ssdp_already_configured_host(hass: HomeAssistant, fc_class_mock):
assert result["reason"] == "already_configured" 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.""" """Test starting a flow from discovery with an already configured uuid."""
mock_config = MockConfigEntry( 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" 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.""" """Test starting a flow from discovery twice."""
with patch( with patch(
"homeassistant.components.fritz.common.FritzConnection", "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" 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.""" """Test starting a flow from discovery."""
with patch( with patch(
"homeassistant.components.fritz.common.FritzConnection", "homeassistant.components.fritz.common.FritzConnection",
@ -417,7 +431,7 @@ async def test_ssdp(hass: HomeAssistant, fc_class_mock):
assert mock_setup_entry.called 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.""" """Test starting a flow from discovery but no device found."""
with patch( with patch(
"homeassistant.components.fritz.common.FritzConnection", "homeassistant.components.fritz.common.FritzConnection",
@ -442,7 +456,7 @@ async def test_ssdp_exception(hass: HomeAssistant):
assert result["step_id"] == "confirm" 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.""" """Test importing."""
with patch( with patch(
"homeassistant.components.fritz.common.FritzConnection", "homeassistant.components.fritz.common.FritzConnection",
@ -473,7 +487,7 @@ async def test_import(hass: HomeAssistant, fc_class_mock):
assert mock_setup_entry.called 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.""" """Test options flow."""
mock_config = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) mock_config = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA)

View file

@ -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.""" """Test we can setup a new instance in bridge mode."""
await setup.async_setup_component(hass, "persistent_notification", {}) await setup.async_setup_component(hass, "persistent_notification", {})
result = await hass.config_entries.flow.async_init( 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 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.""" """Test we can setup a new instance in bridge mode when the name is taken."""
await setup.async_setup_component(hass, "persistent_notification", {}) 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 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.""" """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.one", "on")
hass.states.async_set("camera.existing", "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 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.""" """Test we can import instance."""
await setup.async_setup_component(hass, "persistent_notification", {}) await setup.async_setup_component(hass, "persistent_notification", {})
@ -275,7 +277,7 @@ async def test_import(hass):
@pytest.mark.parametrize("auto_start", [True, False]) @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.""" """Test config flow options in exclude mode with advanced options."""
config_entry = _mock_config_entry_with_options_populated() 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.""" """Test config flow options in exclude mode."""
config_entry = _mock_config_entry_with_options_populated() 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( 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.""" """Test devices can be bridged."""
config_entry = _mock_config_entry_with_options_populated() 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.""" """Test devices are preserved if they were added in advanced mode but it was turned off."""
config_entry = MockConfigEntry( config_entry = MockConfigEntry(
domain=DOMAIN, 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.""" """Test config flow options in include mode."""
config_entry = _mock_config_entry_with_options_populated() 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.""" """Test config flow options in exclude mode with cameras."""
config_entry = _mock_config_entry_with_options_populated() 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.""" """Test config flow options in include mode with cameras."""
config_entry = _mock_config_entry_with_options_populated() 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.""" """Test config flow options."""
config_entry = MockConfigEntry( 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 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.""" """Test config flow options in include mode with a single accessory."""
config_entry = _mock_config_entry_with_options_populated() 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.""" """Test we can convert a bridge to accessory mode."""
await setup.async_setup_component(hass, "persistent_notification", {}) await setup.async_setup_component(hass, "persistent_notification", {})
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(

View file

@ -102,6 +102,13 @@ def always_patch_driver(hk_driver):
"""Load the hk_driver fixture.""" """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): def _mock_homekit(hass, entry, homekit_mode, entity_filter=None, devices=None):
return HomeKit( return HomeKit(
hass=hass, 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( with patch("pyhap.accessory_driver.AccessoryDriver.async_start"), patch(
f"{PATH_HOMEKIT}.HomeKit.async_stop" f"{PATH_HOMEKIT}.HomeKit.async_stop"
): ), patch(f"{PATH_HOMEKIT}.port_is_available"):
entry.add_to_hass(hass) entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id) assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()

View file

@ -23,7 +23,7 @@ from tests.common import MockConfigEntry
@pytest.mark.parametrize( @pytest.mark.parametrize(
"hosts", ["1.1.1.1", "192.168.1.0/24", "192.168.1.0/24,192.168.2.0/24"] "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.""" """Test we get the form."""
await setup.async_setup_component(hass, "persistent_notification", {}) await setup.async_setup_component(hass, "persistent_notification", {})
result = await hass.config_entries.flow.async_init( 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 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.""" """Test we get the form and can take an ip range."""
await setup.async_setup_component(hass, "persistent_notification", {}) await setup.async_setup_component(hass, "persistent_notification", {})
result = await hass.config_entries.flow.async_init( 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 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.""" """Test invalid hosts passed in."""
await setup.async_setup_component(hass, "persistent_notification", {}) await setup.async_setup_component(hass, "persistent_notification", {})
result = await hass.config_entries.flow.async_init( 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"} 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.""" """Test duplicate host list."""
await setup.async_setup_component(hass, "persistent_notification", {}) await setup.async_setup_component(hass, "persistent_notification", {})
config_entry = MockConfigEntry( config_entry = MockConfigEntry(
@ -157,7 +157,7 @@ async def test_form_already_configured(hass: HomeAssistant) -> None:
assert result2["reason"] == "already_configured" 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.""" """Test invalid excludes passed in."""
await setup.async_setup_component(hass, "persistent_notification", {}) await setup.async_setup_component(hass, "persistent_notification", {})
result = await hass.config_entries.flow.async_init( 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"} 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.""" """Test we can edit options."""
config_entry = MockConfigEntry( config_entry = MockConfigEntry(
@ -243,7 +243,7 @@ async def test_options_flow(hass: HomeAssistant) -> None:
assert len(mock_setup_entry.mock_calls) == 1 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.""" """Test we can import from yaml."""
await setup.async_setup_component(hass, "persistent_notification", {}) await setup.async_setup_component(hass, "persistent_notification", {})
with patch( with patch(
@ -278,7 +278,9 @@ async def test_import(hass: HomeAssistant) -> None:
assert len(mock_setup_entry.mock_calls) == 1 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.""" """Test we can import from yaml."""
config_entry = MockConfigEntry( config_entry = MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,

View file

@ -64,7 +64,7 @@ async def _async_run_mocked_scan(hass, mock_ssdp_response, mock_get_ssdp):
return mock_init 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.""" """Test matching based on ST."""
mock_ssdp_response = { mock_ssdp_response = {
"st": "mock-st", "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 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.""" """Test location and st missing."""
mock_ssdp_response = { mock_ssdp_response = {
"usn": "mock-usn", "usn": "mock-usn",
@ -107,7 +107,9 @@ async def test_partial_response(hass, caplog):
@pytest.mark.parametrize( @pytest.mark.parametrize(
"key", (ssdp.ATTR_UPNP_MANUFACTURER, ssdp.ATTR_UPNP_DEVICE_TYPE) "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.""" """Test matching based on UPnP device description data."""
aioclient_mock.get( aioclient_mock.get(
"http://1.1.1.1", "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.""" """Test match fails if some specified attributes are not present."""
aioclient_mock.get( aioclient_mock.get(
"http://1.1.1.1", "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 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.""" """Test match fails if some specified attribute values differ."""
aioclient_mock.get( aioclient_mock.get(
"http://1.1.1.1", "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]) @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.""" """Test failing to fetch description."""
aioclient_mock.get("http://1.1.1.1", exc=exc) aioclient_mock.get("http://1.1.1.1", exc=exc)
mock_ssdp_response = { 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.""" """Test invalid XML."""
aioclient_mock.get( aioclient_mock.get(
"http://1.1.1.1", "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 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.""" """Test that we replace bad characters with placeholders."""
aioclient_mock.get( aioclient_mock.get(
"http://1.1.1.1", "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_search")
@patch("homeassistant.components.ssdp.SSDPListener.async_stop") @patch("homeassistant.components.ssdp.SSDPListener.async_stop")
async def test_start_stop_scanner( 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.""" """Test we start and stop the scanner."""
assert await async_setup_component(hass, ssdp.DOMAIN, {ssdp.DOMAIN: {}}) 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 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.""" """Test unexpected exception while fetching."""
aioclient_mock.get( aioclient_mock.get(
"http://1.1.1.1", "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 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.""" """Test matching based on callback."""
aioclient_mock.get( aioclient_mock.get(
"http://1.1.1.1", "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 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.""" """Test matching based on callback can handle unsolicited ssdp traffic without st."""
aioclient_mock.get( aioclient_mock.get(
"http://10.6.9.12:1400/xml/device_description.xml", "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 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.""" """Test matching on second scan."""
aioclient_mock.get( aioclient_mock.get(
"http://1.1.1.1", "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.""" """Test without default interface config and the route returns nothing."""
mock_get_ssdp = { mock_get_ssdp = {
"mock-domain": [ "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.""" """Test that an adapter with a bind failure is skipped."""
mock_get_ssdp = { mock_get_ssdp = {
"mock-domain": [ "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.""" """Test that only ipv4 does an additional search for Sonos."""
mock_get_ssdp = { mock_get_ssdp = {
"mock-domain": [ "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.""" """Test that a location change for a UDN will evict the prior location from the cache."""
mock_get_ssdp = { mock_get_ssdp = {
"hue": [{"manufacturer": "Signify", "modelName": "Philips hue bridge 2015"}] "hue": [{"manufacturer": "Signify", "modelName": "Philips hue bridge 2015"}]

View file

@ -34,7 +34,7 @@ from .mock_upnp_device import mock_upnp_device # noqa: F401
from tests.common import MockConfigEntry, async_fire_time_changed 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( async def test_flow_ssdp_discovery(
hass: HomeAssistant, 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): async def test_flow_ssdp_incomplete_discovery(hass: HomeAssistant):
"""Test config flow: incomplete discovery through ssdp.""" """Test config flow: incomplete discovery through ssdp."""
# Discovered via step ssdp. # Discovered via step ssdp.
@ -88,7 +88,7 @@ async def test_flow_ssdp_incomplete_discovery(hass: HomeAssistant):
assert result["reason"] == "incomplete_discovery" 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): 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.""" """Test config flow: discovery through ssdp, but ignored, as hostname is used by existing config entry."""
# Existing entry. # Existing entry.
@ -113,7 +113,7 @@ async def test_flow_ssdp_discovery_ignored(hass: HomeAssistant):
assert result["reason"] == "discovery_ignored" 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): async def test_flow_user(hass: HomeAssistant):
"""Test config flow: discovered + configured through user.""" """Test config flow: discovered + configured through user."""
# Ensure we have a ssdp Scanner. # 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): async def test_flow_import(hass: HomeAssistant):
"""Test config flow: configured through configuration.yaml.""" """Test config flow: configured through configuration.yaml."""
# Ensure we have a ssdp Scanner. # 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): async def test_flow_import_already_configured(hass: HomeAssistant):
"""Test config flow: configured through configuration.yaml, but existing config entry.""" """Test config flow: configured through configuration.yaml, but existing config entry."""
# Existing entry. # Existing entry.
@ -193,7 +193,7 @@ async def test_flow_import_already_configured(hass: HomeAssistant):
assert result["reason"] == "already_configured" 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): async def test_flow_import_no_devices_found(hass: HomeAssistant):
"""Test config flow: no devices found, configured through configuration.yaml.""" """Test config flow: no devices found, configured through configuration.yaml."""
# Ensure we have a ssdp Scanner. # 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" 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): async def test_options_flow(hass: HomeAssistant):
"""Test options flow.""" """Test options flow."""
# Ensure we have a ssdp Scanner. # Ensure we have a ssdp Scanner.

View file

@ -19,7 +19,7 @@ from .mock_upnp_device import mock_upnp_device # noqa: F401
from tests.common import MockConfigEntry 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): async def test_async_setup_entry_default(hass: HomeAssistant):
"""Test async_setup_entry.""" """Test async_setup_entry."""
entry = MockConfigEntry( entry = MockConfigEntry(

View file

@ -104,7 +104,9 @@ def mock_empty_discovery_information():
# User Flows # 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.""" """Test when user specifies a non-existing device."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} 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"} 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.""" """Test when user specifies an existing device, which does not provide the musiccast API."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} 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"} 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.""" """Test when user specifies an existing device."""
mock_entry = MockConfigEntry( mock_entry = MockConfigEntry(
domain=DOMAIN, 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" 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.""" """Test when user specifies an existing device, which does not provide the musiccast API."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} 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( 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.""" """Test when user specifies an existing device."""
result = await hass.config_entries.flow.async_init( 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( 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.""" """Test when user specifies an existing device, which no discovery data are present for."""
result = await hass.config_entries.flow.async_init( 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.""" """Test when the configurations.yaml contains an existing device."""
mock_entry = MockConfigEntry( mock_entry = MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,
@ -239,7 +255,7 @@ async def test_import_device_already_existing(hass, mock_get_device_info_valid):
assert result["reason"] == "already_configured" 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..""" """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} 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( 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.""" """Test when the device was imported successfully."""
config = {"platform": "yamaha_musiccast", "host": "127.0.0.1", "port": 5006} config = {"platform": "yamaha_musiccast", "host": "127.0.0.1", "port": 5006}
@ -273,7 +292,7 @@ async def test_import_device_successful(
# SSDP Flows # 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.""" """Test when an SSDP discovered device is not a musiccast device."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, DOMAIN,
@ -289,7 +308,9 @@ async def test_ssdp_discovery_failed(hass, mock_ssdp_no_yamaha):
assert result["reason"] == "yxc_control_url_missing" 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.""" """Test when the SSDP discovered device is a musiccast device and the user confirms it."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, 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.""" """Test when the SSDP discovered device is a musiccast device, but it already exists with another IP."""
mock_entry = MockConfigEntry( mock_entry = MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,

View file

@ -1,2 +1,9 @@
"""yeelight conftest.""" """yeelight conftest."""
import pytest
from tests.components.light.conftest import mock_light_profiles # noqa: F401 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."""

View file

@ -488,6 +488,16 @@ async def mqtt_mock(hass, mqtt_client_mock, mqtt_config):
return component 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 @pytest.fixture
def mock_zeroconf(): def mock_zeroconf():
"""Mock zeroconf.""" """Mock zeroconf."""