Don't mock all of pychromecast in tests (#59839)

This commit is contained in:
Erik Montnemery 2021-11-18 11:28:35 +01:00 committed by GitHub
parent bb731fad5d
commit bfafeb7965
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 127 additions and 77 deletions

View File

@ -17,13 +17,7 @@ def dial_mock():
@pytest.fixture()
def castbrowser_mock():
"""Mock pychromecast CastBrowser."""
return MagicMock()
@pytest.fixture()
def castbrowser_constructor_mock():
"""Mock pychromecast CastBrowser constructor."""
return MagicMock()
return MagicMock(spec=pychromecast.discovery.CastBrowser)
@pytest.fixture()
@ -32,37 +26,29 @@ def mz_mock():
return MagicMock()
@pytest.fixture()
def pycast_mock(castbrowser_mock, castbrowser_constructor_mock):
"""Mock pychromecast."""
pycast_mock = MagicMock()
pycast_mock.IDLE_APP_ID = pychromecast.IDLE_APP_ID
pycast_mock.IGNORE_CEC = []
pycast_mock.const = pychromecast.const
pycast_mock.discovery.CastBrowser = castbrowser_constructor_mock
pycast_mock.discovery.CastBrowser.return_value = castbrowser_mock
pycast_mock.discovery.AbstractCastListener = (
pychromecast.discovery.AbstractCastListener
)
return pycast_mock
@pytest.fixture()
def quick_play_mock():
"""Mock pychromecast quick_play."""
return MagicMock()
@pytest.fixture()
def get_chromecast_mock():
"""Mock pychromecast get_chromecast_from_cast_info."""
return MagicMock()
@pytest.fixture(autouse=True)
def cast_mock(dial_mock, mz_mock, pycast_mock, quick_play_mock):
def cast_mock(
dial_mock, mz_mock, quick_play_mock, castbrowser_mock, get_chromecast_mock
):
"""Mock pychromecast."""
ignore_cec_orig = list(pychromecast.IGNORE_CEC)
with patch(
"homeassistant.components.cast.media_player.pychromecast", pycast_mock
), patch(
"homeassistant.components.cast.discovery.pychromecast", pycast_mock
), patch(
"homeassistant.components.cast.helpers.dial", dial_mock
), patch(
"homeassistant.components.cast.discovery.pychromecast.discovery.CastBrowser",
castbrowser_mock,
), patch("homeassistant.components.cast.helpers.dial", dial_mock), patch(
"homeassistant.components.cast.media_player.MultizoneManager",
return_value=mz_mock,
), patch(
@ -71,5 +57,10 @@ def cast_mock(dial_mock, mz_mock, pycast_mock, quick_play_mock):
), patch(
"homeassistant.components.cast.media_player.quick_play",
quick_play_mock,
), patch(
"homeassistant.components.cast.media_player.pychromecast.get_chromecast_from_cast_info",
get_chromecast_mock,
):
yield
pychromecast.IGNORE_CEC = list(ignore_cec_orig)

View File

@ -245,7 +245,7 @@ async def test_option_flow(hass, parameter_data):
assert dict(config_entry.data) == expected_data
async def test_known_hosts(hass, castbrowser_mock, castbrowser_constructor_mock):
async def test_known_hosts(hass, castbrowser_mock):
"""Test known hosts is passed to pychromecasts."""
result = await hass.config_entries.flow.async_init(
"cast", context={"source": config_entries.SOURCE_USER}
@ -257,12 +257,9 @@ async def test_known_hosts(hass, castbrowser_mock, castbrowser_constructor_mock)
await hass.async_block_till_done()
config_entry = hass.config_entries.async_entries("cast")[0]
assert castbrowser_mock.start_discovery.call_count == 1
castbrowser_constructor_mock.assert_called_once_with(
ANY, ANY, ["192.168.0.1", "192.168.0.2"]
)
assert castbrowser_mock.return_value.start_discovery.call_count == 1
castbrowser_mock.assert_called_once_with(ANY, ANY, ["192.168.0.1", "192.168.0.2"])
castbrowser_mock.reset_mock()
castbrowser_constructor_mock.reset_mock()
result = await hass.config_entries.options.async_init(config_entry.entry_id)
result = await hass.config_entries.options.async_configure(
@ -272,8 +269,8 @@ async def test_known_hosts(hass, castbrowser_mock, castbrowser_constructor_mock)
await hass.async_block_till_done()
castbrowser_mock.start_discovery.assert_not_called()
castbrowser_constructor_mock.assert_not_called()
castbrowser_mock.host_browser.update_hosts.assert_called_once_with(
castbrowser_mock.return_value.start_discovery.assert_not_called()
castbrowser_mock.assert_not_called()
castbrowser_mock.return_value.host_browser.update_hosts.assert_called_once_with(
["192.168.0.11", "192.168.0.12"]
)

View File

@ -46,6 +46,13 @@ FakeUUID = UUID("57355bce-9364-4aa6-ac1e-eb849dccf9e2")
FakeUUID2 = UUID("57355bce-9364-4aa6-ac1e-eb849dccf9e4")
FakeGroupUUID = UUID("57355bce-9364-4aa6-ac1e-eb849dccf9e3")
FAKE_HOST_SERVICE = pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_HOST, ("127.0.0.1", 8009)
)
FAKE_MDNS_SERVICE = pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_MDNS, "the-service"
)
def get_fake_chromecast(info: ChromecastInfo):
"""Generate a Fake Chromecast object with the specified arguments."""
@ -56,7 +63,7 @@ def get_fake_chromecast(info: ChromecastInfo):
def get_fake_chromecast_info(
host="192.168.178.42", port=8009, uuid: UUID | None = FakeUUID
host="192.168.178.42", port=8009, service=None, uuid: UUID | None = FakeUUID
):
"""Generate a Fake ChromecastInfo with the specified arguments."""
@ -81,10 +88,14 @@ def get_fake_chromecast_info(
)
return super().__eq__(other)
if service is None:
service = pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_HOST, (host, port)
)
return ExtendedChromecastInfo(
host=host,
port=port,
services={"the-service"},
services={service},
uuid=uuid,
model_name="Chromecast",
friendly_name="Speaker",
@ -136,10 +147,12 @@ async def async_setup_cast_internal_discovery(hass, config=None):
discovery_callback = cast_browser.call_args[0][0].add_cast
remove_callback = cast_browser.call_args[0][0].remove_cast
def discover_chromecast(service_name: str, info: ChromecastInfo) -> None:
def discover_chromecast(
service: pychromecast.discovery.ServiceInfo, info: ChromecastInfo
) -> None:
"""Discover a chromecast device."""
browser.devices[info.uuid] = pychromecast.discovery.CastInfo(
{service_name},
{service},
info.uuid,
info.model_name,
info.friendly_name,
@ -148,7 +161,7 @@ async def async_setup_cast_internal_discovery(hass, config=None):
info.cast_type,
info.manufacturer,
)
discovery_callback(info.uuid, service_name)
discovery_callback(info.uuid, "")
def remove_chromecast(service_name: str, info: ChromecastInfo) -> None:
"""Remove a chromecast device."""
@ -194,9 +207,8 @@ async def async_setup_media_player_cast(hass: HomeAssistant, info: ChromecastInf
discovery_callback = cast_browser.call_args[0][0].add_cast
service_name = "the-service"
browser.devices[info.uuid] = pychromecast.discovery.CastInfo(
{service_name},
{FAKE_MDNS_SERVICE},
info.uuid,
info.model_name,
info.friendly_name,
@ -205,7 +217,7 @@ async def async_setup_media_player_cast(hass: HomeAssistant, info: ChromecastInf
info.cast_type,
info.manufacturer,
)
discovery_callback(info.uuid, service_name)
discovery_callback(info.uuid, FAKE_MDNS_SERVICE[1])
await hass.async_block_till_done()
await hass.async_block_till_done()
@ -214,7 +226,7 @@ async def async_setup_media_player_cast(hass: HomeAssistant, info: ChromecastInf
def discover_chromecast(service_name: str, info: ChromecastInfo) -> None:
"""Discover a chromecast device."""
browser.devices[info.uuid] = pychromecast.discovery.CastInfo(
{service_name},
{FAKE_MDNS_SERVICE},
info.uuid,
info.model_name,
info.friendly_name,
@ -223,7 +235,7 @@ async def async_setup_media_player_cast(hass: HomeAssistant, info: ChromecastInf
info.cast_type,
info.manufacturer,
)
discovery_callback(info.uuid, service_name)
discovery_callback(info.uuid, FAKE_MDNS_SERVICE[1])
return chromecast, discover_chromecast
@ -250,16 +262,16 @@ def get_status_callbacks(chromecast_mock, mz_mock=None):
async def test_start_discovery_called_once(hass, castbrowser_mock):
"""Test pychromecast.start_discovery called exactly once."""
await async_setup_cast(hass)
assert castbrowser_mock.start_discovery.call_count == 1
assert castbrowser_mock.return_value.start_discovery.call_count == 1
await async_setup_cast(hass)
assert castbrowser_mock.start_discovery.call_count == 1
assert castbrowser_mock.return_value.start_discovery.call_count == 1
async def test_internal_discovery_callback_fill_out_fail(hass):
"""Test internal discovery automatically filling out information."""
discover_cast, _, _ = await async_setup_cast_internal_discovery(hass)
info = get_fake_chromecast_info(host="host1")
info = get_fake_chromecast_info(host="host1", service=FAKE_MDNS_SERVICE)
zconf = get_fake_zconf(host="host1", port=8009)
full_info = (
info # attr.evolve(info, model_name="", friendly_name="Speaker", uuid=FakeUUID)
@ -275,7 +287,7 @@ async def test_internal_discovery_callback_fill_out_fail(hass):
signal = MagicMock()
async_dispatcher_connect(hass, "cast_discovered", signal)
discover_cast("the-service", info)
discover_cast(FAKE_MDNS_SERVICE, info)
await hass.async_block_till_done()
# when called with incomplete info, it should use HTTP to get missing
@ -286,7 +298,7 @@ async def test_internal_discovery_callback_fill_out_fail(hass):
async def test_internal_discovery_callback_fill_out_group(hass):
"""Test internal discovery automatically filling out information."""
discover_cast, _, _ = await async_setup_cast_internal_discovery(hass)
info = get_fake_chromecast_info(host="host1", port=12345)
info = get_fake_chromecast_info(host="host1", port=12345, service=FAKE_MDNS_SERVICE)
zconf = get_fake_zconf(host="host1", port=12345)
full_info = attr.evolve(
info,
@ -306,7 +318,7 @@ async def test_internal_discovery_callback_fill_out_group(hass):
signal = MagicMock()
async_dispatcher_connect(hass, "cast_discovered", signal)
discover_cast("the-service", info)
discover_cast(FAKE_MDNS_SERVICE, info)
await hass.async_block_till_done()
# when called with incomplete info, it should use HTTP to get missing
@ -318,12 +330,12 @@ async def test_stop_discovery_called_on_stop(hass, castbrowser_mock):
"""Test pychromecast.stop_discovery called on shutdown."""
# start_discovery should be called with empty config
await async_setup_cast(hass, {})
assert castbrowser_mock.start_discovery.call_count == 1
assert castbrowser_mock.return_value.start_discovery.call_count == 1
# stop discovery should be called on shutdown
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
await hass.async_block_till_done()
assert castbrowser_mock.stop_discovery.call_count == 1
assert castbrowser_mock.return_value.stop_discovery.call_count == 1
async def test_create_cast_device_without_uuid(hass):
@ -362,7 +374,12 @@ async def test_manual_cast_chromecasts_uuid(hass):
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_2,
):
discover_cast("service2", cast_2)
discover_cast(
pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_MDNS, "service2"
),
cast_2,
)
await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 0
@ -371,7 +388,12 @@ async def test_manual_cast_chromecasts_uuid(hass):
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_1,
):
discover_cast("service1", cast_1)
discover_cast(
pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_MDNS, "service1"
),
cast_1,
)
await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 1
@ -390,7 +412,12 @@ async def test_auto_cast_chromecasts(hass):
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_1,
):
discover_cast("service2", cast_2)
discover_cast(
pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_MDNS, "service2"
),
cast_2,
)
await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 1
@ -399,13 +426,18 @@ async def test_auto_cast_chromecasts(hass):
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_2,
):
discover_cast("service1", cast_1)
discover_cast(
pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_MDNS, "service1"
),
cast_1,
)
await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 2
async def test_discover_dynamic_group(hass, dial_mock, pycast_mock, caplog):
async def test_discover_dynamic_group(hass, dial_mock, get_chromecast_mock, caplog):
"""Test dynamic group does not create device or entity."""
cast_1 = get_fake_chromecast_info(host="host_1", port=23456, uuid=FakeUUID)
cast_2 = get_fake_chromecast_info(host="host_2", port=34567, uuid=FakeUUID2)
@ -421,7 +453,7 @@ async def test_discover_dynamic_group(hass, dial_mock, pycast_mock, caplog):
tmp2.uuid = FakeUUID2
dial_mock.get_multizone_status.return_value.dynamic_groups = [tmp1, tmp2]
pycast_mock.get_chromecast_from_cast_info.assert_not_called()
get_chromecast_mock.assert_not_called()
discover_cast, remove_cast, add_dev1 = await async_setup_cast_internal_discovery(
hass
)
@ -431,11 +463,16 @@ async def test_discover_dynamic_group(hass, dial_mock, pycast_mock, caplog):
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_1,
):
discover_cast("service", cast_1)
discover_cast(
pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_MDNS, "service"
),
cast_1,
)
await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs
pycast_mock.get_chromecast_from_cast_info.assert_called()
pycast_mock.get_chromecast_from_cast_info.reset_mock()
get_chromecast_mock.assert_called()
get_chromecast_mock.reset_mock()
assert add_dev1.call_count == 0
assert reg.async_get_entity_id("media_player", "cast", cast_1.uuid) is None
@ -444,11 +481,16 @@ async def test_discover_dynamic_group(hass, dial_mock, pycast_mock, caplog):
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_2,
):
discover_cast("service", cast_2)
discover_cast(
pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_MDNS, "service"
),
cast_2,
)
await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs
pycast_mock.get_chromecast_from_cast_info.assert_called()
pycast_mock.get_chromecast_from_cast_info.reset_mock()
get_chromecast_mock.assert_called()
get_chromecast_mock.reset_mock()
assert add_dev1.call_count == 0
assert reg.async_get_entity_id("media_player", "cast", cast_1.uuid) is None
@ -457,10 +499,15 @@ async def test_discover_dynamic_group(hass, dial_mock, pycast_mock, caplog):
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_1,
):
discover_cast("service", cast_1)
discover_cast(
pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_MDNS, "service"
),
cast_1,
)
await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs
pycast_mock.get_chromecast_from_cast_info.assert_not_called()
get_chromecast_mock.assert_not_called()
assert add_dev1.call_count == 0
assert reg.async_get_entity_id("media_player", "cast", cast_1.uuid) is None
@ -471,7 +518,12 @@ async def test_discover_dynamic_group(hass, dial_mock, pycast_mock, caplog):
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_1,
):
remove_cast("service", cast_1)
remove_cast(
pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_MDNS, "service"
),
cast_1,
)
await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs
@ -492,7 +544,12 @@ async def test_update_cast_chromecasts(hass):
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_1,
):
discover_cast("service1", cast_1)
discover_cast(
pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_MDNS, "service1"
),
cast_1,
)
await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 1
@ -501,7 +558,12 @@ async def test_update_cast_chromecasts(hass):
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_2,
):
discover_cast("service2", cast_2)
discover_cast(
pychromecast.discovery.ServiceInfo(
pychromecast.const.SERVICE_TYPE_MDNS, "service2"
),
cast_2,
)
await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 1
@ -1406,7 +1468,7 @@ async def test_entry_setup_empty_config(hass: HomeAssistant):
assert config_entry.data["ignore_cec"] == []
async def test_entry_setup_single_config(hass: HomeAssistant, pycast_mock):
async def test_entry_setup_single_config(hass: HomeAssistant):
"""Test deprecated yaml config with a single config media_player."""
await async_setup_component(
hass, "cast", {"cast": {"media_player": {"uuid": "bla", "ignore_cec": "cast1"}}}
@ -1417,10 +1479,10 @@ async def test_entry_setup_single_config(hass: HomeAssistant, pycast_mock):
assert config_entry.data["uuid"] == ["bla"]
assert config_entry.data["ignore_cec"] == ["cast1"]
assert pycast_mock.IGNORE_CEC == ["cast1"]
assert pychromecast.IGNORE_CEC == ["cast1"]
async def test_entry_setup_list_config(hass: HomeAssistant, pycast_mock):
async def test_entry_setup_list_config(hass: HomeAssistant):
"""Test deprecated yaml config with multiple media_players."""
await async_setup_component(
hass,
@ -1439,4 +1501,4 @@ async def test_entry_setup_list_config(hass: HomeAssistant, pycast_mock):
config_entry = hass.config_entries.async_entries("cast")[0]
assert set(config_entry.data["uuid"]) == {"bla", "blu"}
assert set(config_entry.data["ignore_cec"]) == {"cast1", "cast2", "cast3"}
assert set(pycast_mock.IGNORE_CEC) == {"cast1", "cast2", "cast3"}
assert set(pychromecast.IGNORE_CEC) == {"cast1", "cast2", "cast3"}