from __future__ import annotations from pathlib import Path def test_actions_save_env_to_file_expands_shell_vars(monkeypatch, tmp_path: Path): """Regression: core env setup must expand `$HOME`/`$KNOE_HOME` for filesystem ops. This complements the Environment UI regression test by covering the non-UI installer/actions code paths that can run during status checks. """ monkeypatch.chdir(tmp_path) home_dir = tmp_path / "home" home_dir.mkdir(parents=True, exist_ok=True) monkeypatch.setenv("HOME", str(home_dir)) proj = tmp_path / "project_root" (proj / "etc").mkdir(parents=True, exist_ok=True) (proj / "etc" / "init-port-forward.sh").write_text( "#!/usr/bin/env bash\necho ok\n" ) (proj / "etc" / "dummy.txt").write_text("ok\n") from knoe.core.actions import KnoeInstaller class Dummy(KnoeInstaller): def __init__(self, project_root: Path): self.project_root = project_root self.inputs = {"init_cluster.cluster_env": "dev"} self._init_shared_state() def _get_input(self, key: str, default: str | None = None) -> str: if key in self.inputs: return self.inputs[key] return default if default is not None else "" dummy = Dummy(proj) values = { "KNOE_HOME": "$HOME/knoe", "KNOE_CONF": "$KNOE_HOME/conf", "PROLE_DATA": "$KNOE_HOME/data", "PROLE_LOGS": "$KNOE_HOME/logs", "KNOE_SERVICE": "$KNOE_HOME/etc", } dummy._save_env_to_file(values) expected_home = home_dir / "knoe" assert expected_home.is_dir() assert (expected_home / "conf").is_dir() assert (expected_home / "data").is_dir() assert (expected_home / "logs").is_dir() assert (expected_home / "etc").is_dir() assert (expected_home / "env.sh").is_file() assert (expected_home / "init-port-forward.sh").is_file() # Critical assertions: we must NOT create literal `$HOME`/`$KNOE_HOME` dirs in CWD. assert not (tmp_path / "$HOME").exists() assert not (tmp_path / "$KNOE_HOME").exists()