-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_reply_behavior.py
More file actions
319 lines (257 loc) · 10.9 KB
/
test_reply_behavior.py
File metadata and controls
319 lines (257 loc) · 10.9 KB
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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#!/usr/bin/env python3
"""
Test the new BOT_REPLY_BEHAVIOR configuration option.
This test validates:
1. Configuration accepts valid reply behavior values (ignore, mention, watch)
2. Configuration rejects invalid reply behavior values
3. Default reply behavior is set correctly
4. Reply behavior is properly logged
"""
import os
import sys
import tempfile
from pathlib import Path
from unittest.mock import MagicMock
# Ensure the src directory is in Python path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
def test_reply_behavior_config():
"""Test reply behavior configuration validation and defaults."""
print("=== Testing Reply Behavior Configuration ===")
# Test valid reply behaviors
valid_behaviors = ["ignore", "mention", "watch"]
for behavior in valid_behaviors:
print(f"Testing valid behavior: {behavior}")
# Set test environment
os.environ["MATRIX_HOMESERVER_URL"] = "https://matrix.test.org"
os.environ["MATRIX_USER_ID"] = "@testbot:matrix.test.org"
os.environ["MATRIX_PASSWORD"] = "test_password"
os.environ["LLM_API_KEY"] = "test_key"
os.environ["BOT_REPLY_BEHAVIOR"] = behavior
try:
from config import Config
# Mock logging to capture output
import logging
# Create a string buffer to capture log messages
log_output = []
original_info = logging.Logger.info
def mock_info(self, msg, *args, **kwargs):
log_output.append(msg % args if args else msg)
original_info(self, msg, *args, **kwargs)
logging.Logger.info = mock_info
config = Config()
# Restore original logging
logging.Logger.info = original_info
assert config.bot_reply_behavior == behavior, f"Expected {behavior}, got {config.bot_reply_behavior}"
# Check that reply behavior is logged
behavior_logged = any(f"Bot reply behavior: {behavior}" in log for log in log_output)
assert behavior_logged, f"Reply behavior {behavior} was not logged"
print(f"✓ Valid behavior '{behavior}' accepted and logged")
except Exception as e:
print(f"✗ Failed for valid behavior '{behavior}': {e}")
return False
finally:
# Clean up environment
if "BOT_REPLY_BEHAVIOR" in os.environ:
del os.environ["BOT_REPLY_BEHAVIOR"]
# Test invalid reply behavior
print("Testing invalid behavior: invalid_mode")
os.environ["BOT_REPLY_BEHAVIOR"] = "invalid_mode"
try:
from config import Config
config = Config()
print("✗ Invalid behavior should have been rejected")
return False
except ValueError as e:
if "Invalid BOT_REPLY_BEHAVIOR" in str(e):
print("✓ Invalid behavior correctly rejected")
else:
print(f"✗ Wrong error message: {e}")
return False
except Exception as e:
print(f"✗ Unexpected error: {e}")
return False
finally:
del os.environ["BOT_REPLY_BEHAVIOR"]
# Test default behavior
print("Testing default behavior")
try:
from config import Config
# Reload the module to clear any cached imports
if 'config' in sys.modules:
del sys.modules['config']
from config import Config
config = Config()
assert config.bot_reply_behavior == "mention", f"Expected default 'mention', got {config.bot_reply_behavior}"
print("✓ Default behavior is 'mention'")
except Exception as e:
print(f"✗ Failed to test default behavior: {e}")
return False
print("🎉 All reply behavior configuration tests passed!")
return True
def test_clean_reply_content():
"""Test the _clean_reply_content method."""
print("\n=== Testing Reply Content Cleaning ===")
# Mock setup for testing the method
import importlib.util
import sys
from pathlib import Path
# Load bot module with absolute import
bot_path = Path(__file__).parent / 'src' / 'bot.py'
spec = importlib.util.spec_from_file_location("bot", bot_path)
bot_module = importlib.util.module_from_spec(spec)
# Add the src directory to sys.path temporarily
src_path = str(Path(__file__).parent / 'src')
if src_path not in sys.path:
sys.path.insert(0, src_path)
try:
spec.loader.exec_module(bot_module)
# Create a minimal config for testing
config_path = Path(__file__).parent / 'src' / 'config.py'
config_spec = importlib.util.spec_from_file_location("config", config_path)
config_module = importlib.util.module_from_spec(config_spec)
config_spec.loader.exec_module(config_module)
config = config_module.Config()
bot = bot_module.AskaosusBot(config)
except Exception as e:
print(f"✗ Failed to setup test environment: {e}")
# Test the cleaning logic directly without the bot class
return test_clean_reply_content_standalone()
finally:
# Remove the src path from sys.path
if src_path in sys.path:
sys.path.remove(src_path)
# Test cases for content cleaning
test_cases = [
{
"input": "@askaosus how do I install Ubuntu?",
"expected": "how do I install Ubuntu?",
"description": "Remove simple mention"
},
{
"input": "> Original message here\n@askaosus what about this?",
"expected": "what about this?",
"description": "Remove quote lines and mention"
},
{
"input": "askaosus please help with this issue",
"expected": "please help with this issue",
"description": "Remove mention without @ symbol"
},
{
"input": " @askaosus help me please ",
"expected": "help me please",
"description": "Clean up extra whitespace"
},
{
"input": "> Quote line 1\n> Quote line 2\nActual question here @askaosus",
"expected": "Actual question here",
"description": "Remove multiple quote lines and mention"
}
]
bot_mentions = ["@askaosus", "askaosus"]
for i, test_case in enumerate(test_cases):
print(f"Test {i+1}: {test_case['description']}")
try:
result = bot._clean_reply_content(test_case["input"], bot_mentions)
if result == test_case["expected"]:
print(f"✓ Input: '{test_case['input']}' -> Output: '{result}'")
else:
print(f"✗ Expected: '{test_case['expected']}', Got: '{result}'")
return False
except Exception as e:
print(f"✗ Error cleaning content: {e}")
return False
print("🎉 All content cleaning tests passed!")
return True
def test_clean_reply_content_standalone():
"""Test content cleaning with standalone implementation."""
import re
def clean_reply_content(message_body: str, bot_mentions: list) -> str:
"""Standalone version of the cleaning function for testing."""
cleaned = message_body
# Remove bot mentions - need to handle @ symbols separately
for mention in bot_mentions:
if mention.startswith('@'):
# For @mentions, remove the whole word
cleaned = re.sub(rf"@{re.escape(mention[1:])}\b", "", cleaned, flags=re.IGNORECASE)
# Also handle the mention without @ in case it's in the list
cleaned = re.sub(rf"\b{re.escape(mention)}\b", "", cleaned, flags=re.IGNORECASE)
# Remove common Matrix reply prefixes (fallback formatting)
lines = cleaned.split('\n')
non_quote_lines = []
for line in lines:
if not line.strip().startswith('> '):
non_quote_lines.append(line)
cleaned = '\n'.join(non_quote_lines).strip()
# Remove extra whitespace
cleaned = re.sub(r'\s+', ' ', cleaned).strip()
return cleaned
print("Testing with standalone implementation...")
test_cases = [
{
"input": "@askaosus how do I install Ubuntu?",
"expected": "how do I install Ubuntu?",
"description": "Remove simple mention"
},
{
"input": "> Original message here\n@askaosus what about this?",
"expected": "what about this?",
"description": "Remove quote lines and mention"
},
{
"input": "askaosus please help with this issue",
"expected": "please help with this issue",
"description": "Remove mention without @ symbol"
},
{
"input": " @askaosus help me please ",
"expected": "help me please",
"description": "Clean up extra whitespace"
},
{
"input": "> Quote line 1\n> Quote line 2\nActual question here @askaosus",
"expected": "Actual question here",
"description": "Remove multiple quote lines and mention"
}
]
bot_mentions = ["@askaosus", "askaosus"]
for i, test_case in enumerate(test_cases):
print(f"Test {i+1}: {test_case['description']}")
try:
result = clean_reply_content(test_case["input"], bot_mentions)
if result == test_case["expected"]:
print(f"✓ Input: '{test_case['input']}' -> Output: '{result}'")
else:
print(f"✗ Expected: '{test_case['expected']}', Got: '{result}'")
return False
except Exception as e:
print(f"✗ Error cleaning content: {e}")
return False
print("🎉 All content cleaning tests passed!")
return True
def main():
"""Run all reply behavior tests."""
print("Testing BOT_REPLY_BEHAVIOR configuration and functionality...\n")
# Clean up environment first
env_vars_to_clean = [
"MATRIX_HOMESERVER_URL", "MATRIX_USER_ID", "MATRIX_PASSWORD",
"LLM_API_KEY", "BOT_REPLY_BEHAVIOR"
]
for var in env_vars_to_clean:
if var in os.environ:
del os.environ[var]
success = True
# Test configuration
if not test_reply_behavior_config():
success = False
# Test content cleaning
if not test_clean_reply_content():
success = False
if success:
print("\n🎉 All reply behavior tests passed!")
return 0
else:
print("\n❌ Some tests failed!")
return 1
if __name__ == "__main__":
sys.exit(main())