from __future__ import annotations import io import json from pathlib import Path import pytest from gyxx_flow.cli import EXIT_SUCCESS, main from gyxx_flow.core.config import Settings from gyxx_flow.script_catalog import ScriptCatalog, ScriptCatalogError def test_script_catalog_discovers_python_main_and_launchers(tmp_path: Path) -> None: runtime = tmp_path / "content_marketing" / "runtime" (runtime / "tools").mkdir(parents=True) (runtime / "tools" / "run_job.py").write_text( 'if __name__ == "__main__":\n raise SystemExit(0)\n', encoding="utf-8" ) (runtime / "library.py").write_text("def helper():\n return 1\n", encoding="utf-8") (runtime / "daily.bat").write_text("@echo off\n", encoding="utf-8") (runtime / "maint.ps1").write_text("Write-Output ok\n", encoding="utf-8") (runtime / "runtime_tests").mkdir() (runtime / "runtime_tests" / "test_old.py").write_text( 'if __name__ == "__main__":\n pass\n', encoding="utf-8" ) catalog = ScriptCatalog.discover({"content_marketing": runtime}) assert catalog.script_ids == ( "content_marketing:daily.bat", "content_marketing:maint.ps1", "content_marketing:tools/run_job.py", ) assert catalog.get("content_marketing:tools/run_job.py").entry == "tools/run_job.py" def test_default_script_catalog_discovers_every_project_owned_runtime() -> None: catalog = ScriptCatalog.discover_default() modules = {item.module for item in catalog.scripts} assert modules == { "content_marketing", "product_commerce", "shop_intelligence", "supply_chain", } assert len(catalog.scripts) > 21 @pytest.mark.parametrize("script_id", ("missing", "content_marketing:../run.py")) def test_script_catalog_rejects_unknown_or_unsafe_ids( tmp_path: Path, script_id: str ) -> None: runtime = tmp_path / "content_marketing" / "runtime" runtime.mkdir(parents=True) catalog = ScriptCatalog.discover({"content_marketing": runtime}) with pytest.raises(ScriptCatalogError): catalog.get(script_id) def test_cli_lists_and_dry_runs_project_owned_scripts(tmp_path: Path) -> None: output = io.StringIO() settings = Settings(project_root=Path(__file__).parents[1], data_root=tmp_path) assert main(["scripts", "list", "--json"], settings=settings, stdout=output) == 0 rows = json.loads(output.getvalue()) assert len(rows) > 21 assert {row["module"] for row in rows} == { "content_marketing", "product_commerce", "shop_intelligence", "supply_chain", } output = io.StringIO() exit_code = main( [ "scripts", "run", "content_marketing:run_all.py", "--date", "2026-07-27", ], settings=settings, stdout=output, ) payload = json.loads(output.getvalue()) assert exit_code == EXIT_SUCCESS assert payload["dry_run"] is True assert payload["script_id"] == "content_marketing:run_all.py" assert payload["steps"] == {"module_script": "skipped"}