"""Tests for protocol_muse package.""" import os import sys import unittest from unittest.mock import patch, MagicMock REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) PKG_DIR = os.path.join(REPO_ROOT, "packages", "protocol-muse") if PKG_DIR not in sys.path: sys.path.insert(0, PKG_DIR) import protocol_muse from protocol_muse import MuseClient, QueueSnapshot, TaskItem, NoiseGateway, GatewayFallback class TestProtocolMuse(unittest.TestCase): def test_version_and_exports(self): self.assertEqual(protocol_muse.__version__, "0.1.0") self.assertIsNotNone(MuseClient) self.assertIsNotNone(QueueSnapshot) def test_queue_snapshot_from_dict(self): data = { "ok": True, "tasks": [ {"name": "001-task.md", "queue": "pending", "owner": None, "age_s": 12.5}, {"name": "002-claimed.md.opm", "queue": "claimed", "owner": "opm", "age_s": 5.0}, {"name": "003-done.md", "queue": "done", "owner": "646", "age_s": 100.0}, ], "counts": {"pending": 1, "claimed": 1, "done": 1} } snap = QueueSnapshot.from_dict(data) self.assertTrue(snap.ok) self.assertEqual(len(snap.tasks), 3) self.assertEqual(snap.pending_count, 1) self.assertEqual(snap.claimed_count, 1) self.assertEqual(snap.done_count, 1) self.assertEqual(snap.tasks[1].owner, "opm") @patch("urllib.request.urlopen") def test_gateway_fallback_health(self, mock_urlopen): mock_resp = MagicMock() mock_resp.read.return_value = b'{"status": "ok", "ops": ["chat.send"]}' mock_resp.__enter__.return_value = mock_resp mock_urlopen.return_value = mock_resp fb = GatewayFallback(endpoint="https://mock.gateway:8445", token="test-token") res = fb.check_health() self.assertEqual(res.get("status"), "ok") @patch("urllib.request.urlopen") def test_gateway_fallback_queue(self, mock_urlopen): mock_resp = MagicMock() mock_resp.read.return_value = b'{"ok": true, "tasks": [], "counts": {"pending": 0, "claimed": 0, "done": 0}}' mock_resp.__enter__.return_value = mock_resp mock_urlopen.return_value = mock_resp fb = GatewayFallback(endpoint="https://mock.gateway:8445", token="test-token") res = fb.get_queue() self.assertTrue(res.get("ok")) self.assertEqual(res.get("counts", {}).get("pending"), 0) @patch.object(NoiseGateway, "list_threads") def test_muse_client_list_threads_primary(self, mock_list): mock_list.return_value = ([{"id": "t1", "title": "Test Thread"}], None) client = MuseClient(node="pip") threads = client.list_threads() self.assertEqual(len(threads), 1) self.assertEqual(threads[0]["id"], "t1") @patch.object(NoiseGateway, "send_message") def test_muse_client_send_message_primary(self, mock_send): mock_send.return_value = ({"ok": True, "msg_id": "m1"}, None) client = MuseClient(node="646") res = client.send_message("Testing send") self.assertTrue(res.get("ok")) self.assertEqual(res.get("msg_id"), "m1") @patch.object(GatewayFallback, "get_queue") def test_muse_client_get_queue(self, mock_get_q): mock_get_q.return_value = { "ok": True, "tasks": [{"name": "task-1.md", "queue": "pending"}], "counts": {"pending": 1, "claimed": 0, "done": 0} } client = MuseClient(node="opm") snap = client.get_queue() self.assertTrue(snap.ok) self.assertEqual(snap.pending_count, 1) if __name__ == "__main__": unittest.main()