123 lines
4.3 KiB
Python
123 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from gyxx_flow.modules.content_marketing.runtime import runtime_paths
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|
RUNTIME_ROOT = (
|
|
PROJECT_ROOT / "src" / "gyxx_flow" / "modules" / "content_marketing" / "runtime"
|
|
)
|
|
|
|
|
|
def _source(relative: str) -> str:
|
|
return (RUNTIME_ROOT / relative).read_text(encoding="utf-8-sig")
|
|
|
|
|
|
def test_content_output_resolver_keeps_paths_inside_the_selected_layer(
|
|
tmp_path: Path,
|
|
) -> None:
|
|
root = tmp_path / "exports" / "content_marketing"
|
|
|
|
relative = runtime_paths.resolve_layer_output(
|
|
"reports/monthly.md", layer_root=root, field="--output"
|
|
)
|
|
absolute = runtime_paths.resolve_layer_output(
|
|
root / "summary" / "daily.md", layer_root=root, field="--output"
|
|
)
|
|
|
|
assert relative == (root / "reports" / "monthly.md").resolve()
|
|
assert absolute == (root / "summary" / "daily.md").resolve()
|
|
with pytest.raises(ValueError, match="--output"):
|
|
runtime_paths.resolve_layer_output(
|
|
"../escape.md", layer_root=root, field="--output"
|
|
)
|
|
with pytest.raises(ValueError, match="--output"):
|
|
runtime_paths.resolve_layer_output(
|
|
tmp_path / "outside.md", layer_root=root, field="--output"
|
|
)
|
|
|
|
|
|
def test_dynamic_mapping_uses_normalized_cache_and_read_only_source_seed() -> None:
|
|
source = _source("feishu_mapping.py")
|
|
|
|
assert 'MAPPING_DIR = PATHS.normalized_root / "mappings"' in source
|
|
assert 'MAPPING_SEED_PATH = PATHS.config_root /' in source
|
|
assert 'SELF_MAPPING_SEED_PATH = PATHS.config_root /' in source
|
|
assert 'MAPPING_PATH = PATHS.config_root /' not in source
|
|
assert "if data_dir:" not in source
|
|
|
|
|
|
def test_v2_outputs_and_checkpoints_use_their_semantic_layers() -> None:
|
|
assert 'Path("data") / "v2_results"' not in _source("chanmama_scraper.py")
|
|
assert 'PATHS.normalized_root / "v2_results"' in _source("chanmama_scraper.py")
|
|
|
|
for relative in (
|
|
"bilibili_scraper.py",
|
|
"pgy_xhs_scraper_v2.py",
|
|
"xingtu_scraper_v2.py",
|
|
"self_bilibili_scraper.py",
|
|
"self_douyin_scraper.py",
|
|
):
|
|
assert 'PATHS.normalized_root / "v2_results"' in _source(relative), relative
|
|
|
|
assert 'PATHS.curated_root / "run_all"' in _source("run_all.py")
|
|
assert 'PATHS.state_root / "checkpoints" / "bilibili"' in _source(
|
|
"bilibili_scraper.py"
|
|
)
|
|
assert "PATHS.browser_storage_state_file.write_text" in _source(
|
|
"xingtu_scraper.py"
|
|
)
|
|
assert 'PATHS.state_root / "checkpoints" / "pgy"' in _source(
|
|
"pgy_xhs_scraper_v2.py"
|
|
)
|
|
|
|
for relative in (
|
|
"data/tools/check_status.py",
|
|
"data/tools/retry_failed.py",
|
|
"data/tools/sync_metrics_to_cmt_notes.py",
|
|
):
|
|
source = _source(relative)
|
|
assert 'PATHS.normalized_root / "v2_results"' in source, relative
|
|
assert 'PATHS.raw_root / "v2_results"' not in source, relative
|
|
|
|
|
|
def test_transient_content_artifacts_use_tmp_root() -> None:
|
|
doc_writer = _source("data/tools/feishu_doc_writer.py")
|
|
report_card = _source("data/tools/daily_report_card.py")
|
|
|
|
assert 'TMP_DIR = PATHS.tmp_root / "feishu_doc_writer"' in doc_writer
|
|
assert 'PATHS.tmp_root / "daily_report_card"' in report_card
|
|
assert 'chart_path.with_name(f"{chart_path.stem}_feishu.png")' not in report_card
|
|
|
|
|
|
def test_batch_launchers_never_fall_back_to_module_local_var() -> None:
|
|
for path in sorted((RUNTIME_ROOT / "data" / "tools").glob("*.bat")):
|
|
source = path.read_text(encoding="utf-8-sig")
|
|
if "GYXX_DATA_ROOT" not in source:
|
|
continue
|
|
assert '%PROJECT_DIR%\\var' not in source, path.name
|
|
assert '%GYXX_PROJECT_ROOT%\\var' in source, path.name
|
|
assert "if not defined GYXX_PROJECT_ROOT" in source, path.name
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("relative", "layer_expression"),
|
|
(
|
|
("data/tools/analyze_comments.py", "PATHS.exports_root"),
|
|
("data/tools/analyze_note.py", "PATHS.exports_root"),
|
|
("data/tools/collect_note_metrics.py", "PATHS.normalized_root"),
|
|
("data/tools/generate_creator_report.py", "PATHS.exports_root"),
|
|
),
|
|
)
|
|
def test_cli_output_overrides_are_constrained_to_a_data_layer(
|
|
relative: str, layer_expression: str
|
|
) -> None:
|
|
source = _source(relative)
|
|
|
|
assert "resolve_layer_output(" in source
|
|
assert layer_expression in source
|
|
|