Files
manage/backend/tests/test_utils.py

246 lines
7.1 KiB
Python

"""Unit tests for utils.py formatting helpers."""
from media_library_viewer_api.utils import (
ffprobe_format_summary,
format_bitrate,
format_duration,
human_size,
is_known_video_file,
summarize_audio_streams,
summarize_streams,
summarize_subtitle_streams,
summarize_video_streams,
ticks_to_minutes,
timestamp_to_local,
)
class TestTicksToMinutes:
def test_none(self):
assert ticks_to_minutes(None) is None
def test_zero(self):
assert ticks_to_minutes(0) is None
def test_one_hour(self):
# 1 hour = 3600 * 10_000_000 ticks
assert ticks_to_minutes(3600 * 10_000_000) == 60
def test_90_minutes(self):
assert ticks_to_minutes(90 * 60 * 10_000_000) == 90
def test_rounding(self):
# 45.7 minutes
ticks = int(45.7 * 60 * 10_000_000)
assert ticks_to_minutes(ticks) == 46
class TestHumanSize:
def test_none(self):
assert human_size(None) == ""
def test_zero(self):
assert human_size(0) == "0 B"
def test_bytes(self):
assert human_size(500) == "500 B"
def test_kilobytes(self):
result = human_size(2048)
assert "KB" in result
assert "2.0" in result
def test_megabytes(self):
result = human_size(5 * 1024 * 1024)
assert "MB" in result
def test_gigabytes(self):
result = human_size(3 * 1024**3)
assert "GB" in result
def test_terabytes(self):
result = human_size(2 * 1024**4)
assert "TB" in result
class TestIsKnownVideoFile:
def test_none(self):
assert is_known_video_file(None) is False
def test_empty(self):
assert is_known_video_file("") is False
def test_mkv(self):
assert is_known_video_file("/media/movie.mkv") is True
def test_mp4(self):
assert is_known_video_file("file.MP4") is True
def test_txt(self):
assert is_known_video_file("/path/to/notes.txt") is False
def test_srt(self):
assert is_known_video_file("subtitle.srt") is False
def test_spaces_in_path(self):
assert is_known_video_file("/media/My Movie (2024)/file.mkv") is True
class TestFormatDuration:
def test_none(self):
assert format_duration(None) == ""
def test_empty(self):
assert format_duration("") == ""
def test_seconds(self):
assert format_duration(90) == "00:01:30"
def test_hours(self):
assert format_duration(7200) == "02:00:00"
def test_string_input(self):
assert format_duration("3661.5") == "01:01:01"
class TestFormatBitrate:
def test_none(self):
assert format_bitrate(None) == ""
def test_empty(self):
assert format_bitrate("") == ""
def test_low(self):
assert format_bitrate(500) == "500 bps"
def test_kbps(self):
result = format_bitrate(128000)
assert "128 kbps" in result
def test_mbps(self):
result = format_bitrate(5_000_000)
assert "Mbps" in result
def test_string_input(self):
result = format_bitrate("2500000")
assert "Mbps" in result
class TestFfprobeSummary:
def test_empty(self):
result = ffprobe_format_summary({})
assert result["filename"] == ""
assert result["format"] == ""
def test_with_format(self):
data = {
"format": {
"filename": "/path/to/file.mkv",
"format_name": "matroska,webm",
"format_long_name": "Matroska / WebM",
"duration": "7200.5",
"size": "5368709120",
"bit_rate": "5000000",
"nb_streams": 3,
}
}
result = ffprobe_format_summary(data)
assert result["filename"] == "/path/to/file.mkv"
assert result["format"] == "matroska,webm"
assert "02:00:00" in result["duration"]
assert "GB" in result["size"]
assert "Mbps" in result["bit_rate"]
assert result["stream_count"] == "3"
class TestSummarizeStreams:
SAMPLE_FFPROBE = {
"streams": [
{
"index": 0,
"codec_type": "video",
"codec_name": "hevc",
"profile": "Main 10",
"width": 3840,
"height": 2160,
"pix_fmt": "yuv420p10le",
"bit_rate": "15000000",
"avg_frame_rate": "24/1",
"color_range": "tv",
"color_space": "bt2020nc",
"color_transfer": "smpte2084",
"color_primaries": "bt2020",
"tags": {"language": "eng", "title": "Main"},
"disposition": {"default": 1},
"side_data_list": [{"side_data_type": "Mastering display metadata"}],
},
{
"index": 1,
"codec_type": "audio",
"codec_name": "truehd",
"profile": "TrueHD+Atmos",
"channels": 8,
"channel_layout": "7.1",
"sample_rate": "48000",
"bit_rate": "4500000",
"tags": {"language": "eng", "title": "Atmos"},
"disposition": {"default": 1, "forced": 0},
},
{
"index": 2,
"codec_type": "subtitle",
"codec_name": "subrip",
"codec_long_name": "SubRip subtitle",
"tags": {"language": "eng", "title": "English"},
"disposition": {"default": 0, "forced": 1, "hearing_impaired": 0},
},
]
}
def test_video_streams(self):
rows = summarize_video_streams(self.SAMPLE_FFPROBE)
assert len(rows) == 1
v = rows[0]
assert v["codec"] == "hevc"
assert v["resolution"] == "3840x2160"
assert v["color_transfer"] == "smpte2084"
assert v["language"] == "eng"
assert v["default"] == "yes"
assert "Mastering" in v["side_data"]
def test_audio_streams(self):
rows = summarize_audio_streams(self.SAMPLE_FFPROBE)
assert len(rows) == 1
a = rows[0]
assert a["codec"] == "truehd"
assert a["channels"] == 8
assert a["layout"] == "7.1"
assert a["default"] == "yes"
assert a["forced"] == ""
def test_subtitle_streams(self):
rows = summarize_subtitle_streams(self.SAMPLE_FFPROBE)
assert len(rows) == 1
s = rows[0]
assert s["codec"] == "subrip"
assert s["language"] == "eng"
assert s["forced"] == "yes"
assert s["default"] == ""
def test_summarize_all(self):
rows = summarize_streams(self.SAMPLE_FFPROBE)
assert len(rows) == 3
types = [r["type"] for r in rows]
assert types == ["video", "audio", "subtitle"]
class TestTimestampToLocal:
def test_none(self):
assert timestamp_to_local(None) == ""
def test_valid(self):
# Just verify it returns a non-empty formatted string
result = timestamp_to_local(1700000000.0)
assert result != ""
assert "-" in result # date format contains dashes