"""Tests for explicit calendar-authorize operation – TDD fakes only, no live service.""" import json import pytest from typer.testing import CliRunner from reyna_cli.cli import app runner = CliRunner() def test_privacy_client_direct_op_uses_explicit_operation(monkeypatch): from reyna_cli import privacy_host as ph_mod captured = {} class FakeClient: def __init__(self, timeout): captured["timeout"] = timeout def call(self, op, args): captured["op"] = op captured["args"] = args return {"id": "x", "ok": True, "result": {"protocol_version": "1.0.0", "operation": "calendar.request_full_access", "status": "authorized"}} monkeypatch.setattr(ph_mod, "PrivacyClient", FakeClient) result = ph_mod.native_calendar_request_full_access() assert captured["op"] == "calendar.request_full_access" assert captured["args"] == {} assert captured["timeout"] == 35 assert result["ok"] is True assert result["source"] == "native_privacy_host" assert result["result"]["status"] == "authorized" def test_calendar_authorize_cli_no_generic_fallback(monkeypatch): from reyna_cli import privacy_host as ph_mod calls = {"count": 0} def fake_native(): calls["count"] += 1 return {"ok": True, "source": "native_privacy_host", "result": {"protocol_version": "1.0.0", "operation": "calendar.request_full_access", "status": "authorized"}} monkeypatch.setattr("reyna_cli.privacy_host.native_calendar_request_full_access", fake_native) # Ensure src does not use generic call / MCP fallback src = ph_mod.__file__ import pathlib text = pathlib.Path(src).read_text() # The new function must call PrivacyClient directly with explicit op and not use generic 'call' helper referencing arbitrary operation arg # CLI command must import the explicit function, not PrivacyClient directly (checked via cli source) cli_text = pathlib.Path("src/reyna_cli/cli.py").read_text() if pathlib.Path("src/reyna_cli/cli.py").exists() else pathlib.Path(__file__).parents[1].joinpath("src/reyna_cli/cli.py").read_text() res = runner.invoke(app, ["privacy-host", "calendar-authorize", "--json"]) assert res.exit_code == 0, res.stdout + res.stderr payload = json.loads(res.stdout) assert payload["ok"] is True assert payload["result"]["status"] == "authorized" assert calls["count"] == 1 def test_calendar_authorize_cli_help_mentions_prompt(): res = runner.invoke(app, ["privacy-host", "calendar-authorize", "--help"]) assert res.exit_code == 0 out = res.stdout.lower() # Help must make prompting clear assert "calendar" in out assert "permission" in out or "prompt" in out or "privacy" in out def test_calendar_authorize_failures_surface(monkeypatch): from reyna_cli.privacy_client import PrivacyClientError def fake_fail(): raise PrivacyClientError("privacy RPC returned ok=false: {'code': 'permission_denied'}") monkeypatch.setattr("reyna_cli.privacy_host.native_calendar_request_full_access", fake_fail) res = runner.invoke(app, ["privacy-host", "calendar-authorize", "--json"]) assert res.exit_code != 0 # payload should have ok:false payload = json.loads(res.stdout) assert payload["ok"] is False def test_native_calendar_request_full_access_no_mcp_import(): from reyna_cli import privacy_host as ph_mod import pathlib src = pathlib.Path(ph_mod.__file__).read_text() # Ensure new function does not import MCP fallback # We locate function definition region # Simple guard: whole module still must not reference MCP fallback helpers assert "call_macmini_tool" not in src assert "macmini_client" not in src # The specific new function should exist assert "def native_calendar_request_full_access" in src assert "calendar.request_full_access" in src def test_privacy_host_cli_has_calendar_authorize(): res = runner.invoke(app, ["privacy-host", "--help"]) assert res.exit_code == 0 assert "calendar-authorize" in res.stdout # Ensure no generic 'call' command exposed assert "call" not in res.stdout.lower() or "calendar-authorize" in res.stdout