Files
mopidy-webhooks/tests/test_metadata.py

187 lines
5.6 KiB
Python
Raw Permalink Normal View History

import json
import shutil
from pathlib import Path
import pytest
from mutagen import File as MutagenFile
from mutagen.id3 import COMM, WXXX
from mopidy_webhooks import metadata
DATA_DIR = Path(__file__).parent / "data"
@pytest.fixture
def tagged_episode(tmp_path):
episode = tmp_path / "2026-09-22 Episode One.mp3"
shutil.copy(DATA_DIR / "silence.mp3", episode)
audio = MutagenFile(episode, easy=True)
audio["title"] = ["Episode One"]
audio["artist"] = ["Jane Host"]
audio["album"] = ["The Test Podcast"]
audio["tracknumber"] = ["42"]
audio["date"] = ["2026-09-22"]
audio["genre"] = ["Technology"]
audio.save()
raw = MutagenFile(episode)
raw.tags.add(
COMM(encoding=3, lang="eng", desc="", text="A tag description")
)
raw.tags.add(WXXX(encoding=3, desc="", url="https://example.com/episode"))
raw.save()
return episode
def test_resolve_media_path_for_file_uri(tagged_episode):
path = metadata.resolve_media_path(tagged_episode.as_uri(), [])
assert path == str(tagged_episode)
def test_resolve_media_path_for_local_uri(tagged_episode, tmp_path):
uri = f"local:podcast:{tagged_episode.name}"
path = metadata.resolve_media_path(uri, [str(tmp_path)])
assert path == str(tagged_episode)
def test_resolve_media_path_for_local_track_uri(tagged_episode, tmp_path):
uri = f"local:track:{tagged_episode.name}"
path = metadata.resolve_media_path(uri, [str(tmp_path)])
assert path == str(tagged_episode)
def test_resolve_media_path_percent_decodes_uri(tagged_episode, tmp_path):
uri = "local:podcast:2026-09-22%20Episode%20One.mp3"
path = metadata.resolve_media_path(uri, [str(tmp_path)])
assert path == str(tagged_episode)
def test_resolve_media_path_returns_none_for_remote_uri():
assert metadata.resolve_media_path("spotify:track:123", []) is None
assert (
metadata.resolve_media_path("podcast+https://example.com/feed#1", [])
is None
)
assert metadata.resolve_media_path("", []) is None
def test_read_tags_returns_normalized_metadata(tagged_episode):
tags = metadata.read_tags(str(tagged_episode))
assert tags["title"] == "Episode One"
assert tags["artist"] == "Jane Host"
assert tags["album"] == "The Test Podcast"
assert tags["track_number"] == "42"
assert tags["date"] == "2026-09-22"
assert tags["genre"] == "Technology"
assert tags["comment"] == "A tag description"
assert tags["website"] == "https://example.com/episode"
def test_read_tags_handles_missing_file():
assert metadata.read_tags("/does/not/exist.mp3") == {}
assert metadata.read_tags(None) == {}
def test_read_sidecar_json_prefers_same_directory(tagged_episode):
sidecar = tagged_episode.with_suffix(".json")
sidecar.write_text(json.dumps({"feed_url": "https://example.com/feed"}))
data = metadata.read_sidecar_json(str(tagged_episode))
assert data["feed_url"] == "https://example.com/feed"
def test_read_metadata_merges_sidecar_and_tags(tagged_episode, tmp_path):
metadata_dir = tmp_path / "metadata"
metadata_dir.mkdir()
sidecar = metadata_dir / f"{tagged_episode.stem}.json"
sidecar.write_text(
json.dumps(
{
"title": "Sidecar Title",
"date": "2026-09-21T10:00:00",
"feed_url": "https://example.com/feed",
"guid": "episode-guid",
"episode_url": "https://example.com/episode.mp3",
"description": "A sidecar description",
"duration": 1234,
}
)
)
data = metadata.read_metadata(str(tagged_episode))
assert data["title"] == "Episode One"
assert data["artist"] == "Jane Host"
assert data["album"] == "The Test Podcast"
assert data["feed_url"] == "https://example.com/feed"
assert data["guid"] == "episode-guid"
assert data["episode_url"] == "https://example.com/episode.mp3"
assert data["description"] == "A sidecar description"
assert data["duration"] == 1234
assert data["date"] == "2026-09-21T10:00:00"
@pytest.mark.parametrize(
"value,expected",
[
("2026-09-22", "2026-09-22"),
("2026-09-22T10:00:00", "2026-09-22"),
("2026-09", "2026-09-01"),
("2026", ""),
("", ""),
("not a date", ""),
],
)
def test_normalize_date(value, expected):
assert metadata.normalize_date(value) == expected
def test_normalize_date_handles_date_objects():
import datetime
assert metadata.normalize_date(datetime.date(2026, 9, 22)) == "2026-09-22"
def test_split_podcast_uri():
feed, guid = metadata.split_podcast_uri(
"podcast+https://feed.example/rss#abc"
)
assert feed == "https://feed.example/rss"
assert guid == "abc"
assert metadata.split_podcast_uri("local:track:foo.mp3") == (None, None)
def test_parse_dirs():
assert metadata.parse_dirs("/a, /b ,, ") == ["/a", "/b"]
assert metadata.parse_dirs("") == []
assert metadata.parse_dirs(None) == []
assert metadata.parse_dirs(["/a", "/b"]) == ["/a", "/b"]
def test_is_podcast_detection(tagged_episode, tmp_path):
assert metadata.is_podcast("local:podcast:foo.mp3")
assert metadata.is_podcast("podcast+https://feed.example/rss#abc")
assert metadata.is_podcast("file:///media/podcasts/foo.mp3")
assert metadata.is_podcast(
"file:///tmp/foo.mp3",
path=str(tagged_episode),
podcast_dirs=[str(tmp_path)],
)
assert metadata.is_podcast(
"file:///tmp/foo.mp3", path="/tmp/foo.mp3", metadata={"feed_url": "x"}
)
assert not metadata.is_podcast(
"local:track:Artist/Album/01%20Song.mp3",
path="/tmp/song.mp3",
)