"""Unit tests for app.cli. Sub-command parsing only — the DB-touching paths (`grant_credit`, `revoke_credit`, `show_status`) are exercised manually inside the dev container. The parser-level tests are enough to catch the common shapes: bad args, missing args, unknown sub-command.""" from __future__ import annotations import pytest from app.cli import build_parser def test_grant_credit_parses(): args = build_parser().parse_args(["grant-credit", "user@example.com", "3"]) assert args.cmd == "grant-credit" assert args.email == "user@example.com" assert args.months == 3.0 def test_grant_credit_accepts_fractional_months(): args = build_parser().parse_args(["grant-credit", "user@x.com", "0.5"]) assert args.months == 0.5 def test_revoke_credit_parses(): args = build_parser().parse_args(["revoke-credit", "user@example.com"]) assert args.cmd == "revoke-credit" assert args.email == "user@example.com" def test_show_status_parses(): args = build_parser().parse_args(["show-status", "user@example.com"]) assert args.cmd == "show-status" def test_grant_credit_requires_months(): with pytest.raises(SystemExit): build_parser().parse_args(["grant-credit", "user@example.com"]) def test_unknown_command_rejected(): with pytest.raises(SystemExit): build_parser().parse_args(["bogus-cmd"]) def test_no_command_rejected(): with pytest.raises(SystemExit): build_parser().parse_args([])