"""Ordenes de sort por canal y por estado (query_videos). El dropdown de la UI expone Channel A→Z y Status; el backend debe agrupar por nombre de canal legible (no UUID) y por ciclo de vida (done → pending → no_subtitles → error), no alfabeticamente. """ from yt_scraper.store import Store, VideoRef def _store(tmp_path): s = Store(tmp_path / "test.db") # Beta alfabetiza antes que Alpha en channel_id pero despues en nombre. s.upsert_channel("UCzzz", None, "Beta") s.upsert_channel("UCaaa", None, "Alpha") return s def _ref(vid, ch, date=None, pos=None): return VideoRef(video_id=vid, channel_id=ch, title="t " + vid, url=f"https://youtu.be/{vid}", upload_date=date, position=pos) def test_sort_by_channel_name_groups_and_orders(tmp_path): s = _store(tmp_path) # position respeta el orden del listado de YouTube (0 = mas nuevo). s.upsert_videos([ _ref("b1", "UCzzz", "20260201", pos=1), _ref("a2", "UCaaa", "20260101", pos=1), _ref("a1", "UCaaa", "20260301", pos=0), _ref("b0", "UCzzz", "20260401", pos=0), ]) rows, _ = s.query_videos(sort="channel") ids = [r.video_id for r in rows] # Alpha primero por nombre; dentro del canal manda el rank del listado. assert ids == ["a1", "a2", "b0", "b1"] def test_sort_by_status_lifecycle(tmp_path): s = _store(tmp_path) s.upsert_videos([ _ref("p1", "UCaaa"), # pending _ref("d1", "UCaaa", "20260101"), _ref("e1", "UCzzz"), _ref("d2", "UCzzz", "20260201"), ]) s.mark_done("d1", "md/d1.md", "es", "manual", False) s.mark_done("d2", "md/d2.md", "es", "manual", False) s.mark_error("e1", "boom") rows, _ = s.query_videos(sort="status") statuses = [r.status for r in rows] assert statuses[0:2] == ["done", "done"] assert "pending" in statuses and "error" in statuses[-2:]