# -*- coding: utf-8 -*- # Copyright (c) 2025 relakkes@gmail.com # # This file is part of MediaCrawler project. # Repository: https://github.com/NanmiCoder/MediaCrawler/blob/main/tests/test_cmd_arg_monitor_flags.py # GitHub: https://github.com/NanmiCoder # Licensed under NON-COMMERCIAL LEARNING LICENSE 1.1 # # 声明:本代码仅供学习和研究目的使用。使用者应遵守以下原则: # 1. 不得用于任何商业用途。 # 2. 使用时应遵守目标平台的使用条款和robots.txt规则。 # 3. 不得进行大规模爬取或对平台造成运营干扰。 # 4. 应合理控制请求频率,避免给目标平台带来不必要的负担。 # 5. 不得用于任何非法或不当的用途。 # # 详细许可条款请参阅项目根目录下的LICENSE文件。 # 使用本代码即表示您同意遵守上述原则和LICENSE中的所有条款。 """Tests for the CLI flags added to support unattended monitoring runs. Each flag must default to the existing config value, so a manual crawl that does not pass them behaves exactly as before. """ import pytest import config from cmd_arg.arg import parse_cmd BASE_ARGS = ["--platform", "xhs", "--type", "creator", "--creator_id", "abc123"] @pytest.fixture(autouse=True) def _isolate_config(monkeypatch): monkeypatch.setattr(config, "ENABLE_CDP_MODE", True) monkeypatch.setattr(config, "INJECT_ALL_COOKIES", False) monkeypatch.setattr(config, "SAVE_LOGIN_STATE", True) monkeypatch.setattr(config, "COOKIES", "") monkeypatch.setattr(config, "SAVE_DATA_PATH", "") monkeypatch.setattr(config, "CRAWLER_MAX_SLEEP_SEC", 2) yield class TestEnableCdpMode: """CDP attaches to the user's desktop Chrome, which cannot work on a server.""" @pytest.mark.asyncio async def test_false_disables_cdp(self): await parse_cmd([*BASE_ARGS, "--enable_cdp_mode", "false"]) assert config.ENABLE_CDP_MODE is False @pytest.mark.asyncio async def test_defaults_to_config_value(self): await parse_cmd(BASE_ARGS) assert config.ENABLE_CDP_MODE is True class TestCookieFlags: @pytest.mark.asyncio async def test_inject_all_cookies_enables_switch(self): await parse_cmd([*BASE_ARGS, "--inject_all_cookies", "true"]) assert config.INJECT_ALL_COOKIES is True @pytest.mark.asyncio async def test_inject_all_cookies_defaults_off(self): await parse_cmd(BASE_ARGS) assert config.INJECT_ALL_COOKIES is False @pytest.mark.asyncio async def test_cookies_file_is_read_into_config(self, tmp_path): cookie_file = tmp_path / "cookies.txt" cookie_file.write_text("web_session=abc; a1=def", encoding="utf-8") await parse_cmd([*BASE_ARGS, "--cookies_file", str(cookie_file)]) assert config.COOKIES == "web_session=abc; a1=def" @pytest.mark.asyncio async def test_cookies_file_wins_over_inline_cookies(self, tmp_path): cookie_file = tmp_path / "cookies.txt" cookie_file.write_text("web_session=fromfile", encoding="utf-8") await parse_cmd( [*BASE_ARGS, "--cookies", "web_session=inline", "--cookies_file", str(cookie_file)] ) assert config.COOKIES == "web_session=fromfile" @pytest.mark.asyncio async def test_missing_cookies_file_is_rejected(self, tmp_path): missing = tmp_path / "nope.txt" with pytest.raises(Exception) as excinfo: await parse_cmd([*BASE_ARGS, "--cookies_file", str(missing)]) # A silently-ignored unreadable cookie file would produce a crawl that # returns nothing, which is exactly the failure mode this flag exists # to avoid. assert "cookies_file" in str(excinfo.value) class TestSaveDataPath: @pytest.mark.asyncio async def test_save_data_path_is_applied(self): await parse_cmd([*BASE_ARGS, "--save_data_path", "data/monitor_runs/1/2"]) assert config.SAVE_DATA_PATH == "data/monitor_runs/1/2" class TestSaveLoginState: @pytest.mark.asyncio async def test_save_login_state_can_be_disabled(self): await parse_cmd([*BASE_ARGS, "--save_login_state", "false"]) assert config.SAVE_LOGIN_STATE is False class TestCrawlSleepSec: """Exposed on the Settings page; previously had no CLI flag at all.""" @pytest.mark.asyncio async def test_value_is_applied(self): await parse_cmd([*BASE_ARGS, "--crawler_max_sleep_sec", "9"]) assert config.CRAWLER_MAX_SLEEP_SEC == 9 @pytest.mark.asyncio async def test_defaults_to_config_value(self, monkeypatch): monkeypatch.setattr(config, "CRAWLER_MAX_SLEEP_SEC", 4) await parse_cmd(BASE_ARGS) assert config.CRAWLER_MAX_SLEEP_SEC == 4