| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- import unittest
- from unittest.mock import MagicMock, patch, AsyncMock
- import asyncio
- import json
- from app.services.forum_scheduler import ForumScheduler
- from app.agent.agent import ModeratorAgent
- class TestStreamRobustness(unittest.IsolatedAsyncioTestCase):
- async def test_moderator_stream_fields(self):
- """
- Verify that moderator streaming broadcasts include stream_id and moderator_id.
- """
- scheduler = ForumScheduler()
-
- # Mock DB and objects
- mock_db = MagicMock()
- mock_forum = MagicMock()
- mock_forum.id = 1
- mock_forum.moderator_id = 99
- mock_forum.summary_history = []
-
- # Mock get_forum to return our mock forum
- # We need to patch 'app.services.forum_scheduler.get_forum'
-
- # Mock ModeratorAgent to return a generator
- mock_moderator = MagicMock(spec=ModeratorAgent)
- mock_moderator.name = "TestHost"
-
- def mock_opening(guests):
- yield "Hello"
- yield " World"
-
- # Patch dependencies
- with patch('app.services.forum_scheduler.get_forum', return_value=mock_forum), \
- patch('app.services.forum_scheduler.create_message') as mock_create_msg, \
- patch('app.services.forum_scheduler.update_forum'), \
- patch('app.services.forum_scheduler.manager') as mock_manager, \
- patch.object(scheduler, '_is_forum_running', return_value=True), \
- patch('asyncio.to_thread', side_effect=lambda func, *args: func(*args)) as mock_to_thread:
-
- # Make broadcast awaitable
- mock_manager.broadcast = AsyncMock()
-
- # Setup moderator mock methods
- mock_moderator.opening = mock_opening
-
- # Run _moderator_speak
- # We assume asyncio.to_thread executes the function immediately for this test
- mock_create_msg.return_value.id = 1
- await scheduler._moderator_speak(1, mock_moderator, "opening", guests=[])
-
- # Verify broadcasts
- calls = mock_manager.broadcast.call_args_list
- chunk_calls = [call for call in calls if call[0][1]['type'] == 'message_chunk']
- message_calls = [call for call in calls if call[0][1]['type'] == 'new_message']
- speech_logs = [
- call for call in calls
- if call[0][1]['type'] == 'system_log'
- and call[0][1]['data']['level'] == 'speech'
- ]
- self.assertEqual(len(chunk_calls), 2)
- self.assertEqual(len(message_calls), 1)
- self.assertGreaterEqual(len(speech_logs), 1)
- # Check that stream_id and moderator_id are present in chunks
- # First call: Chunk 1
- call_args_1 = chunk_calls[0]
- payload_1 = call_args_1[0][1]
- self.assertEqual(payload_1['type'], 'message_chunk')
- self.assertIn('stream_id', payload_1['data'])
- self.assertEqual(payload_1['data']['moderator_id'], 99)
- call_args_msg = message_calls[0]
- payload_msg = call_args_msg[0][1]
- self.assertEqual(payload_msg['type'], 'new_message')
- self.assertIn('stream_id', payload_msg['data'])
- self.assertEqual(payload_msg['data']['moderator_id'], 99)
- if __name__ == '__main__':
- unittest.main()
|