feat: improve replay workflow and viewer UI
Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
28 files changed
+1496
-227
No files matched your search
@@ -49,7 +49,7 @@ class ReplayWorkflowTest(unittest.TestCase):
|
||||
_normalize_chapters(chapters)
|
||||
|
||||
def test_status_payload_exposes_pending_live_and_ended_updates(self):
|
||||
stream = SimpleNamespace(id=7, replay_file=None, chapters_json="[]")
|
||||
stream = SimpleNamespace(id=7, replay_file=None, replay_url=None, chapters_json="[]")
|
||||
for status in ("pending", "live", "ended"):
|
||||
stream.status = SimpleNamespace(value=status)
|
||||
self.assertEqual(_status_payload(stream)["status"], status)
|
||||
@@ -57,5 +57,19 @@ class ReplayWorkflowTest(unittest.TestCase):
|
||||
stream.replay_file = "session.mp4"
|
||||
stream.chapters_json = json.dumps([{"title": "Intro", "time": 0}])
|
||||
payload = _status_payload(stream)
|
||||
self.assertEqual(payload["replay_url"], "/api/streams/7/replay")
|
||||
self.assertEqual(payload["replay_local_url"], "/api/streams/7/replay")
|
||||
self.assertIsNone(payload["replay_url"])
|
||||
self.assertEqual(payload["chapters"], [{"title": "Intro", "time": 0}])
|
||||
|
||||
stream.replay_file = None
|
||||
stream.replay_url = "https://example.com/vod/master.m3u8"
|
||||
payload = _status_payload(stream)
|
||||
self.assertIsNone(payload["replay_local_url"])
|
||||
self.assertEqual(payload["replay_url"], "https://example.com/vod/master.m3u8")
|
||||
|
||||
def test_replay_url_rejects_non_http(self):
|
||||
from routes.streams import _valid_replay_url
|
||||
for unsafe in ("ftp://example.com/a.mp4", "file:///etc/passwd", "javascript:alert(1)"):
|
||||
with self.subTest(unsafe=unsafe), self.assertRaises(HTTPException):
|
||||
_valid_replay_url(unsafe)
|
||||
self.assertEqual(_valid_replay_url(" https://cdn.example.com/a.mp4 "), "https://cdn.example.com/a.mp4")
|
||||
Reference in new issue
Block a user