# -*- coding: utf-8 -*- """CLI 入口测试(离线): uv run python tests/test_cli.py""" import contextlib import io import json import os import sys import tempfile from pathlib import Path sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.stdout.reconfigure(encoding="utf-8") from reaction_board.bilibili.models import LoginState # noqa: E402 from reaction_board.cli import main # noqa: E402 from reaction_board.database import Database # noqa: E402 from reaction_board.repository import Repository # noqa: E402 import reaction_board.cli as cli # noqa: E402 def write_config(tmp, *, cookie="SESSDATA=x; buvid3=y", csrf="csrf"): path = Path(tmp) / "config.json" path.write_text(json.dumps({ "mid": 1, "csrf": csrf, "cookie": cookie, "storage": { "database_path": str(Path(tmp) / "app.db"), "backup_dir": str(Path(tmp) / "backup"), }, "folders": [ {"year": 2025, "media_id": 11, "title": "2025"}, {"year": 2026, "media_id": 22, "title": "2026"}, ], "up_blacklist_seed": [101, 202], }, ensure_ascii=False), encoding="utf-8") return path def run_cli(argv): out = io.StringIO() with contextlib.redirect_stdout(out): code = main(argv) return code, out.getvalue() def test_init_and_status(): with tempfile.TemporaryDirectory() as tmp: path = write_config(tmp) code, output = run_cli(["init", "--config", str(path)]) assert code == 0 assert '"schema_version": 1' in output db = Database(Path(tmp) / "app.db") db.initialize() try: repo = Repository(db) assert len(repo.list_folders()) == 2 assert [r["mid"] for r in repo.blacklist()] == [101, 202] assert repo.counts()["video_total"] == 0 finally: db.close() code, output = run_cli(["status", "--config", str(path)]) assert code == 0 assert '"configured_folders"' in output assert '"media_count": null' in output assert '"video_total": 0' in output def test_missing_config(): with tempfile.TemporaryDirectory() as tmp: code, output = run_cli(["init", "--config", str(Path(tmp) / "nope.json")]) assert code == 2 payload = json.loads(output.strip().splitlines()[-1]) assert payload["level"] == "error" assert "缺少配置文件" in payload["error"] def test_sync_requires_auth_without_network(): with tempfile.TemporaryDirectory() as tmp: path = write_config(tmp, cookie="", csrf="") code, output = run_cli(["sync", "--config", str(path)]) assert code == 2 payload = json.loads(output.strip().splitlines()[-1]) assert "cookie" in payload["error"] assert not (Path(tmp) / "app.db").exists() def test_snapshot_offline_empty_db(): with tempfile.TemporaryDirectory() as tmp: path = write_config(tmp, cookie="", csrf="") data = json.loads(path.read_text(encoding="utf-8")) data["folders"] = [] data["track_fans"] = [] path.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8") code, output = run_cli(["snapshot", "--config", str(path)]) assert code == 0 assert '"completed": true' in output assert '"total": 0' in output assert len(list((Path(tmp) / "backup").glob("app-*.db"))) == 1 def test_auth_check_without_cookie(): with tempfile.TemporaryDirectory() as tmp: path = write_config(tmp, cookie="", csrf="") code, output = run_cli(["auth-check", "--config", str(path)]) assert code == 1 payload = json.loads(output) assert payload["is_login"] is False assert "未配置 cookie" in payload["message"] def test_run_once_offline(): class FakeClient: def check_login(self): return LoginState(True, 1, "tester", 0, "OK") with tempfile.TemporaryDirectory() as tmp: path = write_config(tmp) data = json.loads(path.read_text(encoding="utf-8")) data["folders"] = [] data["track_fans"] = [] path.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8") original = cli._client cli._client = lambda *args, **kwargs: FakeClient() try: code, output = run_cli(["run", "--once", "--config", str(path)]) finally: cli._client = original assert code == 0 assert '"name": "folder_sync"' in output assert '"name": "snapshot"' in output def main_test(): test_init_and_status() test_missing_config() test_sync_requires_auth_without_network() test_snapshot_offline_empty_db() test_auth_check_without_cookie() test_run_once_offline() print("OK: CLI init/sync/snapshot/auth-check/run/status/错误路径测试全部通过") if __name__ == "__main__": main_test()