返回 last30days-skill
test_youtube_transcript_fallback_spend.py
根目录 / tests / test_youtube_transcript_fallback_spend.py
1 from pathlib import Path
2 from unittest import mock
3
4 import pytest
5 from lib import env, youtube_yt
6
7
8 def test_youtube_tuning_loaded_from_env_file_reaches_lazy_readers(
9 tmp_path: Path,
10 monkeypatch: pytest.MonkeyPatch,
11 ) -> None:
12 config_file = tmp_path / ".env"
13 config_file.write_text(
14 "LAST30DAYS_YT_SUB_LANGS=en\nLAST30DAYS_YT_TRANSCRIPT_FAST_TIMEOUT=25\n",
15 encoding="utf-8",
16 )
17 config_file.chmod(0o600)
18 monkeypatch.setattr(env, "CONFIG_DIR", tmp_path)
19 monkeypatch.setattr(env, "CONFIG_FILE", config_file)
20 monkeypatch.setenv("LAST30DAYS_CONFIG_DIR", str(tmp_path))
21 monkeypatch.delenv("LAST30DAYS_YT_SUB_LANGS", raising=False)
22 monkeypatch.delenv("LAST30DAYS_YT_TRANSCRIPT_FAST_TIMEOUT", raising=False)
23 monkeypatch.chdir(tmp_path)
24
25 with (
26 mock.patch.object(env, "_load_keychain", return_value={}),
27 mock.patch.object(env, "_load_pass", return_value={}),
28 ):
29 config = env.get_config()
30
31 assert config["LAST30DAYS_YT_SUB_LANGS"] == "en"
32 assert config["LAST30DAYS_YT_TRANSCRIPT_FAST_TIMEOUT"] == "25"
33 assert youtube_yt._ytdlp_sub_langs() == "en"
34 assert youtube_yt._transcript_fast_timeout() == 25.0
35
36
37 @pytest.mark.parametrize(
38 "value",
39 ["", "not-a-number", "0", "-1", "nan", "inf"],
40 )
41 def test_invalid_or_empty_fast_timeout_uses_default(
42 value: str,
43 monkeypatch: pytest.MonkeyPatch,
44 ) -> None:
45 monkeypatch.setenv("LAST30DAYS_YT_TRANSCRIPT_FAST_TIMEOUT", value)
46
47 assert youtube_yt._transcript_fast_timeout() == 12.0
48
49
50 def test_timeout_reuses_completed_vtt_without_paid_fallback(
51 tmp_path: Path,
52 ) -> None:
53 (tmp_path / "video123.en.vtt").write_text(
54 "WEBVTT\n\n00:00:00.000 --> 00:00:02.000\nusable transcript\n",
55 encoding="utf-8",
56 )
57 status: dict[str, str] = {}
58
59 with mock.patch.object(
60 youtube_yt.subproc,
61 "run_with_timeout",
62 side_effect=youtube_yt.subproc.SubprocTimeout,
63 ) as run_mock:
64 transcript = youtube_yt._fetch_transcript_ytdlp(
65 "video123",
66 str(tmp_path),
67 status=status,
68 fast_fail=True,
69 )
70
71 assert transcript is not None
72 assert "usable transcript" in transcript
73 assert "ytdlp_error" not in status
74 assert run_mock.call_count == 1
75
76
77 def test_fast_timeout_override_controls_keyed_attempt(
78 tmp_path: Path,
79 monkeypatch: pytest.MonkeyPatch,
80 ) -> None:
81 monkeypatch.setenv("LAST30DAYS_YT_TRANSCRIPT_FAST_TIMEOUT", "25")
82 status: dict[str, str] = {}
83
84 with mock.patch.object(
85 youtube_yt.subproc,
86 "run_with_timeout",
87 side_effect=youtube_yt.subproc.SubprocTimeout,
88 ) as run_mock:
89 transcript = youtube_yt._fetch_transcript_ytdlp(
90 "video123",
91 str(tmp_path),
92 status=status,
93 fast_fail=True,
94 )
95
96 assert transcript is None
97 assert run_mock.call_args.kwargs["timeout"] == 25.0
98 assert status["ytdlp_error"] == "timed out after 25.0s"
99
99 lines PYTHON