"""Tests for the attributedBody parser."""
import pytest
# Sample attributedBody data captured from real messages
# (with personal content replaced)
SAMPLE_ATTRIBUTED_BODY = (
b'\x04\x0bstreamtyped\x81\xe8\x03\x84\x01@\x84\x84\x84\x12NSAttributedString'
b'\x00\x84\x84\x08NSObject\x00\x85\x92\x84\x84\x84\x08NSString\x01\x94\x84\x01'
b'+\x0cHello World!\x86\x84\x02iI\x01\x0c\x92\x84\x84\x84\x0cNSDictionary'
b'\x00\x94\x84\x01i\x01\x92\x84\x96\x96\x1d__kIMMessagePartAttributeName'
b'\x86\x92\x84\x84\x84\x08NSNumber\x00\x84\x84\x07NSValue\x00\x94\x84\x01*'
b'\x84\x99\x99\x00\x86\x86\x86'
)
# Emoji message
SAMPLE_EMOJI_BODY = (
b'\x04\x0bstreamtyped\x81\xe8\x03\x84\x01@\x84\x84\x84\x12NSAttributedString'
b'\x00\x84\x84\x08NSObject\x00\x85\x92\x84\x84\x84\x08NSString\x01\x94\x84\x01'
b'+\x04\xf0\x9f\x98\x80\x86' # Length 4, followed by 😀 emoji
)
class TestParseAttributedBody:
"""Tests for parse_attributed_body function."""
def test_parse_simple_message(self):
"""Test parsing a simple text message."""
import sys
sys.path.insert(0, 'src')
from jons_mcp_imessage.db.parser import parse_attributed_body
result = parse_attributed_body(SAMPLE_ATTRIBUTED_BODY)
assert result == "Hello World!"
def test_parse_emoji_message(self):
"""Test parsing a message with emoji."""
import sys
sys.path.insert(0, 'src')
from jons_mcp_imessage.db.parser import parse_attributed_body
result = parse_attributed_body(SAMPLE_EMOJI_BODY)
assert result == "😀"
def test_parse_none(self):
"""Test parsing None returns None."""
import sys
sys.path.insert(0, 'src')
from jons_mcp_imessage.db.parser import parse_attributed_body
result = parse_attributed_body(None)
assert result is None
def test_parse_empty(self):
"""Test parsing empty bytes returns None."""
import sys
sys.path.insert(0, 'src')
from jons_mcp_imessage.db.parser import parse_attributed_body
result = parse_attributed_body(b"")
assert result is None
def test_parse_invalid(self):
"""Test parsing invalid data returns None."""
import sys
sys.path.insert(0, 'src')
from jons_mcp_imessage.db.parser import parse_attributed_body
result = parse_attributed_body(b"not a valid attributed body")
assert result is None
class TestParseMessageText:
"""Tests for parse_message_text function."""
def test_prefers_text_column(self):
"""Test that text column is preferred over attributedBody."""
import sys
sys.path.insert(0, 'src')
from jons_mcp_imessage.db.parser import parse_message_text
row = {
"text": "Plain text",
"attributedBody": SAMPLE_ATTRIBUTED_BODY,
}
result = parse_message_text(row)
assert result == "Plain text"
def test_falls_back_to_attributed_body(self):
"""Test fallback to attributedBody when text is None."""
import sys
sys.path.insert(0, 'src')
from jons_mcp_imessage.db.parser import parse_message_text
row = {
"text": None,
"attributedBody": SAMPLE_ATTRIBUTED_BODY,
}
result = parse_message_text(row)
assert result == "Hello World!"
def test_returns_none_when_both_empty(self):
"""Test returns None when both columns are empty."""
import sys
sys.path.insert(0, 'src')
from jons_mcp_imessage.db.parser import parse_message_text
row = {
"text": None,
"attributedBody": None,
}
result = parse_message_text(row)
assert result is None