diff --git a/homeassistant/components/cast/media_player.py b/homeassistant/components/cast/media_player.py index edac0e6e3ec..e687dc715df 100644 --- a/homeassistant/components/cast/media_player.py +++ b/homeassistant/components/cast/media_player.py @@ -55,7 +55,7 @@ from .const import ( SIGNAL_CAST_REMOVED, SIGNAL_HASS_CAST_SHOW_VIEW, ) -from .discovery import discover_chromecast, setup_internal_discovery +from .discovery import setup_internal_discovery from .helpers import ( CastStatusListener, ChromecastInfo, @@ -178,20 +178,7 @@ async def _async_setup_platform( for chromecast in list(hass.data[KNOWN_CHROMECAST_INFO_KEY]): async_cast_discovered(chromecast) - if info is None or info.is_audio_group: - # If we were a) explicitly told to enable discovery or - # b) have an audio group cast device, we need internal discovery. - hass.async_add_executor_job(setup_internal_discovery, hass) - else: - info = await hass.async_add_executor_job(info.fill_out_missing_chromecast_info) - if info.friendly_name is None: - _LOGGER.debug( - "Cannot retrieve detail information for chromecast" - " %s, the device may not be online", - info, - ) - - hass.async_add_executor_job(discover_chromecast, hass, info) + hass.async_add_executor_job(setup_internal_discovery, hass) class CastDevice(MediaPlayerDevice): diff --git a/tests/components/cast/test_media_player.py b/tests/components/cast/test_media_player.py index 3a40e9065d3..9809710f372 100644 --- a/tests/components/cast/test_media_player.py +++ b/tests/components/cast/test_media_player.py @@ -22,6 +22,7 @@ from tests.common import MockConfigEntry, mock_coro def cast_mock(): """Mock pychromecast.""" pycast_mock = MagicMock() + pycast_mock.start_discovery.return_value = (None, Mock()) dial_mock = MagicMock(name="XXX") dial_mock.get_device_status.return_value.uuid = "fake_uuid" dial_mock.get_device_status.return_value.manufacturer = "fake_manufacturer" @@ -42,6 +43,7 @@ def cast_mock(): # pylint: disable=invalid-name FakeUUID = UUID("57355bce-9364-4aa6-ac1e-eb849dccf9e2") +FakeUUID2 = UUID("57355bce-9364-4aa6-ac1e-eb849dccf9e4") FakeGroupUUID = UUID("57355bce-9364-4aa6-ac1e-eb849dccf9e3") @@ -108,19 +110,42 @@ async def async_setup_cast_internal_discovery(hass, config=None, discovery_info= async def async_setup_media_player_cast(hass: HomeAssistantType, info: ChromecastInfo): """Set up the cast platform with async_setup_component.""" + listener = MagicMock(services={}) + browser = MagicMock(zc={}) chromecast = get_fake_chromecast(info) cast.CastStatusListener = MagicMock() with patch( - "homeassistant.components.cast.discovery.pychromecast._get_chromecast_from_host", + "homeassistant.components.cast.discovery.pychromecast._get_chromecast_from_service", return_value=chromecast, - ) as get_chromecast: + ) as get_chromecast, patch( + "homeassistant.components.cast.discovery.pychromecast.start_discovery", + return_value=(listener, browser), + ) as start_discovery: await async_setup_component( hass, "media_player", {"media_player": {"platform": "cast", "host": info.host}}, ) + + await hass.async_block_till_done() + + discovery_callback = start_discovery.call_args[0][0] + + def discover_chromecast(service_name: str, info: ChromecastInfo) -> None: + """Discover a chromecast device.""" + listener.services[service_name] = ( + info.host, + info.port, + info.uuid, + info.model_name, + info.friendly_name, + ) + discovery_callback(service_name) + + discover_chromecast("the-service", info) + await hass.async_block_till_done() await hass.async_block_till_done() assert get_chromecast.call_count == 1 assert cast.CastStatusListener.call_count == 1 @@ -220,42 +245,6 @@ async def test_create_cast_device_with_uuid(hass): assert cast_device is None -async def test_normal_chromecast_not_starting_discovery(hass): - """Test cast platform not starting discovery when not required.""" - # pylint: disable=no-member - with patch( - "homeassistant.components.cast.media_player.setup_internal_discovery" - ) as setup_discovery: - # normal (non-group) chromecast shouldn't start discovery. - add_entities = await async_setup_cast(hass, {"host": "host1"}) - await hass.async_block_till_done() - assert add_entities.call_count == 1 - assert setup_discovery.call_count == 0 - - # Same entity twice - add_entities = await async_setup_cast(hass, {"host": "host1"}) - await hass.async_block_till_done() - assert add_entities.call_count == 0 - assert setup_discovery.call_count == 0 - - hass.data[cast.ADDED_CAST_DEVICES_KEY] = set() - add_entities = await async_setup_cast( - hass, discovery_info={"host": "host1", "port": 8009} - ) - await hass.async_block_till_done() - assert add_entities.call_count == 1 - assert setup_discovery.call_count == 0 - - # group should start discovery. - hass.data[cast.ADDED_CAST_DEVICES_KEY] = set() - add_entities = await async_setup_cast( - hass, discovery_info={"host": "host1", "port": 42} - ) - await hass.async_block_till_done() - assert add_entities.call_count == 0 - assert setup_discovery.call_count == 1 - - async def test_replay_past_chromecasts(hass): """Test cast platform re-playing past chromecasts when adding new one.""" cast_group1 = get_fake_chromecast_info(host="host1", port=42) @@ -282,6 +271,62 @@ async def test_replay_past_chromecasts(hass): assert add_dev2.call_count == 1 +async def test_manual_cast_chromecasts(hass): + """Test only wanted casts are added for manual configuration.""" + cast_1 = get_fake_chromecast_info(host="configured_host") + cast_2 = get_fake_chromecast_info(host="other_host", uuid=FakeUUID2) + + # Manual configuration of media player with host "configured_host" + discover_cast, add_dev1 = await async_setup_cast_internal_discovery( + hass, config={"host": "configured_host"} + ) + discover_cast("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 + + discover_cast("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 + + +async def test_auto_cast_chromecasts(hass): + """Test all discovered casts are added for default configuration.""" + cast_1 = get_fake_chromecast_info(host="some_host") + cast_2 = get_fake_chromecast_info(host="other_host", uuid=FakeUUID2) + + # Manual configuration of media player with host "configured_host" + discover_cast, add_dev1 = await async_setup_cast_internal_discovery(hass) + discover_cast("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 + + discover_cast("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_update_cast_chromecasts(hass): + """Test discovery of same UUID twice only adds one cast.""" + cast_1 = get_fake_chromecast_info(host="old_host") + cast_2 = get_fake_chromecast_info(host="new_host") + + # Manual configuration of media player with host "configured_host" + discover_cast, add_dev1 = await async_setup_cast_internal_discovery(hass) + discover_cast("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 + + discover_cast("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 + + async def test_entity_media_states(hass: HomeAssistantType): """Test various entity media states.""" info = get_fake_chromecast_info()