from __future__ import annotations import asyncio import unittest from isphere_ai_bridge import real_lab class RealLoggedInLabTests(unittest.TestCase): def test_plan_tree_reports_ready_and_blocked_phases(self) -> None: tree = real_lab.plan_tree() self.assertEqual("real-loggedin-planning", tree["mode"]) self.assertEqual("A", tree["phases"][0]["id"]) self.assertEqual("ready-now", tree["phases"][0]["status"]) self.assertTrue( any(phase["status"] == "blocked-waiting-real-data" for phase in tree["phases"]) ) def test_required_files_checklist_has_expected_sections(self) -> None: checklist = real_lab.required_files_checklist() section_ids = {section["id"] for section in checklist["sections"]} self.assertTrue({"install_dir", "user_data", "logged_in_window"}.issubset(section_ids)) self.assertEqual("copy-later", checklist["recommended_timing"]) def test_action_contract_requires_approval_for_send_and_file_upload(self) -> None: contract = real_lab.action_contract() actions = {action["name"]: action for action in contract["actions"]} self.assertFalse(actions["real_lab_search_contacts"]["requires_approval"]) self.assertTrue(actions["real_lab_send_after_approval"]["requires_approval"]) self.assertTrue(actions["real_lab_send_file_after_approval"]["requires_approval"]) self.assertEqual("no-login-automation", contract["hard_limits"][0]) def test_status_and_scan_windows_are_structured_without_real_client(self) -> None: status = real_lab.status() scan = real_lab.scan_windows() self.assertIn("ready", status) self.assertIn("process_candidates", status) self.assertIn("next_step", status) self.assertIn("windows", scan) self.assertIn("next_step", scan) def test_win_helper_version_and_self_check_are_structured(self) -> None: built = real_lab.build_win_helper() self.assertTrue(built["ok"], built) version = real_lab.win_helper_version() self.assertTrue(version["ok"], version) self.assertEqual("version", version["op"]) self.assertEqual("ISphereWinHelper", version["data"]["helper_name"]) self_check = real_lab.win_helper_self_check() self.assertTrue(self_check["ok"], self_check) self.assertEqual("self_check", self_check["op"]) self.assertIn("uia_available", self_check["data"]) def test_win_helper_scan_and_missing_uia_dump_are_structured(self) -> None: built = real_lab.build_win_helper() self.assertTrue(built["ok"], built) scan = real_lab.win_helper_scan_windows(include_all_visible=True) self.assertTrue(scan["ok"], scan) self.assertEqual("scan_windows", scan["op"]) self.assertIsInstance(scan["data"]["windows"], list) dump = real_lab.win_helper_dump_uia("0x0") self.assertFalse(dump["ok"], dump) self.assertIn(dump["error"]["code"], {"WINDOW_NOT_FOUND", "UIA_DUMP_FAILED"}) def test_real_lab_tools_are_registered(self) -> None: from isphere_ai_bridge.server import mcp names = [tool.name for tool in asyncio.run(mcp.list_tools())] required = { "real_lab_plan_tree", "real_lab_required_files", "real_lab_action_contract", "real_lab_status", "real_lab_scan_windows", "real_lab_win_helper_version", "real_lab_win_helper_self_check", "real_lab_win_helper_scan_windows", "real_lab_win_helper_dump_uia", } self.assertTrue(required.issubset(set(names))) if __name__ == "__main__": unittest.main()