"""Test fixtures. Every path the application uses is redirected into a tmpdir. No test touches the network, the real media tree, or a real yt-dlp. """ from __future__ import annotations import os import tempfile from pathlib import Path # config resolves its paths at import time, so the environment has to be set # before anything from the package is imported. _SANDBOX = Path(tempfile.mkdtemp(prefix="yta-tests-")) os.environ.setdefault("YTA_STATE_DIR", str(_SANDBOX / "state")) os.environ.setdefault("YTA_MEDIA_ROOT", str(_SANDBOX / "media")) os.environ.setdefault("YTA_DB_PATH", str(_SANDBOX / "state" / "subs.db")) os.environ.setdefault("YTA_LOCK_PATH", str(_SANDBOX / "state" / "run.lock")) os.environ.setdefault("YTA_VENV_BIN", str(_SANDBOX / "venv" / "bin")) import pytest # noqa: E402 from youtube_automate import config, db, util, videos # noqa: E402 from youtube_automate.settings import Settings # noqa: E402 FIXTURES = Path(__file__).parent / "fixtures" @pytest.fixture() def media_root(tmp_path, monkeypatch): """Point the media root and work dir at a per-test tmpdir.""" root = tmp_path / "media" work = root / ".work" work.mkdir(parents=True) (work / ".ignore").touch() monkeypatch.setattr(config, "MEDIA_ROOT", root) monkeypatch.setattr(config, "WORK_DIR", work) return root @pytest.fixture() def conn(tmp_path): connection = db.connect(tmp_path / "subs.db") yield connection connection.close() @pytest.fixture() def settings(conn): return Settings(conn) @pytest.fixture() def channel(conn): """One subscribed channel, returned as a row.""" with conn: conn.execute( "INSERT INTO channel (channel_id, handle, title, description, dir_name, added_at) " "VALUES (?, ?, ?, ?, ?, ?)", ( "UCW7jUEpYT_t0Gsf632d6_wQ", "@clabretro", "clabretro", "Retro computing", "clabretro", util.utcnow_iso(), ), ) return conn.execute("SELECT * FROM channel WHERE dir_name = 'clabretro'").fetchone() def add_video(conn, channel_pk, video_id, **kwargs): """Insert a video row with sensible defaults.""" defaults = { "title": f"Video {video_id}", "upload_date": "2026-08-01", "state": videos.PENDING, "discovery_source": videos.SOURCE_UULF, } defaults.update(kwargs) videos.insert(conn, channel_pk=channel_pk, video_id=video_id, **defaults) return videos.get(conn, video_id) def feed_bytes(name: str) -> bytes: return (FIXTURES / name).read_bytes()