import pytest from unittest.mock import MagicMock from src.claude_client import ClaudeClient, MODEL @pytest.fixture def mock_anthropic(mocker): return mocker.patch("src.claude_client.Anthropic") def _make_response(mock_anthropic, text: str): text_block = MagicMock() text_block.type = "text" text_block.text = text mock_response = MagicMock() mock_response.content = [text_block] mock_anthropic.return_value.messages.create.return_value = mock_response return mock_response def test_generate_report_returns_text_content(mock_anthropic): _make_response(mock_anthropic, "## Executive Summary\n\nTest content.") client = ClaudeClient("fake_key") result = client.generate_report("system", "user prompt") assert result == "## Executive Summary\n\nTest content." def test_generate_report_skips_thinking_blocks(mock_anthropic): thinking_block = MagicMock() thinking_block.type = "thinking" thinking_block.text = "internal reasoning not for output" text_block = MagicMock() text_block.type = "text" text_block.text = "Report output only" mock_response = MagicMock() mock_response.content = [thinking_block, text_block] mock_anthropic.return_value.messages.create.return_value = mock_response client = ClaudeClient("fake_key") result = client.generate_report("system", "user prompt") assert "internal reasoning" not in result assert result == "Report output only" def test_generate_report_uses_correct_model(mock_anthropic): _make_response(mock_anthropic, "report") client = ClaudeClient("fake_key") client.generate_report("sys", "user") call_kwargs = mock_anthropic.return_value.messages.create.call_args.kwargs assert call_kwargs["model"] == MODEL def test_generate_report_uses_max_tokens(mock_anthropic): _make_response(mock_anthropic, "report") client = ClaudeClient("fake_key") client.generate_report("sys", "user") call_kwargs = mock_anthropic.return_value.messages.create.call_args.kwargs assert call_kwargs["max_tokens"] == 4096 def test_generate_report_passes_system_prompt(mock_anthropic): _make_response(mock_anthropic, "report") client = ClaudeClient("fake_key") client.generate_report("my system prompt", "user message") call_kwargs = mock_anthropic.return_value.messages.create.call_args.kwargs assert call_kwargs["system"] == "my system prompt" def test_generate_report_concatenates_multiple_text_blocks(mock_anthropic): block_a = MagicMock() block_a.type = "text" block_a.text = "Part one. " block_b = MagicMock() block_b.type = "text" block_b.text = "Part two." mock_response = MagicMock() mock_response.content = [block_a, block_b] mock_anthropic.return_value.messages.create.return_value = mock_response client = ClaudeClient("fake_key") result = client.generate_report("sys", "user") assert result == "Part one. Part two." def test_chat_returns_text(mocker): mock_anthropic = mocker.patch("src.claude_client.Anthropic") mock_client = MagicMock() mock_anthropic.return_value = mock_client mock_block = MagicMock() mock_block.type = "text" mock_block.text = "Here is the answer." mock_client.messages.create.return_value.content = [mock_block] from src.claude_client import ClaudeClient client = ClaudeClient("fake_key") result = client.chat( messages=[{"role": "user", "content": "What is blocked?"}], system_prompt="You are an assistant." ) assert result == "Here is the answer." def test_chat_passes_messages_and_system(mocker): mock_anthropic = mocker.patch("src.claude_client.Anthropic") mock_client = MagicMock() mock_anthropic.return_value = mock_client mock_block = MagicMock() mock_block.type = "text" mock_block.text = "response" mock_client.messages.create.return_value.content = [mock_block] from src.claude_client import ClaudeClient client = ClaudeClient("fake_key") messages = [{"role": "user", "content": "hello"}] client.chat(messages=messages, system_prompt="sys") call_kwargs = mock_client.messages.create.call_args.kwargs assert call_kwargs["system"] == "sys" assert call_kwargs["messages"] == messages assert call_kwargs["max_tokens"] == 8192