soulsync/tests/test_video_youtube_enrichment.py
BoulderBadgeDad b6d8f07516 Dashboard: YouTube date enricher as a 4th worker orb + Follow→Watchlist consistency
- The standalone enricher now reports orb telemetry: stats()/pause()/resume();
  /enrichment/youtube/status (+pause/resume) special-cased in the route. Added
  the 4th header worker button (red ▶), WORKER_DEFS entry, and SERVICES wiring —
  it's not on the socket so video-enrichment.js polls it every 3s. It animates
  (idle → active orb + inbound pulses) while a followed channel's dates are being
  fetched, like the TMDB/TVDB/OMDb orbs.
- Channel detail now uses the SAME standard watchlist button as shows/movies
  (library-artist-watchlist-btn, ✓/+ icon, 'In Watchlist'/'Watchlist') instead
  of a bespoke 'Follow' — consistency. Still wired to the channel follow action.

176 backend tests green; JS balanced; music untouched.
2026-06-17 11:05:59 -07:00

60 lines
2.7 KiB
Python

"""Seam tests for the background YouTube date enricher."""
from pathlib import Path
import pytest
from core.video.youtube_enrichment import YoutubeDateEnricher
from database.video_database import VideoDatabase
@pytest.fixture()
def db(tmp_path):
return VideoDatabase(database_path=str(tmp_path / "video_library.db"))
def test_enrich_caches_proxy_dates_and_marks_done(db, monkeypatch):
import core.video.youtube as yt
monkeypatch.setattr(yt, "proxy_channel_dates",
lambda cid, *a, **k: {"v1": "2024-06-01", "v2": "2023-02-02"})
# if proxy covers everything, the per-video fallback must NOT run
monkeypatch.setattr(yt, "video_detail", lambda vid: (_ for _ in ()).throw(AssertionError("no fallback")))
db.add_videos_to_wishlist({"youtube_id": "UCx", "title": "X"}, [{"youtube_id": "v1", "title": "A"}])
e = YoutubeDateEnricher(db_factory=lambda: db)
e._enrich("UCx")
assert db.get_video_dates(["v1", "v2"]) == {"v1": "2024-06-01", "v2": "2023-02-02"}
assert db.channel_dates_enriched_recently("UCx") is True
# already enriched → second pass is a no-op (no proxy call)
monkeypatch.setattr(yt, "proxy_channel_dates", lambda *a, **k: (_ for _ in ()).throw(AssertionError("re-swept")))
e._enrich("UCx")
def test_enrich_falls_back_to_per_video_when_proxy_empty(db, monkeypatch):
import core.video.youtube as yt
monkeypatch.setattr(yt, "proxy_channel_dates", lambda cid, *a, **k: {}) # all proxies down
monkeypatch.setattr(yt, "video_detail",
lambda vid: {"youtube_id": vid, "published_at": "2022-03-03"} if vid == "w1" else None)
import core.video.youtube_enrichment as mod
monkeypatch.setattr(mod.time, "sleep", lambda s: None) # no real throttle delay in tests
db.add_videos_to_wishlist({"youtube_id": "UCx", "title": "X"},
[{"youtube_id": "w1", "title": "A"}, {"youtube_id": "w2", "title": "B"}])
e = YoutubeDateEnricher(db_factory=lambda: db)
e._enrich("UCx")
assert db.get_video_dates(["w1", "w2"]) == {"w1": "2022-03-03"} # only w1 had a date
assert db.channel_dates_enriched_recently("UCx") is True
def test_enricher_imports_nothing_from_music():
src = Path("core/video/youtube_enrichment.py").read_text(encoding="utf-8")
assert "database.music_database" not in src and "from database import" not in src
def test_enricher_stats_shape_and_pause():
e = YoutubeDateEnricher(db_factory=lambda: None)
s = e.stats()
assert s["enabled"] is True and s["running"] is False and s["paused"] is False
assert s["current_item"] is None and "progress" in s
e.pause(); assert e.stats()["paused"] is True
e.resume(); assert e.stats()["paused"] is False