/
/
/
1"""
2Tests for restoring the duration probed during playback onto podcast episodes.
3
4Podcast feeds that omit ``itunes:duration`` yield episodes with a duration of 0. The value
5determined by ffmpeg while streaming is stored per item, so listings and later playbacks do
6not start blind again. These tests use the ``mass`` fixture from ``tests/conftest.py``, which
7provides a full MusicAssistant instance with a real cache database.
8"""
9
10from __future__ import annotations
11
12from music_assistant_models.enums import MediaType
13from music_assistant_models.media_items import ItemMapping, PodcastEpisode, ProviderMapping
14
15from music_assistant.helpers.audio import get_probed_duration, store_probed_duration
16from music_assistant.mass import MusicAssistant
17
18
19def _episode(item_id: str, duration: int = 0) -> PodcastEpisode:
20 return PodcastEpisode(
21 item_id=item_id,
22 provider="test_podcast_prov",
23 name="Episode One",
24 duration=duration,
25 position=1,
26 podcast=ItemMapping(
27 item_id="show-001",
28 provider="test_podcast_prov",
29 name="My Podcast Show",
30 media_type=MediaType.PODCAST,
31 ),
32 provider_mappings={
33 ProviderMapping(
34 item_id=item_id,
35 provider_domain="test_podcast_prov",
36 provider_instance="test_podcast_prov",
37 )
38 },
39 )
40
41
42def _uri(episode: PodcastEpisode) -> str:
43 assert episode.uri is not None # set in __post_init__
44 return episode.uri
45
46
47async def test_probed_duration_is_restored_on_a_durationless_episode(mass: MusicAssistant) -> None:
48 """An episode without a duration gets the one probed during an earlier playback."""
49 episode = _episode("ep-restore")
50 await store_probed_duration(mass, _uri(episode), 2700)
51
52 await mass.music.podcasts._restore_probed_duration(episode)
53
54 assert episode.duration == 2700
55
56
57async def test_probed_duration_does_not_replace_the_feeds_duration(mass: MusicAssistant) -> None:
58 """A duration published by the feed wins over the probed one."""
59 episode = _episode("ep-keep", duration=2712)
60 await store_probed_duration(mass, _uri(episode), 2700)
61
62 await mass.music.podcasts._restore_probed_duration(episode)
63
64 assert episode.duration == 2712
65
66
67async def test_probed_duration_of_an_unknown_episode_stays_zero(mass: MusicAssistant) -> None:
68 """An episode that was never played keeps its unknown duration."""
69 episode = _episode("ep-unknown")
70
71 await mass.music.podcasts._restore_probed_duration(episode)
72
73 assert episode.duration == 0
74
75
76async def test_zero_duration_is_never_stored(mass: MusicAssistant) -> None:
77 """A probe that produced nothing useful is not written to the store."""
78 episode = _episode("ep-zero")
79
80 await store_probed_duration(mass, _uri(episode), 0)
81
82 assert await get_probed_duration(mass, _uri(episode)) is None
83