import asyncio import importlib import json import sys import types def test_cli_runs_single_task_with_prompt(tmp_path, load_json_fixture, monkeypatch): fake_scraper = types.ModuleType("src.scraper") async def placeholder_scrape(task_config, debug_limit): return 0 fake_scraper.scrape_xianyu = placeholder_scrape monkeypatch.setitem(sys.modules, "src.scraper", fake_scraper) sys.modules.pop("spider_v2", None) spider_v2 = importlib.import_module("spider_v2") config_data = load_json_fixture("config.sample.json") base_prompt = "Base prompt. " + ("x" * 120) + " {{CRITERIA_SECTION}}" criteria_prompt = "Criteria text for A7M4." base_path = tmp_path / "base_prompt.txt" criteria_path = tmp_path / "criteria_prompt.txt" base_path.write_text(base_prompt, encoding="utf-8") criteria_path.write_text(criteria_prompt, encoding="utf-8") config_data[0]["ai_prompt_base_file"] = str(base_path) config_data[0]["ai_prompt_criteria_file"] = str(criteria_path) config_data[1]["ai_prompt_base_file"] = str(base_path) config_data[1]["ai_prompt_criteria_file"] = str(criteria_path) config_path = tmp_path / "config.json" config_path.write_text(json.dumps(config_data, ensure_ascii=False), encoding="utf-8") state_path = tmp_path / "state.json" state_path.write_text("{}", encoding="utf-8") monkeypatch.setattr(spider_v2, "STATE_FILE", str(state_path)) called = [] async def fake_scrape_xianyu(task_config, debug_limit): called.append(task_config["task_name"]) assert "{{CRITERIA_SECTION}}" not in task_config["ai_prompt_text"] assert "Criteria text for A7M4." in task_config["ai_prompt_text"] return 1 monkeypatch.setattr(spider_v2, "scrape_xianyu", fake_scrape_xianyu) monkeypatch.setattr(sys, "argv", ["spider_v2.py", "--config", str(config_path), "--task-name", "Sony A7M4"]) asyncio.run(spider_v2.main()) assert called == ["Sony A7M4"]