"""Tests for context & token visualization (Track: context_token_viz_20260301).""" from typing import Generator from unittest.mock import patch import pytest import ai_client from ai_client import _add_bleed_derived, get_history_bleed_stats from gui_2 import App # --- _add_bleed_derived unit tests --- def test_add_bleed_derived_aliases() -> None: base = {"provider": "test", "limit": 1000, "current": 400, "percentage": 40.0} result = _add_bleed_derived(base) assert result["estimated_prompt_tokens"] == 400 assert result["max_prompt_tokens"] == 1000 assert result["utilization_pct"] == 40.0 def test_add_bleed_derived_headroom() -> None: base = {"provider": "test", "limit": 1000, "current": 400, "percentage": 40.0} result = _add_bleed_derived(base) assert result["headroom_tokens"] == 600 def test_add_bleed_derived_would_trim_false() -> None: base = {"provider": "test", "limit": 100000, "current": 10000, "percentage": 10.0} result = _add_bleed_derived(base) assert result["would_trim"] is False def test_add_bleed_derived_would_trim_true() -> None: base = {"provider": "test", "limit": 100000, "current": 90000, "percentage": 90.0} result = _add_bleed_derived(base) assert result["would_trim"] is True # headroom = 10000 < 20000 def test_add_bleed_derived_breakdown() -> None: base = {"provider": "test", "limit": 10000, "current": 5000, "percentage": 50.0} result = _add_bleed_derived(base, sys_tok=500, tool_tok=2500) assert result["system_tokens"] == 500 assert result["tools_tokens"] == 2500 assert result["history_tokens"] == 2000 # 5000 - 500 - 2500 def test_add_bleed_derived_history_clamped_to_zero() -> None: """history_tokens should not go negative when sys+tool > current.""" base = {"provider": "test", "limit": 1000, "current": 100, "percentage": 10.0} result = _add_bleed_derived(base, sys_tok=200, tool_tok=2500) assert result["history_tokens"] == 0 def test_add_bleed_derived_headroom_clamped_to_zero() -> None: base = {"provider": "test", "limit": 1000, "current": 1100, "percentage": 110.0} result = _add_bleed_derived(base) assert result["headroom_tokens"] == 0 # --- get_history_bleed_stats returns all required keys --- REQUIRED_KEYS = [ "provider", "limit", "current", "percentage", "estimated_prompt_tokens", "max_prompt_tokens", "utilization_pct", "headroom_tokens", "would_trim", "system_tokens", "tools_tokens", "history_tokens", ] def test_get_history_bleed_stats_returns_all_keys_unknown_provider() -> None: """Fallback path (unknown provider) must still return all derived keys.""" original = ai_client._provider try: ai_client._provider = "unknown_test_provider" stats = get_history_bleed_stats() for key in REQUIRED_KEYS: assert key in stats, f"Missing key: {key}" finally: ai_client._provider = original # --- App initialization --- def test_app_token_stats_initialized_empty(app_instance: App) -> None: assert app_instance._token_stats == {} def test_app_last_stable_md_initialized_empty(app_instance: App) -> None: assert app_instance._last_stable_md == "" def test_app_has_render_token_budget_panel(app_instance: App) -> None: assert callable(getattr(app_instance, "_render_token_budget_panel", None)) def test_render_token_budget_panel_empty_stats_no_crash(app_instance: App) -> None: """With empty _token_stats, _render_token_budget_panel must not raise.""" app_instance._token_stats = {} # We can't render ImGui in tests, so just verify the guard condition logic # by checking the method exists and _token_stats is empty (early-return path) assert not app_instance._token_stats # falsy — method would return early # --- Trim warning logic --- def test_would_trim_boundary_exact() -> None: """would_trim is False when headroom == 20000 (threshold is strictly < 20000).""" base = {"provider": "test", "limit": 100000, "current": 80000, "percentage": 80.0} result = _add_bleed_derived(base) assert result["headroom_tokens"] == 20000 assert result["would_trim"] is False # headroom < 20000 is False at exactly 20000 def test_would_trim_just_below_threshold() -> None: base = {"provider": "test", "limit": 100000, "current": 80001, "percentage": 80.0} result = _add_bleed_derived(base) assert result["headroom_tokens"] == 19999 assert result["would_trim"] is True def test_would_trim_just_above_threshold() -> None: base = {"provider": "test", "limit": 100000, "current": 79999, "percentage": 80.0} result = _add_bleed_derived(base) assert result["headroom_tokens"] == 20001 assert result["would_trim"] is False # --- Cache status fields available from ai_client --- def test_gemini_cache_fields_accessible() -> None: """_gemini_cache, _gemini_cache_created_at, _GEMINI_CACHE_TTL must be accessible.""" assert hasattr(ai_client, "_gemini_cache") assert hasattr(ai_client, "_gemini_cache_created_at") assert hasattr(ai_client, "_GEMINI_CACHE_TTL") assert isinstance(ai_client._GEMINI_CACHE_TTL, int) assert ai_client._GEMINI_CACHE_TTL > 0 def test_anthropic_history_lock_accessible() -> None: """_anthropic_history_lock must be accessible for cache hint rendering.""" assert hasattr(ai_client, "_anthropic_history_lock") assert hasattr(ai_client, "_anthropic_history")