import os import tempfile from typer.testing import CliRunner from porchlight.cli import app runner = CliRunner() ENV = {"OIDC_OP_ISSUER": "https://example.com"} def _env(tmpdir: str) -> dict[str, str]: return {**ENV, "OIDC_OP_SQLITE_PATH": os.path.join(tmpdir, "test.db")} # -- create-invite ----------------------------------------------------------- def test_create_invite_prints_registration_url() -> None: """create-invite should print a URL containing /register/.""" with tempfile.TemporaryDirectory() as tmpdir: result = runner.invoke(app, ["create-invite", "testuser"], env=_env(tmpdir)) assert result.exit_code == 0, result.output assert "https://example.com/register/" in result.output def test_create_invite_with_note() -> None: """create-invite with --note should work.""" with tempfile.TemporaryDirectory() as tmpdir: result = runner.invoke(app, ["create-invite", "testuser", "--note", "Welcome aboard"], env=_env(tmpdir)) assert result.exit_code == 0, result.output assert "https://example.com/register/" in result.output def test_create_invite_with_custom_ttl() -> None: """create-invite with --ttl should use the custom TTL.""" with tempfile.TemporaryDirectory() as tmpdir: result = runner.invoke(app, ["create-invite", "testuser", "--ttl", "3600"], env=_env(tmpdir)) assert result.exit_code == 0, result.output assert "https://example.com/register/" in result.output def test_create_invite_missing_username_shows_error() -> None: """create-invite without a username should show an error.""" result = runner.invoke(app, ["create-invite"]) assert result.exit_code != 0 # -- initial-admin ------------------------------------------------------------ def test_initial_admin_creates_user_and_prints_url() -> None: """initial-admin should create a user and print a registration URL.""" with tempfile.TemporaryDirectory() as tmpdir: result = runner.invoke(app, ["initial-admin", "admin"], env=_env(tmpdir)) assert result.exit_code == 0, result.output assert "https://example.com/register/" in result.output def test_initial_admin_with_custom_groups() -> None: """initial-admin with --group should assign those groups.""" with tempfile.TemporaryDirectory() as tmpdir: result = runner.invoke( app, ["initial-admin", "admin", "--group", "admin", "--group", "superusers"], env=_env(tmpdir) ) assert result.exit_code == 0, result.output assert "https://example.com/register/" in result.output def test_initial_admin_duplicate_username_fails() -> None: """initial-admin should fail if username already exists.""" with tempfile.TemporaryDirectory() as tmpdir: env = _env(tmpdir) # Create the user first result1 = runner.invoke(app, ["initial-admin", "admin"], env=env) assert result1.exit_code == 0, result1.output # Try again — should fail result2 = runner.invoke(app, ["initial-admin", "admin"], env=env) assert result2.exit_code != 0 def test_initial_admin_missing_username_shows_error() -> None: """initial-admin without a username should show an error.""" result = runner.invoke(app, ["initial-admin"]) assert result.exit_code != 0