Files
community-plugins/lyrics/test_lyric_sources.py
T
rrztandGitHub a079c8a652 feat(lyrics): add SPlayer source (#55)
* feat(lyrics): add SPlayer source

* fix(lyrics): harden SPlayer fallback
2026-07-19 20:32:03 -04:00

99 lines
3.4 KiB
Python

#!/usr/bin/env python3
import unittest
from unittest import mock
import urllib.error
import lyric_sources
class SPlayerLinesTest(unittest.TestCase):
def test_preserves_timing_layers_and_markers(self):
lines = lyric_sources.splayer_transmitted_lines({
"duration": 5000,
"yrcData": [{
"startTime": 1000,
"endTime": 3000,
"translatedLyric": "Hello",
"isBG": True,
"isDuet": True,
"words": [
{"word": "A", "startTime": 1000, "endTime": 1500, "romanWord": "ay"},
{"word": "B", "startTime": 1500, "endTime": 2000, "romanWord": "bee"},
],
}],
})
self.assertEqual(lines[0]["text"], "AB")
self.assertEqual(lines[0]["translation"], "Hello")
self.assertEqual(lines[0]["romanization"], "ay bee")
self.assertEqual(lines[0]["chars"], [1000, 1500])
self.assertTrue(lines[0]["is_background"])
self.assertTrue(lines[0]["is_duet"])
self.assertEqual(lines[0]["words"][1]["end"], 2000)
def test_falls_back_to_lrc_when_yrc_is_invalid(self):
lines = lyric_sources.splayer_transmitted_lines({
"yrcData": [{"unexpected": "value"}],
"lrcData": [{"startTime": 2000, "endTime": 3000, "text": "fallback"}],
})
self.assertEqual(len(lines), 1)
self.assertEqual(lines[0]["text"], "fallback")
def test_marks_stretched_single_word_as_inferred(self):
lines = lyric_sources.splayer_transmitted_lines({
"yrcData": [
{
"startTime": 1000,
"endTime": 9000,
"words": [{"word": "line", "startTime": 1000, "endTime": 9000}],
},
{"startTime": 9000, "endTime": 10000, "text": "next"},
],
})
self.assertTrue(lines[0]["duration_inferred"])
self.assertEqual(lines[0]["chars"], [])
class SPlayerAdapterTest(unittest.TestCase):
@mock.patch("lyric_sources.time.sleep")
@mock.patch("lyric_sources.request_json")
def test_unavailable_api_uses_bounded_retries(self, request_json, sleep):
request_json.side_effect = urllib.error.URLError("offline")
result = lyric_sources.adapter_splayer(
{"title": "Song", "artist": "Artist"},
{"splayer_api_url": "http://127.0.0.1:25884"},
{},
)
self.assertEqual(result["type"], "none")
self.assertEqual(result["diag"], ["splayer: API unavailable"])
self.assertEqual(request_json.call_count, 3)
request_json.assert_called_with(
"http://127.0.0.1:25884/api/control/song-info", timeout=1
)
self.assertEqual(sleep.call_count, 2)
@mock.patch("lyric_sources.request_json")
def test_matches_title_suffix_and_artist_list(self, request_json):
request_json.return_value = {"data": {
"name": "Song (Live)",
"artists": [{"name": "Artist"}],
"lrcData": [{"startTime": 0, "endTime": 1000, "text": "line"}],
}}
result = lyric_sources.adapter_splayer(
{"title": "Song", "artist": "Artist"},
{"splayer_api_url": "http://127.0.0.1:25884"},
{},
)
self.assertEqual(result["type"], "lyrics")
if __name__ == "__main__":
unittest.main()