File size: 7,434 Bytes
dc893fb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | """Tests for terminal_utils module."""
import pytest
from mini_agent.utils import (
calculate_display_width,
pad_to_width,
truncate_with_ellipsis,
)
class TestCalculateDisplayWidth:
"""Tests for calculate_display_width function."""
def test_ascii_text(self):
"""Test ASCII text width calculation."""
assert calculate_display_width("Hello") == 5
assert calculate_display_width("World") == 5
assert calculate_display_width("Test 123") == 8
def test_empty_string(self):
"""Test empty string."""
assert calculate_display_width("") == 0
def test_emoji(self):
"""Test emoji width (should count as 2)."""
assert calculate_display_width("🤖") == 2
assert calculate_display_width("💭") == 2
assert calculate_display_width("🤖 Agent") == 8 # 2 + 1 + 5
def test_chinese_characters(self):
"""Test Chinese characters (each counts as 2)."""
assert calculate_display_width("你好") == 4
assert calculate_display_width("你好世界") == 8
assert calculate_display_width("中文") == 4
def test_japanese_characters(self):
"""Test Japanese characters."""
assert calculate_display_width("日本語") == 6 # 3 chars * 2
def test_mixed_content(self):
"""Test mixed ASCII and wide characters."""
assert calculate_display_width("Hello 你好") == 10 # 5 + 1 + 4
assert calculate_display_width("Test 🤖") == 7 # 4 + 1 + 2
def test_ansi_codes_ignored(self):
"""Test that ANSI escape codes are not counted."""
colored = "\033[31mRed\033[0m"
assert calculate_display_width(colored) == 3
colored_emoji = "\033[31m🤖\033[0m"
assert calculate_display_width(colored_emoji) == 2
def test_combining_characters(self):
"""Test combining characters (should not add width)."""
# é = e + combining acute accent
e_with_accent = "e\u0301"
assert calculate_display_width(e_with_accent) == 1
def test_complex_ansi_sequences(self):
"""Test complex ANSI sequences."""
text = "\033[1m\033[36mBold Cyan\033[0m"
assert calculate_display_width(text) == 9 # "Bold Cyan"
class TestTruncateWithEllipsis:
"""Tests for truncate_with_ellipsis function."""
def test_no_truncation_needed(self):
"""Test when text fits within width."""
assert truncate_with_ellipsis("Hello", 10) == "Hello"
assert truncate_with_ellipsis("Test", 5) == "Test"
def test_exact_fit(self):
"""Test when text exactly fits."""
assert truncate_with_ellipsis("Hello", 5) == "Hello"
def test_ascii_truncation(self):
"""Test truncation of ASCII text."""
assert truncate_with_ellipsis("Hello World", 8) == "Hello W…"
assert truncate_with_ellipsis("Testing", 4) == "Tes…"
def test_chinese_truncation(self):
"""Test truncation with Chinese characters."""
result = truncate_with_ellipsis("你好世界", 5)
# Should be: 你好 (4 width) + … (1 width) = 5
assert calculate_display_width(result) <= 5
assert "…" in result
def test_emoji_truncation(self):
"""Test truncation with emoji."""
result = truncate_with_ellipsis("🤖🤖🤖", 3)
# Should be: 🤖 (2 width) + … (1 width) = 3
assert calculate_display_width(result) <= 3
def test_zero_width(self):
"""Test with zero width."""
assert truncate_with_ellipsis("Hello", 0) == ""
def test_width_one(self):
"""Test with width of 1."""
result = truncate_with_ellipsis("Hello", 1)
assert len(result) <= 1
def test_ansi_codes_removed(self):
"""Test that ANSI codes are removed during truncation."""
colored = "\033[31mHello World\033[0m"
result = truncate_with_ellipsis(colored, 8)
# ANSI codes should be removed
assert "\033[" not in result
assert "…" in result
class TestPadToWidth:
"""Tests for pad_to_width function."""
def test_left_align(self):
"""Test left alignment (default)."""
result = pad_to_width("Hello", 10)
assert result == "Hello "
assert len(result) == 10
def test_right_align(self):
"""Test right alignment."""
result = pad_to_width("Hello", 10, align="right")
assert result == " Hello"
assert len(result) == 10
def test_center_align(self):
"""Test center alignment."""
result = pad_to_width("Test", 10, align="center")
assert result == " Test "
assert len(result) == 10
def test_center_align_odd(self):
"""Test center alignment with odd padding."""
result = pad_to_width("Hi", 7, align="center")
# Should be: " Hi " or " Hi " (either is acceptable)
assert "Hi" in result
assert len(result) == 7
def test_chinese_padding(self):
"""Test padding with Chinese characters."""
result = pad_to_width("你好", 10)
# "你好" is 4 display width, so needs 6 spaces
assert calculate_display_width(result) == 10
def test_emoji_padding(self):
"""Test padding with emoji."""
result = pad_to_width("🤖", 10)
# "🤖" is 2 display width, so needs 8 spaces
assert calculate_display_width(result) == 10
def test_no_padding_needed(self):
"""Test when text already reaches target width."""
result = pad_to_width("Hello", 5)
assert result == "Hello"
def test_text_exceeds_width(self):
"""Test when text exceeds target width."""
result = pad_to_width("Hello World", 5)
assert result == "Hello World" # No truncation, just return as-is
def test_invalid_align(self):
"""Test invalid alignment value."""
with pytest.raises(ValueError, match="Invalid align value"):
pad_to_width("Test", 10, align="invalid")
def test_custom_fill_char(self):
"""Test custom fill character."""
result = pad_to_width("Test", 10, fill_char="-")
assert result == "Test------"
class TestRealWorldScenarios:
"""Tests for real-world usage scenarios."""
def test_step_header(self):
"""Test Step header formatting (from agent.py)."""
step = 1
max_steps = 50
step_text = f"💭 Step {step}/{max_steps}"
width = calculate_display_width(step_text)
# "💭" (2) + " Step 1/50" (10) = 12
assert width == 12
def test_session_info_model(self):
"""Test Session Info model line."""
model = "minimax-01"
line = f"Model: {model}"
width = calculate_display_width(line)
# Should calculate correctly regardless of model name
assert width > 0
def test_chinese_model_name(self):
"""Test with Chinese model name."""
model = "模型-01"
line = f"Model: {model}"
width = calculate_display_width(line)
# "Model: " (7) + "模型-01" (2+2+3) = 14
assert width == 14
def test_banner_text(self):
"""Test banner text from cli.py."""
banner = "🤖 Mini Agent - Multi-turn Interactive Session"
width = calculate_display_width(banner)
# "🤖" (2) + " Mini Agent - Multi-turn Interactive Session" (44) = 46
assert width == 46
|