"""Comprehensive tests for Discord response formatter.""" import pytest from claude_coordinator.response_formatter import ResponseFormatter class TestResponseFormatterBasics: """Test basic functionality of ResponseFormatter.""" def test_short_response_single_message(self): """Short response (<2000 chars) returns single message.""" formatter = ResponseFormatter() text = "This is a short response." result = formatter.format_response(text) assert len(result) == 1 assert result[0] == text def test_empty_input_returns_empty_list(self): """Empty input returns empty list.""" formatter = ResponseFormatter() result = formatter.format_response("") assert result == [] def test_whitespace_only_returns_empty_list(self): """Whitespace-only input returns empty list.""" formatter = ResponseFormatter() result = formatter.format_response(" \n\t \n ") assert result == [] def test_exactly_max_length_single_message(self): """Text exactly at max_length returns single message.""" formatter = ResponseFormatter() text = "a" * 2000 result = formatter.format_response(text, max_length=2000) assert len(result) == 1 assert result[0] == text class TestSmartChunking: """Test intelligent chunking on natural boundaries.""" def test_long_response_without_code_blocks(self): """Long response without code blocks is intelligently chunked.""" formatter = ResponseFormatter() # Create text longer than 2000 chars with paragraphs paragraphs = [ "This is paragraph one with some content. " * 30, "This is paragraph two with more content. " * 30, "This is paragraph three with even more content. " * 30, ] text = "\n\n".join(paragraphs) result = formatter.format_response(text, max_length=2000) # Should split into multiple messages assert len(result) > 1 # Each chunk should be under max_length for chunk in result: assert len(chunk) <= 2000 def test_split_on_paragraph_boundaries(self): """Text splits on paragraph boundaries (double newlines).""" formatter = ResponseFormatter() # Create text with clear paragraph breaks paragraph1 = "A" * 1100 + "\n\n" paragraph2 = "B" * 1100 text = paragraph1 + paragraph2 result = formatter.format_response(text, max_length=2000) # Should split into 2 chunks at paragraph boundary assert len(result) == 2 assert "A" in result[0] and "B" not in result[0] assert "B" in result[1] and "A" not in result[1] def test_split_on_sentence_boundaries(self): """Text splits on sentence boundaries when no paragraph breaks.""" formatter = ResponseFormatter() # Create long sentences sentence1 = "This is the first sentence. " * 40 sentence2 = "This is the second sentence. " * 40 text = sentence1 + sentence2 result = formatter.format_response(text, max_length=1500) # Should split into multiple messages assert len(result) >= 2 # Each chunk should be under max_length for chunk in result: assert len(chunk) <= 1500 def test_split_on_word_boundaries(self): """Text splits on word boundaries when no sentence breaks.""" formatter = ResponseFormatter() # Create text with unique words to detect mid-word splits text = " ".join([f"testword{i}" for i in range(400)]) # ~4000 chars result = formatter.format_response(text, max_length=2000) # Should split into chunks assert len(result) >= 2 # All chunks should be under max length for chunk in result: assert len(chunk) <= 2000 def test_very_long_single_line(self): """Single line longer than max_length is force-split.""" formatter = ResponseFormatter() # Create one continuous line with no spaces text = "a" * 3000 result = formatter.format_response(text, max_length=2000) # Should split into 2 chunks assert len(result) == 2 assert len(result[0]) == 2000 assert len(result[1]) == 1000 class TestCodeBlockPreservation: """Test code block handling and preservation.""" def test_single_code_block_preserved(self): """Response with single code block preserves it.""" formatter = ResponseFormatter() text = "Here's the code:\n\n```python\ndef hello():\n return 'world'\n```\n\nThat's it!" result = formatter.format_response(text) # Should keep code block intact assert len(result) == 1 assert "```python" in result[0] assert "def hello():" in result[0] assert "```" in result[0] def test_multiple_code_blocks_preserved(self): """Response with multiple code blocks preserves all.""" formatter = ResponseFormatter() text = """First block: ```python def func1(): pass ``` Second block: ```javascript function func2() {} ``` Done!""" result = formatter.format_response(text) # Should preserve both code blocks full_text = " ".join(result) assert "```python" in full_text assert "```javascript" in full_text assert full_text.count("```") >= 4 # 2 opening + 2 closing def test_code_block_at_chunk_boundary(self): """Code block at chunk boundary is properly split and closed.""" formatter = ResponseFormatter() # Create text with code block that causes splitting prefix = "A" * 1000 + "\n\n" code_block = "```python\n" + ("print('test')\n" * 100) + "```" text = prefix + code_block result = formatter.format_response(text, max_length=2000) # Should split into multiple chunks assert len(result) >= 2 # Each chunk should have valid markdown for chunk in result: assert len(chunk) <= 2000 def test_large_code_block_split_correctly(self): """Code block larger than 2000 chars splits with markers.""" formatter = ResponseFormatter() # Create huge code block code_lines = "\n".join([f"line_{i} = {i}" for i in range(200)]) text = f"```python\n{code_lines}\n```" result = formatter.format_response(text, max_length=2000) # Should split into multiple chunks assert len(result) >= 2 # Each chunk should have code block markers for chunk in result: assert chunk.startswith("```python") assert chunk.endswith("```") assert len(chunk) <= 2000 def test_code_block_without_language(self): """Code blocks without language identifier are handled.""" formatter = ResponseFormatter() text = "Code:\n\n```\nsome code here\nmore code\n```\n\nDone." result = formatter.format_response(text) assert len(result) == 1 assert "```" in result[0] assert "some code here" in result[0] class TestMixedContent: """Test responses with mixed markdown and code.""" def test_mixed_markdown_preserved(self): """Response with bold, italic, lists is preserved.""" formatter = ResponseFormatter() text = """**Bold text** and *italic text* - List item 1 - List item 2 - List item 3 Regular text after list.""" result = formatter.format_response(text) assert len(result) == 1 assert "**Bold text**" in result[0] assert "*italic text*" in result[0] assert "- List item 1" in result[0] def test_multiple_paragraphs_chunked_correctly(self): """Response with multiple paragraphs splits on paragraph boundaries.""" formatter = ResponseFormatter() # Create multiple substantial paragraphs paragraphs = [] for i in range(5): paragraphs.append(f"Paragraph {i+1}. " + ("Content. " * 50)) text = "\n\n".join(paragraphs) result = formatter.format_response(text, max_length=2000) # Should split into multiple messages assert len(result) >= 2 # Verify content distribution for chunk in result: assert len(chunk) <= 2000 class TestCodeBlockSplitting: """Test code block splitting behavior with split_on_code_blocks flag.""" def test_split_on_code_blocks_false(self): """With split_on_code_blocks=False, uses simple splitting.""" formatter = ResponseFormatter() text = "Text before\n\n```python\ndef func():\n pass\n```\n\nText after" * 50 result = formatter.format_response(text, max_length=2000, split_on_code_blocks=False) # Should split into chunks assert len(result) >= 2 # May split code blocks (not preserving them) for chunk in result: assert len(chunk) <= 2000 def test_split_on_code_blocks_true_preserves(self): """With split_on_code_blocks=True, preserves code block integrity.""" formatter = ResponseFormatter() code = "```python\ndef hello():\n return 'world'\n```" text = "Intro text\n\n" + code + "\n\nOutro text" result = formatter.format_response(text, max_length=2000, split_on_code_blocks=True) # Code block should be intact in one of the chunks full_text = "".join(result) assert "```python\ndef hello():\n return 'world'\n```" in full_text class TestEdgeCases: """Test edge cases and error handling.""" def test_single_code_block_exactly_max_length(self): """Code block exactly at max_length is handled.""" formatter = ResponseFormatter() # Create code block that's exactly 2000 chars including markers code_content = "x" * (2000 - len("```python\n\n```")) text = f"```python\n{code_content}\n```" result = formatter.format_response(text, max_length=2000) assert len(result) == 1 assert len(result[0]) <= 2000 def test_consecutive_code_blocks(self): """Multiple consecutive code blocks are preserved.""" formatter = ResponseFormatter() text = """```python code1 = 1 ``` ```javascript code2 = 2 ``` ```bash code3 = 3 ```""" result = formatter.format_response(text) full_text = " ".join(result) assert "```python" in full_text assert "```javascript" in full_text assert "```bash" in full_text def test_very_long_single_word(self): """Single word longer than max_length is force-split.""" formatter = ResponseFormatter() text = "a" * 2500 # Single "word" with no spaces result = formatter.format_response(text, max_length=2000) assert len(result) == 2 assert len(result[0]) == 2000 assert len(result[1]) == 500 def test_custom_max_length(self): """Custom max_length parameter is respected.""" formatter = ResponseFormatter() text = "word " * 300 # ~1500 chars result = formatter.format_response(text, max_length=500) # Should split into multiple chunks assert len(result) >= 3 for chunk in result: assert len(chunk) <= 500 class TestHelperMethods: """Test existing helper methods still work.""" def test_format_code_block_with_language(self): """format_code_block() creates proper code block.""" formatter = ResponseFormatter() result = formatter.format_code_block("print('test')", "python") assert result == "```python\nprint('test')\n```" def test_format_code_block_without_language(self): """format_code_block() works without language.""" formatter = ResponseFormatter() result = formatter.format_code_block("some code") assert result == "```\nsome code\n```" def test_format_error(self): """format_error() creates proper error message.""" formatter = ResponseFormatter() result = formatter.format_error("Something went wrong") assert ":warning:" in result assert "Error:" in result assert "Something went wrong" in result assert "```" in result def test_chunk_response_basic(self): """chunk_response() splits on line boundaries.""" formatter = ResponseFormatter() text = "line1\nline2\nline3\n" + ("x" * 2000) result = formatter.chunk_response(text, max_length=2000) assert len(result) >= 2 for chunk in result: assert len(chunk) <= 2000