#!/usr/bin/env python3 """test_settings_rpa.py: Unit tests for Settings RPA substrate.""" import json import sys import unittest from pathlib import Path from unittest.mock import MagicMock, patch REPO_ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(REPO_ROOT / "bin")) from settings_rpa import NodeUsage, SettingsRPA, cdp_dispatch_mouse_click, cdp_send_command class TestSettingsRPAPrimitives(unittest.TestCase): def test_cdp_send_command_matches_id(self): mock_ws = MagicMock() mock_ws.recv.return_value = json.dumps({"id": 10000, "result": {"success": True}}) # Mock _REQ_COUNTER next value with patch("settings_rpa._REQ_COUNTER", iter([10000])): res = cdp_send_command(mock_ws, "Test.method", {"param": 1}) self.assertEqual(res, {"success": True}) mock_ws.send.assert_called_once() sent_msg = json.loads(mock_ws.send.call_args[0][0]) self.assertEqual(sent_msg["method"], "Test.method") def test_cdp_dispatch_mouse_click(self): mock_ws = MagicMock() with patch("settings_rpa.cdp_send_command") as mock_send: mock_send.return_value = {} res = cdp_dispatch_mouse_click(mock_ws, 100.0, 200.0) self.assertTrue(res) self.assertEqual(mock_send.call_count, 2) # Check mousePressed and mouseReleased call_methods = [c[0][1] for c in mock_send.call_args_list] self.assertEqual(call_methods, ["Input.dispatchMouseEvent", "Input.dispatchMouseEvent"]) @patch("settings_rpa.get_cdp_ws") @patch("settings_rpa.cdp_evaluate") def test_settings_dialog_check(self, mock_eval, mock_ws): mock_ws.return_value = (MagicMock(), MagicMock()) mock_eval.return_value = True rpa = SettingsRPA("646") rpa.connect() self.assertTrue(rpa.is_settings_dialog_open()) @patch("settings_rpa.get_cdp_ws") @patch("settings_rpa.cdp_evaluate") def test_read_usage_blocked(self, mock_eval, mock_ws): mock_ws.return_value = (MagicMock(), MagicMock()) # Provide responses: open check (True), tab open check (True), click tab (True), usage dict usage_payload = { "dialogText": "Free plan\nWeekly limit resets on Oct 9\n100% used\nAdditional tokens\n100% used (0 tokens left)", "bars": [ {"label": "Free plan", "percent": 100, "raw_text": "Free plan\nWeekly limit resets on Oct 9\n100% used"}, {"label": "Additional tokens", "percent": 100, "raw_text": "Additional tokens\n100% used (0 tokens left)"}, ], "plan": "Free plan", "resetText": "Weekly limit resets on Oct 9", "tokensLeft": "0 tokens left", } mock_eval.side_effect = [ True, # is_settings_dialog_open True, # is_settings_dialog_open in select_tab True, # click General tab usage_payload, # read_usage evaluation ] with SettingsRPA("646") as rpa: usage = rpa.read_usage(keep_dialog_open=True) self.assertEqual(usage.node, "646") self.assertEqual(usage.weekly_percent_used, 100) self.assertEqual(usage.extra_percent_used, 100) self.assertTrue(usage.is_blocked) self.assertEqual(usage.extra_tokens_remaining, "0 tokens left") self.assertTrue(usage.has_redeemed) @patch("settings_rpa.get_cdp_ws") @patch("settings_rpa.cdp_evaluate") def test_read_usage_not_redeemed(self, mock_eval, mock_ws): mock_ws.return_value = (MagicMock(), MagicMock()) usage_payload = { "dialogText": "Free plan\nWeekly limit resets on Oct 9\n20% used\nRedeem invite code", "bars": [ {"label": "Free plan", "percent": 20, "raw_text": "Free plan\nWeekly limit resets on Oct 9\n20% used"}, ], "plan": "Free plan", "resetText": "Weekly limit resets on Oct 9", "tokensLeft": "", } mock_eval.side_effect = [ True, # is_settings_dialog_open True, # is_settings_dialog_open in select_tab True, # click General tab usage_payload, # read_usage evaluation ] with SettingsRPA("646") as rpa: usage = rpa.read_usage(keep_dialog_open=True) self.assertEqual(usage.node, "646") self.assertEqual(usage.weekly_percent_used, 20) self.assertEqual(usage.extra_percent_used, 0) self.assertFalse(usage.is_blocked) self.assertFalse(usage.has_redeemed) self.assertTrue(usage.stats_loaded) @patch("settings_rpa.get_cdp_ws") @patch("settings_rpa.cdp_evaluate") def test_read_usage_stats_did_not_render(self, mock_eval, mock_ws): mock_ws.return_value = (MagicMock(), MagicMock()) def eval_side_effect(ws, js, *args, **kwargs): if "role=\"dialog\"" in js and "Weekly limit" in js: return None return True mock_eval.side_effect = eval_side_effect with SettingsRPA("646", timeout=0.5) as rpa: # Shorten deadline by patching time.time or passing small timeout with patch("time.sleep", return_value=None): usage = rpa.read_usage(keep_dialog_open=True) self.assertEqual(usage.node, "646") self.assertFalse(usage.stats_loaded) self.assertFalse(usage.is_blocked) self.assertIn("Unavailable", usage.weekly_reset_text) self.assertEqual(usage.extra_tokens_remaining, "Unavailable") if __name__ == "__main__": unittest.main()