mirror of
https://github.com/rookiestar28/ComfyUI-OpenClaw.git
synced 2026-08-14 00:48:07 +00:00
165 lines
5.5 KiB
Python
165 lines
5.5 KiB
Python
import asyncio
|
|
import unittest
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
from connector.config import ConnectorConfig
|
|
from connector.contract import Platform
|
|
from connector.results_poller import ResultsPoller
|
|
|
|
|
|
class MockPlatform(Platform):
|
|
async def send_image(
|
|
self,
|
|
channel_id,
|
|
image_data,
|
|
filename="image.png",
|
|
caption=None,
|
|
delivery_context=None,
|
|
):
|
|
pass
|
|
|
|
async def send_message(self, channel_id, text, delivery_context=None):
|
|
pass
|
|
|
|
|
|
class TestResultsPoller(unittest.TestCase):
|
|
def setUp(self):
|
|
self.config = ConnectorConfig()
|
|
self.config.delivery_timeout_sec = 5 # short timeout for tests
|
|
|
|
self.client = MagicMock()
|
|
self.client.get_history = AsyncMock()
|
|
self.client.get_view = AsyncMock()
|
|
|
|
self.mock_platform = MockPlatform()
|
|
self.mock_platform.send_image = AsyncMock()
|
|
self.mock_platform.send_message = AsyncMock()
|
|
|
|
self.platforms = {"test_plat": self.mock_platform}
|
|
self.poller = ResultsPoller(self.config, self.client, self.platforms)
|
|
|
|
def test_track_job(self):
|
|
self.poller.track_job("p-1", "test_plat", "c-1", "u-1")
|
|
self.assertEqual(self.poller.queue.qsize(), 1)
|
|
item = self.poller.queue.get_nowait()
|
|
self.assertEqual(item, ("p-1", "test_plat", "c-1", "u-1", {}))
|
|
|
|
@patch("connector.results_poller.time")
|
|
@patch("connector.results_poller.asyncio.sleep", new_callable=AsyncMock)
|
|
def test_poll_job_success(self, mock_sleep, mock_time):
|
|
mock_time.time.side_effect = [0, 1, 2, 3]
|
|
|
|
self.client.get_history.side_effect = [
|
|
{"ok": True, "data": {}},
|
|
{
|
|
"ok": True,
|
|
"data": {
|
|
"p-1": {
|
|
"outputs": {
|
|
"node-1": {
|
|
"images": [{"filename": "f.png", "type": "output"}]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
},
|
|
]
|
|
|
|
self.client.get_view.return_value = b"image_bytes"
|
|
|
|
asyncio.run(
|
|
self.poller._poll_job(
|
|
"p-1",
|
|
"test_plat",
|
|
"c-1",
|
|
"u-1",
|
|
{"workspace_id": "T1", "thread_id": "123.456"},
|
|
)
|
|
)
|
|
|
|
self.assertEqual(self.client.get_history.call_count, 2)
|
|
self.client.get_view.assert_called_with("f.png", "", "output")
|
|
self.mock_platform.send_image.assert_called_with(
|
|
"c-1",
|
|
b"image_bytes",
|
|
filename="f.png",
|
|
delivery_context={"workspace_id": "T1", "thread_id": "123.456"},
|
|
)
|
|
|
|
@patch("connector.results_poller.time")
|
|
@patch("connector.results_poller.asyncio.sleep", new_callable=AsyncMock)
|
|
def test_poll_job_no_outputs(self, mock_sleep, mock_time):
|
|
# Scenario: Job finished, but "outputs" is empty or has no images.
|
|
mock_time.time.side_effect = [0, 1, 2]
|
|
|
|
self.client.get_history.side_effect = [
|
|
{
|
|
"ok": True,
|
|
"data": {"p-empty": {"outputs": {}}},
|
|
} # Completed, empty outputs
|
|
]
|
|
|
|
asyncio.run(self.poller._poll_job("p-empty", "test_plat", "c-1", "u-1"))
|
|
|
|
self.mock_platform.send_image.assert_not_called()
|
|
self.mock_platform.send_message.assert_called_once()
|
|
args = self.mock_platform.send_message.call_args
|
|
self.assertIn("No output images", args[0][1])
|
|
|
|
@patch("connector.results_poller.time")
|
|
@patch("connector.results_poller.asyncio.sleep", new_callable=AsyncMock)
|
|
def test_poll_job_timeout(self, mock_sleep, mock_time):
|
|
self.config.delivery_timeout_sec = 2
|
|
mock_time.time.side_effect = [0, 1, 3]
|
|
|
|
self.client.get_history.return_value = {"ok": True, "data": {}}
|
|
|
|
asyncio.run(self.poller._poll_job("p-timeout", "test_plat", "c-1", "u-1"))
|
|
|
|
self.mock_platform.send_image.assert_not_called()
|
|
self.mock_platform.send_message.assert_called_once()
|
|
self.assertIn("timed out", self.mock_platform.send_message.call_args[0][1])
|
|
|
|
def test_deliver_results_limits(self):
|
|
self.config.delivery_max_images = 1
|
|
|
|
job_data = {
|
|
"outputs": {
|
|
"n1": {
|
|
"images": [
|
|
{"filename": "1.png", "type": "output"},
|
|
{"filename": "2.png", "type": "output"},
|
|
]
|
|
}
|
|
}
|
|
}
|
|
self.client.get_view.return_value = b"123"
|
|
|
|
asyncio.run(self.poller._deliver_results("p-1", job_data, "test_plat", "c-1"))
|
|
|
|
self.assertEqual(self.mock_platform.send_image.call_count, 1)
|
|
args = self.mock_platform.send_image.call_args
|
|
self.assertEqual(args[1]["filename"], "1.png")
|
|
|
|
def test_deliver_results_send_failure(self):
|
|
# Scenario: Platform.send_image raises Exception
|
|
job_data = {
|
|
"outputs": {"n1": {"images": [{"filename": "f.png", "type": "output"}]}}
|
|
}
|
|
self.client.get_view.return_value = b"bytes"
|
|
self.mock_platform.send_image.side_effect = Exception("Network Error")
|
|
|
|
asyncio.run(
|
|
self.poller._deliver_results("p-fail", job_data, "test_plat", "c-1")
|
|
)
|
|
|
|
# Should catch exception and try sending fallback text
|
|
self.mock_platform.send_message.assert_called()
|
|
self.assertIn(
|
|
"Failed to send image", self.mock_platform.send_message.call_args[0][1]
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|