Private
Public Access
test(sandbox): add [paths] section regression tests for FR2 v2 design
This commit is contained in:
@@ -246,6 +246,62 @@ def test_appcontroller_init_does_not_load_config() -> None:
|
|||||||
raise AssertionError("AppController.__init__ not found")
|
raise AssertionError("AppController.__init__ not found")
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_overrides_toml_has_paths_section() -> None:
|
||||||
|
"""The auto-generated config_overrides.toml must include a [paths] section
|
||||||
|
that overrides every path getter to point inside _ISOLATION_WORKSPACE.
|
||||||
|
This is the v2 design (FR2 + per-path routing via config.toml, no env vars).
|
||||||
|
[C: tests/conftest.py:isolate_workspace]"""
|
||||||
|
import tomllib
|
||||||
|
runs = sorted(Path("tests/artifacts").glob("_isolation_workspace_*"))
|
||||||
|
assert runs, "no isolation workspaces found — did a test run yet?"
|
||||||
|
latest = runs[-1]
|
||||||
|
config_file = latest / "config_overrides.toml"
|
||||||
|
assert config_file.exists(), f"missing {config_file}"
|
||||||
|
with open(config_file, "rb") as f:
|
||||||
|
cfg = tomllib.load(f)
|
||||||
|
assert "paths" in cfg, (
|
||||||
|
f"config_overrides.toml must contain a [paths] section; "
|
||||||
|
f"got sections: {list(cfg.keys())}"
|
||||||
|
)
|
||||||
|
paths = cfg["paths"]
|
||||||
|
expected_keys = {
|
||||||
|
"presets", "tool_presets", "personas", "themes",
|
||||||
|
"workspace_profiles", "credentials", "logs_dir", "scripts_dir",
|
||||||
|
}
|
||||||
|
missing = expected_keys - set(paths.keys())
|
||||||
|
assert not missing, f"missing [paths] keys: {missing}"
|
||||||
|
for key, value in paths.items():
|
||||||
|
assert str(latest) in str(value), (
|
||||||
|
f"[paths].{key} = '{value}' does not point inside {latest}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_path_getters_read_from_config_paths_section() -> None:
|
||||||
|
"""Every global path getter in src/paths.py reads from the [paths] section
|
||||||
|
of the active config when no env var is set. Verifies via AST that each
|
||||||
|
get_*_path() function calls _resolve_path (not raw os.environ.get)."""
|
||||||
|
import ast
|
||||||
|
paths_py = Path(__file__).resolve().parent.parent / "src" / "paths.py"
|
||||||
|
tree = ast.parse(paths_py.read_text(encoding="utf-8"))
|
||||||
|
getters = {
|
||||||
|
"get_global_presets_path": "presets",
|
||||||
|
"get_global_tool_presets_path": "tool_presets",
|
||||||
|
"get_global_personas_path": "personas",
|
||||||
|
"get_global_themes_path": "themes",
|
||||||
|
"get_global_workspace_profiles_path": "workspace_profiles",
|
||||||
|
"get_credentials_path": "credentials",
|
||||||
|
"get_logs_dir": "logs_dir",
|
||||||
|
"get_scripts_dir": "scripts_dir",
|
||||||
|
}
|
||||||
|
for node in ast.walk(tree):
|
||||||
|
if isinstance(node, ast.FunctionDef) and node.name in getters:
|
||||||
|
src = ast.unparse(node)
|
||||||
|
assert "_resolve_path(" in src, (
|
||||||
|
f"{node.name} must call _resolve_path() to read from config.toml [paths]; "
|
||||||
|
f"got direct os.environ.get() instead."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(os.name != "nt", reason="Windows-only sandbox wrapper")
|
@pytest.mark.skipif(os.name != "nt", reason="Windows-only sandbox wrapper")
|
||||||
def test_run_tests_sandboxed_whatif() -> None:
|
def test_run_tests_sandboxed_whatif() -> None:
|
||||||
"""pwsh -File scripts/run_tests_sandboxed.ps1 -WhatIf exits 0 without
|
"""pwsh -File scripts/run_tests_sandboxed.ps1 -WhatIf exits 0 without
|
||||||
|
|||||||
Reference in New Issue
Block a user