from pathlib import Path from dotenv import dotenv_values from typer.testing import CliRunner from triggershell.cli import _slug, app runner = CliRunner() def test_slug_normalizes_to_env_var_style() -> None: assert _slug("ci-bot") == "CI_BOT" assert _slug("Admin User") == "ADMIN_USER" assert _slug("__weird--name__") == "WEIRD_NAME" def test_users_add_stores_hash_in_dotenv(tmp_path: Path) -> None: config_path = tmp_path / "triggershell.yml" config_path.write_text("scripts: []\n") result = runner.invoke(app, ["users", "add", "admin", "--config", str(config_path)], input="s3cret\ns3cret\n") assert result.exit_code == 0, result.output env_path = tmp_path / ".env" assert env_path.exists() values = dotenv_values(env_path) assert values["TRIGGERSHELL_USER_ADMIN_PASSWORD_HASH"].startswith("$argon2id$") assert "${TRIGGERSHELL_USER_ADMIN_PASSWORD_HASH}" in result.output assert "$argon2id$" not in result.output.split("Stored")[0] # raw hash not printed pre-storage def test_users_add_inline_does_not_touch_dotenv(tmp_path: Path) -> None: config_path = tmp_path / "triggershell.yml" config_path.write_text("scripts: []\n") result = runner.invoke( app, ["users", "add", "admin", "--config", str(config_path), "--inline"], input="s3cret\ns3cret\n" ) assert result.exit_code == 0, result.output assert not (tmp_path / ".env").exists() assert "$argon2id$" in result.output def test_users_add_token_overwrites_existing_var(tmp_path: Path) -> None: config_path = tmp_path / "triggershell.yml" config_path.write_text("scripts: []\n") first = runner.invoke(app, ["users", "add-token", "ci-bot", "--config", str(config_path)]) assert first.exit_code == 0, first.output first_hash = dotenv_values(tmp_path / ".env")["TRIGGERSHELL_TOKEN_CI_BOT_HASH"] second = runner.invoke(app, ["users", "add-token", "ci-bot", "--config", str(config_path)]) assert second.exit_code == 0, second.output values = dotenv_values(tmp_path / ".env") second_hash = values["TRIGGERSHELL_TOKEN_CI_BOT_HASH"] assert first_hash != second_hash env_content = (tmp_path / ".env").read_text() assert env_content.count("TRIGGERSHELL_TOKEN_CI_BOT_HASH") == 1