async def test_resolve_media_thumbnail(hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera, fixed_now: datetime): """Test resolving event thumbnails.""" ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) await init_entry(hass, ufp, [doorbell], regenerate_ids=False) event = Event( id="test_event_id", type=EventType.MOTION, start=fixed_now - timedelta(seconds=20), end=fixed_now, score=100, smart_detect_types=[], smart_detect_event_ids=[], camera_id=doorbell.id, ) event._api = ufp.api ufp.api.bootstrap.events = {"test_event_id": event} source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, "test_id:eventthumb:test_event_id", None) play_media = await source.async_resolve_media(media_item) assert play_media.mime_type == "image/jpeg" assert play_media.url.startswith( "/api/unifiprotect/thumbnail/test_id/test_event_id")
async def test_resolve_media_event(hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera, fixed_now: datetime): """Test resolving event clips.""" ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) await init_entry(hass, ufp, [doorbell], regenerate_ids=False) event = Event( id="test_event_id", type=EventType.MOTION, start=fixed_now - timedelta(seconds=20), end=fixed_now, score=100, smart_detect_types=[], smart_detect_event_ids=[], camera_id=doorbell.id, ) event._api = ufp.api ufp.api.get_event = AsyncMock(return_value=event) source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, "test_id:event:test_event_id", None) play_media = await source.async_resolve_media(media_item) start = event.start.replace(microsecond=0).isoformat() end = event.end.replace(microsecond=0).isoformat() assert play_media.mime_type == "video/mp4" assert play_media.url.startswith( f"/api/unifiprotect/video/test_id/{event.camera_id}/{start}/{end}")
async def test_browse_media_day(hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera, fixed_now: datetime): """Test browsing day selector level media.""" last_month = fixed_now.replace(day=1) - timedelta(days=1) ufp.api.bootstrap._recording_start = last_month ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) await init_entry(hass, ufp, [doorbell], regenerate_ids=False) base_id = ( f"test_id:browse:{doorbell.id}:all:range:{fixed_now.year}:{fixed_now.month}" ) source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, base_id, None) browse = await source.async_browse_media(media_item) assert ( browse.title == f"UnifiProtect > {doorbell.name} > All Events > {fixed_now.strftime('%B %Y')}" ) assert browse.identifier == base_id assert len(browse.children) in (29, 30, 31, 32) assert browse.children[0].title == "Whole Month" assert browse.children[0].identifier == f"{base_id}:all"
async def test_browse_media_camera(hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera, camera: Camera): """Test browsing camera selector level media.""" ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) await init_entry(hass, ufp, [doorbell, camera]) ufp.api.bootstrap.auth_user.all_permissions = [ Permission.unifi_dict_to_dict( {"rawPermission": "camera:create,read,write,delete,deletemedia:*"}), Permission.unifi_dict_to_dict( {"rawPermission": f"camera:readmedia:{doorbell.id}"}), ] entity_registry = er.async_get(hass) entity_registry.async_update_entity( "camera.test_camera_high", disabled_by=er.RegistryEntryDisabler("user")) await hass.async_block_till_done() source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, "test_id:browse", None) browse = await source.async_browse_media(media_item) assert browse.title == "UnifiProtect" assert browse.identifier == "test_id:browse" assert len(browse.children) == 2 assert browse.children[0].title == "All Cameras" assert browse.children[0].identifier == "test_id:browse:all" assert browse.children[1].title == doorbell.name assert browse.children[1].identifier == f"test_id:browse:{doorbell.id}" assert browse.children[1].thumbnail is None
async def test_browse_media_eventthumb(hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera, fixed_now: datetime): """Test browsing specific event.""" ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) await init_entry(hass, ufp, [doorbell], regenerate_ids=False) event = Event( id="test_event_id", type=EventType.SMART_DETECT, start=fixed_now - timedelta(seconds=20), end=fixed_now, score=100, smart_detect_types=[SmartDetectObjectType.PERSON], smart_detect_event_ids=[], camera_id=doorbell.id, ) event._api = ufp.api ufp.api.get_event = AsyncMock(return_value=event) source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, "test_id:eventthumb:test_event_id", None) browse = await source.async_browse_media(media_item) assert browse.identifier == "test_id:eventthumb:test_event_id" assert browse.children is None assert browse.media_class == MEDIA_CLASS_IMAGE
async def test_browse_media_recent(hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera, fixed_now: datetime): """Test browsing event selector level media for recent days.""" ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) await init_entry(hass, ufp, [doorbell], regenerate_ids=False) event = Event( id="test_event_id", type=EventType.MOTION, start=fixed_now - timedelta(seconds=20), end=fixed_now, score=100, smart_detect_types=[], smart_detect_event_ids=[], camera_id=doorbell.id, ) event._api = ufp.api ufp.api.get_events_raw = AsyncMock(return_value=[event.unifi_dict()]) base_id = f"test_id:browse:{doorbell.id}:motion:recent:1" source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, base_id, None) browse = await source.async_browse_media(media_item) assert ( browse.title == f"UnifiProtect > {doorbell.name} > Motion Events > Last 24 Hours (1)") assert browse.identifier == base_id assert len(browse.children) == 1 assert browse.children[0].identifier == "test_id:event:test_event_id"
async def test_browse_media_root_multiple_consoles_only_one_media( hass: HomeAssistant, ufp: MockUFPFixture, bootstrap: Bootstrap): """Test browsing root level media with multiple consoles.""" ufp.api.bootstrap._has_media = True await hass.config_entries.async_setup(ufp.entry.entry_id) await hass.async_block_till_done() bootstrap2 = bootstrap.copy() bootstrap2._has_media = False bootstrap2.nvr = bootstrap.nvr.copy() bootstrap2.nvr.id = "test_id2" bootstrap2.nvr.mac = "A2E00C826924" bootstrap2.nvr.name = "UnifiProtect2" api2 = Mock() bootstrap2.nvr._api = api2 bootstrap2._api = api2 api2.bootstrap = bootstrap2 api2._bootstrap = bootstrap2 api2.api_path = "/api" api2.base_url = "https://127.0.0.2" api2.connection_host = IPv4Address("127.0.0.2") api2.get_nvr = AsyncMock(return_value=bootstrap2.nvr) api2.update = AsyncMock(return_value=bootstrap2) api2.async_disconnect_ws = AsyncMock() with patch("homeassistant.components.unifiprotect.ProtectApiClient" ) as mock_api: mock_config = MockConfigEntry( domain=DOMAIN, data={ "host": "1.1.1.2", "username": "******", "password": "******", "id": "UnifiProtect2", "port": 443, "verify_ssl": False, }, version=2, ) mock_config.add_to_hass(hass) mock_api.return_value = api2 await hass.config_entries.async_setup(mock_config.entry_id) await hass.async_block_till_done() source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, None, None) browse = await source.async_browse_media(media_item) assert browse.title == "UnifiProtect" assert browse.identifier == "test_id:browse" assert len(browse.children) == 1 assert browse.children[0].title == "All Cameras" assert browse.children[0].identifier == "test_id:browse:all"
async def test_browse_media_event_ongoing(hass: HomeAssistant, ufp: MockUFPFixture, fixed_now: datetime, doorbell: Camera): """Test browsing event that is still ongoing.""" ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) await init_entry(hass, ufp, [doorbell], regenerate_ids=False) event = Event( id="test_event_id", type=EventType.MOTION, start=fixed_now - timedelta(seconds=20), end=None, score=100, smart_detect_types=[], smart_detect_event_ids=[], camera_id=doorbell.id, ) event._api = ufp.api ufp.api.get_event = AsyncMock(return_value=event) source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, f"test_id:event:{event.id}", None) with pytest.raises(BrowseError): await source.async_browse_media(media_item)
async def test_resolve_media_bad_identifier(hass: HomeAssistant, ufp: MockUFPFixture, identifier: str): """Test resolving bad identifiers.""" ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) ufp.api.get_event = AsyncMock(side_effect=NvrError) await init_entry(hass, ufp, [], regenerate_ids=False) source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, identifier, None) with pytest.raises(BrowseError): await source.async_resolve_media(media_item)
async def test_browse_media_browse_whole_month(hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera, fixed_now: datetime): """Test events for a specific day.""" fixed_now = fixed_now.replace(month=11) last_month = fixed_now.replace(day=1) - timedelta(days=1) ufp.api.bootstrap._recording_start = last_month ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) await init_entry(hass, ufp, [doorbell], regenerate_ids=False) event = Event( id="test_event_id", type=EventType.MOTION, start=fixed_now - timedelta(seconds=20), end=fixed_now, score=100, smart_detect_types=[], smart_detect_event_ids=[], camera_id=doorbell.id, ) event._api = ufp.api ufp.api.get_events_raw = AsyncMock(return_value=[event.unifi_dict()]) base_id = ( f"test_id:browse:{doorbell.id}:all:range:{fixed_now.year}:{fixed_now.month}:all" ) source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, base_id, None) browse = await source.async_browse_media(media_item) assert ( browse.title == f"UnifiProtect > {doorbell.name} > All Events > {fixed_now.strftime('%B %Y')} > Whole Month (1)" ) assert browse.identifier == base_id assert len(browse.children) == 1 assert browse.children[0].identifier == "test_id:event:test_event_id"
async def test_browse_media_root_single_console(hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera): """Test browsing root level media with a single console.""" ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) await init_entry(hass, ufp, [doorbell], regenerate_ids=False) source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, None, None) browse = await source.async_browse_media(media_item) assert browse.title == "UnifiProtect" assert browse.identifier == "test_id:browse" assert len(browse.children) == 2 assert browse.children[0].title == "All Cameras" assert browse.children[0].identifier == "test_id:browse:all" assert browse.children[1].title == doorbell.name assert browse.children[1].identifier == f"test_id:browse:{doorbell.id}" assert browse.children[1].thumbnail is not None
async def test_browse_media_event_type(hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera): """Test browsing event type selector level media.""" ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) await init_entry(hass, ufp, [doorbell], regenerate_ids=False) source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, "test_id:browse:all", None) browse = await source.async_browse_media(media_item) assert browse.title == "UnifiProtect > All Cameras" assert browse.identifier == "test_id:browse:all" assert len(browse.children) == 4 assert browse.children[0].title == "All Events" assert browse.children[0].identifier == "test_id:browse:all:all" assert browse.children[1].title == "Ring Events" assert browse.children[1].identifier == "test_id:browse:all:ring" assert browse.children[2].title == "Motion Events" assert browse.children[2].identifier == "test_id:browse:all:motion" assert browse.children[3].title == "Smart Detections" assert browse.children[3].identifier == "test_id:browse:all:smart"
async def test_browse_media_camera_offline(hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera): """Test browsing camera selector level media when camera is offline.""" doorbell.is_connected = False ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) await init_entry(hass, ufp, [doorbell]) source = await async_get_media_source(hass) media_item = MediaSourceItem(hass, DOMAIN, "test_id:browse", None) browse = await source.async_browse_media(media_item) assert browse.title == "UnifiProtect" assert browse.identifier == "test_id:browse" assert len(browse.children) == 2 assert browse.children[0].title == "All Cameras" assert browse.children[0].identifier == "test_id:browse:all" assert browse.children[1].title == doorbell.name assert browse.children[1].identifier == f"test_id:browse:{doorbell.id}" assert browse.children[1].thumbnail is None