Files
mcp-maildir/tests/test_server.py
T

163 lines
5.8 KiB
Python
Raw Normal View History

"""Unit tests for mcp-maildir server pure functions."""
import os
os.environ["QDRANT_URL"] = "http://localhost:6333"
os.environ["COLLECTION_NAME"] = "test"
from server import (
normalize_email_address,
payload_matches_participant,
format_search_result,
build_filter,
)
class TestNormalizeEmailAddress:
def test_empty_value(self):
assert normalize_email_address("") == ""
assert normalize_email_address(None) == ""
def test_simple_email(self):
assert normalize_email_address("user@example.com") == "user@example.com"
def test_display_name_with_email(self):
assert normalize_email_address("John Doe <john@example.com>") == "john@example.com"
def test_whitespace_and_case(self):
assert normalize_email_address(" USER@Example.COM ") == "user@example.com"
def test_invalid_email_fallback(self):
result = normalize_email_address("not-an-email")
# Returns stripped lowercase version of the input
assert result == "not-an-email"
class TestPayloadMatchesParticipant:
def test_sender_match_normalized(self):
payload = {"sender": "alice@example.com"}
assert payload_matches_participant(payload, "alice@example.com") is True
def test_receiver_match_normalized(self):
payload = {"receiver": "bob@example.com"}
assert payload_matches_participant(payload, "bob@example.com") is True
def test_sender_raw_match(self):
payload = {"sender_raw": "alice@other.com"}
assert payload_matches_participant(payload, "alice@other.com") is True
def test_no_match(self):
payload = {"sender": "alice@example.com", "receiver": "bob@example.com"}
assert payload_matches_participant(payload, "carol@example.com") is False
def test_display_name_in_sender(self):
payload = {"sender": "Alice <alice@example.com>"}
assert payload_matches_participant(payload, "alice@example.com") is True
def test_display_name_in_receiver(self):
payload = {"receiver": "Bob Smith <bob@example.com>"}
assert payload_matches_participant(payload, "bob@example.com") is True
def test_empty_payload(self):
assert payload_matches_participant({}, "someone@example.com") is False
def test_case_insensitive(self):
payload = {"sender": "ALICE@EXAMPLE.COM"}
assert payload_matches_participant(payload, "alice@example.com") is True
class TestFormatSearchResult:
def test_basic_formatting(self):
class MockPoint:
payload = {
"message_id": "<abc@def>",
"date": "2026-01-15T10:00:00",
"sender": "alice@example.com",
"receiver": "bob@example.com",
"subject": "Hello",
"attachments": ["file.pdf"],
}
score = 0.95
result = format_search_result(MockPoint())
assert result["message_id"] == "<abc@def>"
assert result["date"] == "2026-01-15T10:00:00"
assert result["sender"] == "alice@example.com"
assert result["receiver"] == "bob@example.com"
assert result["subject"] == "Hello"
assert result["attachments"] == ["file.pdf"]
assert result["score"] == 0.95
def test_empty_payload(self):
class MockPoint:
payload = None
score = None
result = format_search_result(MockPoint())
assert result["message_id"] is None
assert result["score"] is None
assert result["attachments"] == []
def test_missing_fields(self):
class MockPoint:
payload = {"message_id": "<123>"}
score = 0.5
result = format_search_result(MockPoint())
assert result["message_id"] == "<123>"
assert result["date"] is None
assert result["sender"] is None
assert result["receiver"] is None
assert result["subject"] is None
assert result["attachments"] == []
class TestBuildFilter:
def test_no_filters_returns_none(self):
assert build_filter(None, None, None) is None
def test_empty_strings_return_none(self):
assert build_filter("", "", "") is None
def test_participant_filter_is_should_clause_on_sender_and_receiver(self):
f = build_filter("alice@example.com", None, None)
assert f is not None
# The date conditions list must be absent and only the participant filter present
assert len(f.must) == 1
participant = f.must[0]
keys = [c.key for c in participant.should]
assert keys == ["sender", "receiver"]
assert all(c.match.value == "alice@example.com" for c in participant.should)
def test_participant_normalized_before_match(self):
f = build_filter("Alice <Alice@Example.COM>", None, None)
should = f.must[0].should
assert all(c.match.value == "alice@example.com" for c in should)
def test_date_range_only(self):
f = build_filter(None, "2026-01-01", "2026-06-30")
assert len(f.must) == 1
cond = f.must[0]
assert cond.key == "date"
assert cond.range.gte is not None
assert cond.range.lte is not None
def test_start_date_only(self):
f = build_filter(None, "2026-03-15", None)
cond = f.must[0]
assert cond.range.gte is not None
assert cond.range.lte is None
def test_end_date_only(self):
f = build_filter(None, None, "2026-03-15")
cond = f.must[0]
assert cond.range.gte is None
assert cond.range.lte is not None
def test_combined_participant_and_date(self):
f = build_filter("bob@example.org", "2026-01-01", "2026-12-31")
assert len(f.must) == 2
# One is the participant should-filter, the other the date range
kinds = sorted(
"participant" if getattr(c, "should", None) else "date" for c in f.must
)
assert kinds == ["date", "participant"]