import unittest from datetime import datetime, timezone from app.features.conversation.models import Conversation from app.features.conversation.service import ( _build_messages_from_history, _latest_message_time_ms, _message_timestamp_ms, ) class ConversationMessagesHistoryTest(unittest.TestCase): def test_build_messages_collapses_audio_segments_from_same_voice_session(self): history = [ { "role": "human", "content": "第一段", "messageType": "audio", "voiceSessionId": "voice-1", "timestamp": "2026-03-14T12:00:01+00:00", }, { "role": "ai", "content": "继续说", "messageType": "text", "timestamp": "2026-03-14T12:00:02+00:00", }, { "role": "human", "content": "第二段", "messageType": "audio", "voiceSessionId": "voice-1", "timestamp": "2026-03-14T12:00:03+00:00", }, { "role": "ai", "content": "我记住了", "messageType": "text", "timestamp": "2026-03-14T12:00:04+00:00", }, ] messages = _build_messages_from_history( conversation_id="conv-1", history=history, fallback_timestamp=datetime(2026, 3, 14, 12, 0, 0, tzinfo=timezone.utc), ) self.assertEqual( [ (msg["senderType"], msg["messageType"], msg["content"]) for msg in messages ], [ ("user", "audio", "第一段"), ("assistant", "text", "继续说"), ("assistant", "text", "我记住了"), ], ) self.assertEqual(messages[0]["timestamp"], 1773489601000) self.assertEqual(messages[0]["voiceSessionId"], "voice-1") self.assertEqual(messages[1]["timestamp"], 1773489602000) self.assertEqual(messages[2]["timestamp"], 1773489604000) def test_build_messages_keeps_distinct_voice_sessions_separate(self): history = [ { "role": "human", "content": "第一次录音", "messageType": "audio", "voiceSessionId": "voice-1", "timestamp": "2026-03-14T12:00:01+00:00", }, { "role": "human", "content": "第二次录音", "messageType": "audio", "voiceSessionId": "voice-2", "timestamp": "2026-03-14T12:00:02+00:00", }, ] messages = _build_messages_from_history( conversation_id="conv-1", history=history, fallback_timestamp=datetime(2026, 3, 14, 12, 0, 0, tzinfo=timezone.utc), ) self.assertEqual(len(messages), 2) self.assertEqual(messages[0]["messageType"], "audio") self.assertEqual(messages[0]["content"], "第一次录音") self.assertEqual(messages[0]["voiceSessionId"], "voice-1") self.assertEqual(messages[1]["messageType"], "audio") self.assertEqual(messages[1]["content"], "第二次录音") self.assertEqual(messages[1]["voiceSessionId"], "voice-2") def test_build_messages_includes_duration_seconds_from_history(self): history = [ { "role": "human", "content": "你好", "messageType": "audio", "voiceSessionId": "vs-a", "durationSeconds": 8, "timestamp": "2026-03-14T12:00:01+00:00", }, ] messages = _build_messages_from_history( conversation_id="conv-1", history=history, fallback_timestamp=datetime(2026, 3, 14, 12, 0, 0, tzinfo=timezone.utc), ) self.assertEqual(len(messages), 1) self.assertEqual(messages[0]["durationSeconds"], 8) def test_latest_message_time_prefers_conversation_last_message_at(self): conversation = Conversation( id="conv-1", user_id="user-1", started_at=datetime(2026, 3, 9, 12, 0, 0, tzinfo=timezone.utc), last_message_at=datetime(2026, 3, 14, 12, 0, 5, tzinfo=timezone.utc), ) history = [ { "role": "human", "content": "旧消息", "messageType": "text", "timestamp": "2026-03-10T12:00:00+00:00", } ] latest_message_time = _latest_message_time_ms(conversation, history) self.assertEqual(latest_message_time, 1773489605000) def test_message_timestamp_falls_back_to_started_at_for_legacy_history(self): conversation = Conversation( id="conv-1", user_id="user-1", started_at=datetime(2026, 3, 14, 12, 0, 0, tzinfo=timezone.utc), ) timestamp = _message_timestamp_ms({}, conversation.started_at) self.assertEqual(timestamp, 1773489600000)