robosystems-client 0.1.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of robosystems-client might be problematic. Click here for more details.

Files changed (282) hide show
  1. robosystems_client/__init__.py +14 -0
  2. robosystems_client/api/__init__.py +1 -0
  3. robosystems_client/api/agent/__init__.py +1 -0
  4. robosystems_client/api/agent/query_financial_agent.py +423 -0
  5. robosystems_client/api/auth/__init__.py +1 -0
  6. robosystems_client/api/auth/check_password_strength.py +172 -0
  7. robosystems_client/api/auth/complete_sso_auth.py +177 -0
  8. robosystems_client/api/auth/generate_sso_token.py +174 -0
  9. robosystems_client/api/auth/get_captcha_config.py +87 -0
  10. robosystems_client/api/auth/get_current_auth_user.py +220 -0
  11. robosystems_client/api/auth/get_password_policy.py +134 -0
  12. robosystems_client/api/auth/login_user.py +181 -0
  13. robosystems_client/api/auth/logout_user.py +169 -0
  14. robosystems_client/api/auth/refresh_session.py +174 -0
  15. robosystems_client/api/auth/register_user.py +189 -0
  16. robosystems_client/api/auth/sso_login.py +177 -0
  17. robosystems_client/api/auth/sso_token_exchange.py +181 -0
  18. robosystems_client/api/backup/__init__.py +1 -0
  19. robosystems_client/api/backup/create_backup.py +401 -0
  20. robosystems_client/api/backup/export_backup.py +225 -0
  21. robosystems_client/api/backup/get_backup_download_url.py +258 -0
  22. robosystems_client/api/backup/get_backup_stats.py +182 -0
  23. robosystems_client/api/backup/kuzu_backup_health.py +202 -0
  24. robosystems_client/api/backup/list_backups.py +217 -0
  25. robosystems_client/api/backup/restore_backup.py +401 -0
  26. robosystems_client/api/billing/__init__.py +1 -0
  27. robosystems_client/api/billing/get_available_subscription_plans_v1_graph_id_billing_available_plans_get.py +198 -0
  28. robosystems_client/api/billing/get_credit_billing_info_v1_graph_id_billing_credits_get.py +210 -0
  29. robosystems_client/api/billing/get_current_graph_bill.py +285 -0
  30. robosystems_client/api/billing/get_graph_billing_history.py +329 -0
  31. robosystems_client/api/billing/get_graph_monthly_bill.py +315 -0
  32. robosystems_client/api/billing/get_graph_pricing_info_v1_graph_id_billing_pricing_get.py +198 -0
  33. robosystems_client/api/billing/get_graph_subscription_v1_graph_id_billing_subscription_get.py +198 -0
  34. robosystems_client/api/billing/get_graph_usage_details.py +350 -0
  35. robosystems_client/api/billing/upgrade_graph_subscription_v1_graph_id_billing_subscription_upgrade_post.py +216 -0
  36. robosystems_client/api/connections/__init__.py +1 -0
  37. robosystems_client/api/connections/create_connection.py +327 -0
  38. robosystems_client/api/connections/create_link_token.py +281 -0
  39. robosystems_client/api/connections/delete_connection.py +278 -0
  40. robosystems_client/api/connections/exchange_link_token.py +301 -0
  41. robosystems_client/api/connections/get_connection.py +262 -0
  42. robosystems_client/api/connections/get_connection_options.py +285 -0
  43. robosystems_client/api/connections/init_o_auth.py +230 -0
  44. robosystems_client/api/connections/list_connections.py +314 -0
  45. robosystems_client/api/connections/oauth_callback.py +318 -0
  46. robosystems_client/api/connections/sync_connection.py +362 -0
  47. robosystems_client/api/create/__init__.py +1 -0
  48. robosystems_client/api/create/create_graph.py +375 -0
  49. robosystems_client/api/create/get_available_extensions.py +134 -0
  50. robosystems_client/api/credits_/__init__.py +1 -0
  51. robosystems_client/api/credits_/check_credit_balance.py +299 -0
  52. robosystems_client/api/credits_/check_storage_limits.py +249 -0
  53. robosystems_client/api/credits_/get_credit_summary.py +245 -0
  54. robosystems_client/api/credits_/get_storage_usage.py +279 -0
  55. robosystems_client/api/credits_/list_credit_transactions.py +392 -0
  56. robosystems_client/api/graph_analytics/__init__.py +1 -0
  57. robosystems_client/api/graph_analytics/get_graph_metrics.py +285 -0
  58. robosystems_client/api/graph_analytics/get_graph_usage_stats.py +329 -0
  59. robosystems_client/api/graph_status/__init__.py +1 -0
  60. robosystems_client/api/graph_status/get_database_health.py +273 -0
  61. robosystems_client/api/graph_status/get_database_info.py +277 -0
  62. robosystems_client/api/mcp/__init__.py +1 -0
  63. robosystems_client/api/mcp/call_mcp_tool.py +432 -0
  64. robosystems_client/api/mcp/list_mcp_tools.py +265 -0
  65. robosystems_client/api/operations/__init__.py +1 -0
  66. robosystems_client/api/operations/cancel_operation.py +246 -0
  67. robosystems_client/api/operations/get_operation_status.py +273 -0
  68. robosystems_client/api/operations/stream_operation_events.py +415 -0
  69. robosystems_client/api/query/__init__.py +1 -0
  70. robosystems_client/api/query/execute_cypher_query.py +482 -0
  71. robosystems_client/api/schema/__init__.py +1 -0
  72. robosystems_client/api/schema/export_graph_schema.py +239 -0
  73. robosystems_client/api/schema/get_graph_schema_info.py +277 -0
  74. robosystems_client/api/schema/list_schema_extensions.py +216 -0
  75. robosystems_client/api/schema/validate_schema.py +326 -0
  76. robosystems_client/api/service_offerings/__init__.py +1 -0
  77. robosystems_client/api/service_offerings/get_service_offerings.py +197 -0
  78. robosystems_client/api/status/__init__.py +1 -0
  79. robosystems_client/api/status/get_mcp_health.py +136 -0
  80. robosystems_client/api/status/get_service_status.py +134 -0
  81. robosystems_client/api/user/__init__.py +1 -0
  82. robosystems_client/api/user/create_user_api_key.py +205 -0
  83. robosystems_client/api/user/get_all_credit_summaries.py +256 -0
  84. robosystems_client/api/user/get_current_user.py +187 -0
  85. robosystems_client/api/user/get_user_graphs.py +187 -0
  86. robosystems_client/api/user/list_user_api_keys.py +187 -0
  87. robosystems_client/api/user/revoke_user_api_key.py +209 -0
  88. robosystems_client/api/user/select_user_graph.py +213 -0
  89. robosystems_client/api/user/update_user.py +205 -0
  90. robosystems_client/api/user/update_user_api_key.py +218 -0
  91. robosystems_client/api/user/update_user_password.py +218 -0
  92. robosystems_client/api/user_analytics/__init__.py +1 -0
  93. robosystems_client/api/user_analytics/get_detailed_user_analytics.py +222 -0
  94. robosystems_client/api/user_analytics/get_user_usage_overview.py +187 -0
  95. robosystems_client/api/user_limits/__init__.py +1 -0
  96. robosystems_client/api/user_limits/get_user_limits.py +190 -0
  97. robosystems_client/api/user_limits/get_user_usage.py +187 -0
  98. robosystems_client/api/user_subscriptions/__init__.py +1 -0
  99. robosystems_client/api/user_subscriptions/cancel_shared_repository_subscription.py +209 -0
  100. robosystems_client/api/user_subscriptions/get_repository_credits.py +206 -0
  101. robosystems_client/api/user_subscriptions/get_shared_repository_credits.py +193 -0
  102. robosystems_client/api/user_subscriptions/get_user_shared_subscriptions.py +213 -0
  103. robosystems_client/api/user_subscriptions/subscribe_to_shared_repository.py +214 -0
  104. robosystems_client/api/user_subscriptions/upgrade_shared_repository_subscription.py +228 -0
  105. robosystems_client/client.py +278 -0
  106. robosystems_client/errors.py +16 -0
  107. robosystems_client/extensions/README.md +611 -0
  108. robosystems_client/extensions/__init__.py +108 -0
  109. robosystems_client/extensions/auth_integration.py +210 -0
  110. robosystems_client/extensions/extensions.py +170 -0
  111. robosystems_client/extensions/operation_client.py +368 -0
  112. robosystems_client/extensions/query_client.py +375 -0
  113. robosystems_client/extensions/sse_client.py +520 -0
  114. robosystems_client/extensions/tests/__init__.py +1 -0
  115. robosystems_client/extensions/tests/test_integration.py +490 -0
  116. robosystems_client/extensions/tests/test_unit.py +560 -0
  117. robosystems_client/extensions/utils.py +526 -0
  118. robosystems_client/models/__init__.py +379 -0
  119. robosystems_client/models/account_info.py +79 -0
  120. robosystems_client/models/add_on_credit_info.py +119 -0
  121. robosystems_client/models/agent_message.py +68 -0
  122. robosystems_client/models/agent_request.py +132 -0
  123. robosystems_client/models/agent_request_context_type_0.py +44 -0
  124. robosystems_client/models/agent_response.py +132 -0
  125. robosystems_client/models/agent_response_metadata_type_0.py +44 -0
  126. robosystems_client/models/api_key_info.py +134 -0
  127. robosystems_client/models/api_keys_response.py +74 -0
  128. robosystems_client/models/auth_response.py +82 -0
  129. robosystems_client/models/auth_response_user.py +44 -0
  130. robosystems_client/models/available_extension.py +78 -0
  131. robosystems_client/models/available_extensions_response.py +73 -0
  132. robosystems_client/models/backup_create_request.py +117 -0
  133. robosystems_client/models/backup_export_request.py +72 -0
  134. robosystems_client/models/backup_list_response.py +90 -0
  135. robosystems_client/models/backup_response.py +200 -0
  136. robosystems_client/models/backup_restore_request.py +81 -0
  137. robosystems_client/models/backup_stats_response.py +156 -0
  138. robosystems_client/models/backup_stats_response_backup_formats.py +44 -0
  139. robosystems_client/models/cancel_operation_response_canceloperation.py +44 -0
  140. robosystems_client/models/cancellation_response.py +76 -0
  141. robosystems_client/models/check_credit_balance_response_checkcreditbalance.py +44 -0
  142. robosystems_client/models/connection_options_response.py +82 -0
  143. robosystems_client/models/connection_provider_info.py +203 -0
  144. robosystems_client/models/connection_provider_info_auth_type.py +11 -0
  145. robosystems_client/models/connection_provider_info_provider.py +10 -0
  146. robosystems_client/models/connection_response.py +149 -0
  147. robosystems_client/models/connection_response_metadata.py +44 -0
  148. robosystems_client/models/connection_response_provider.py +10 -0
  149. robosystems_client/models/create_api_key_request.py +82 -0
  150. robosystems_client/models/create_api_key_response.py +74 -0
  151. robosystems_client/models/create_connection_request.py +179 -0
  152. robosystems_client/models/create_connection_request_provider.py +10 -0
  153. robosystems_client/models/create_graph_request.py +183 -0
  154. robosystems_client/models/credit_check_request.py +82 -0
  155. robosystems_client/models/credit_summary.py +128 -0
  156. robosystems_client/models/credit_summary_response.py +140 -0
  157. robosystems_client/models/credits_summary_response.py +122 -0
  158. robosystems_client/models/credits_summary_response_credits_by_addon_item.py +44 -0
  159. robosystems_client/models/custom_schema_definition.py +194 -0
  160. robosystems_client/models/custom_schema_definition_metadata.py +49 -0
  161. robosystems_client/models/custom_schema_definition_nodes_item.py +44 -0
  162. robosystems_client/models/custom_schema_definition_relationships_item.py +44 -0
  163. robosystems_client/models/cypher_query_request.py +128 -0
  164. robosystems_client/models/cypher_query_request_parameters_type_0.py +44 -0
  165. robosystems_client/models/database_health_response.py +181 -0
  166. robosystems_client/models/database_info_response.py +191 -0
  167. robosystems_client/models/detailed_transactions_response.py +124 -0
  168. robosystems_client/models/detailed_transactions_response_date_range.py +44 -0
  169. robosystems_client/models/detailed_transactions_response_summary.py +59 -0
  170. robosystems_client/models/enhanced_credit_transaction_response.py +192 -0
  171. robosystems_client/models/enhanced_credit_transaction_response_metadata.py +44 -0
  172. robosystems_client/models/error_response.py +145 -0
  173. robosystems_client/models/exchange_token_request.py +116 -0
  174. robosystems_client/models/exchange_token_request_metadata_type_0.py +44 -0
  175. robosystems_client/models/get_all_credit_summaries_response_getallcreditsummaries.py +44 -0
  176. robosystems_client/models/get_backup_download_url_response_getbackupdownloadurl.py +44 -0
  177. robosystems_client/models/get_current_auth_user_response_getcurrentauthuser.py +44 -0
  178. robosystems_client/models/get_current_graph_bill_response_getcurrentgraphbill.py +44 -0
  179. robosystems_client/models/get_graph_billing_history_response_getgraphbillinghistory.py +44 -0
  180. robosystems_client/models/get_graph_monthly_bill_response_getgraphmonthlybill.py +44 -0
  181. robosystems_client/models/get_graph_schema_info_response_getgraphschemainfo.py +44 -0
  182. robosystems_client/models/get_graph_usage_details_response_getgraphusagedetails.py +44 -0
  183. robosystems_client/models/get_mcp_health_response_getmcphealth.py +44 -0
  184. robosystems_client/models/get_operation_status_response_getoperationstatus.py +44 -0
  185. robosystems_client/models/get_storage_usage_response_getstorageusage.py +44 -0
  186. robosystems_client/models/graph_info.py +92 -0
  187. robosystems_client/models/graph_metadata.py +105 -0
  188. robosystems_client/models/graph_metrics_response.py +188 -0
  189. robosystems_client/models/graph_metrics_response_estimated_size.py +44 -0
  190. robosystems_client/models/graph_metrics_response_health_status.py +44 -0
  191. robosystems_client/models/graph_metrics_response_node_counts.py +44 -0
  192. robosystems_client/models/graph_metrics_response_relationship_counts.py +44 -0
  193. robosystems_client/models/graph_usage_response.py +116 -0
  194. robosystems_client/models/graph_usage_response_query_statistics.py +44 -0
  195. robosystems_client/models/graph_usage_response_recent_activity.py +44 -0
  196. robosystems_client/models/graph_usage_response_storage_usage.py +44 -0
  197. robosystems_client/models/health_status.py +110 -0
  198. robosystems_client/models/health_status_details_type_0.py +44 -0
  199. robosystems_client/models/http_validation_error.py +75 -0
  200. robosystems_client/models/initial_entity_data.py +212 -0
  201. robosystems_client/models/kuzu_backup_health_response_kuzubackuphealth.py +44 -0
  202. robosystems_client/models/link_token_request.py +174 -0
  203. robosystems_client/models/link_token_request_options_type_0.py +44 -0
  204. robosystems_client/models/link_token_request_provider_type_0.py +10 -0
  205. robosystems_client/models/list_connections_provider_type_0.py +10 -0
  206. robosystems_client/models/list_schema_extensions_response_listschemaextensions.py +44 -0
  207. robosystems_client/models/login_request.py +68 -0
  208. robosystems_client/models/logout_user_response_logoutuser.py +44 -0
  209. robosystems_client/models/mcp_tool_call.py +84 -0
  210. robosystems_client/models/mcp_tool_call_arguments.py +44 -0
  211. robosystems_client/models/mcp_tools_response.py +74 -0
  212. robosystems_client/models/mcp_tools_response_tools_item.py +44 -0
  213. robosystems_client/models/o_auth_callback_request.py +130 -0
  214. robosystems_client/models/o_auth_init_request.py +128 -0
  215. robosystems_client/models/o_auth_init_request_additional_params_type_0.py +44 -0
  216. robosystems_client/models/o_auth_init_response.py +78 -0
  217. robosystems_client/models/password_check_request.py +82 -0
  218. robosystems_client/models/password_check_response.py +112 -0
  219. robosystems_client/models/password_check_response_character_types.py +44 -0
  220. robosystems_client/models/password_policy_response.py +66 -0
  221. robosystems_client/models/password_policy_response_policy.py +44 -0
  222. robosystems_client/models/plaid_connection_config.py +209 -0
  223. robosystems_client/models/plaid_connection_config_accounts_type_0_item.py +44 -0
  224. robosystems_client/models/plaid_connection_config_institution_type_0.py +44 -0
  225. robosystems_client/models/quick_books_connection_config.py +92 -0
  226. robosystems_client/models/register_request.py +98 -0
  227. robosystems_client/models/repository_credits_response.py +101 -0
  228. robosystems_client/models/repository_plan.py +10 -0
  229. robosystems_client/models/repository_type.py +10 -0
  230. robosystems_client/models/response_mode.py +11 -0
  231. robosystems_client/models/schema_export_response.py +163 -0
  232. robosystems_client/models/schema_export_response_data_stats_type_0.py +44 -0
  233. robosystems_client/models/schema_export_response_schema_definition_type_0.py +44 -0
  234. robosystems_client/models/schema_validation_request.py +142 -0
  235. robosystems_client/models/schema_validation_request_schema_definition_type_0.py +44 -0
  236. robosystems_client/models/schema_validation_response.py +227 -0
  237. robosystems_client/models/schema_validation_response_compatibility_type_0.py +44 -0
  238. robosystems_client/models/schema_validation_response_stats_type_0.py +44 -0
  239. robosystems_client/models/sec_connection_config.py +82 -0
  240. robosystems_client/models/sso_complete_request.py +60 -0
  241. robosystems_client/models/sso_exchange_request.py +90 -0
  242. robosystems_client/models/sso_exchange_response.py +78 -0
  243. robosystems_client/models/sso_login_request.py +60 -0
  244. robosystems_client/models/sso_token_response.py +78 -0
  245. robosystems_client/models/storage_limit_response.py +149 -0
  246. robosystems_client/models/subscription_info.py +180 -0
  247. robosystems_client/models/subscription_info_metadata.py +44 -0
  248. robosystems_client/models/subscription_request.py +89 -0
  249. robosystems_client/models/subscription_response.py +82 -0
  250. robosystems_client/models/success_response.py +112 -0
  251. robosystems_client/models/success_response_data_type_0.py +44 -0
  252. robosystems_client/models/sync_connection_request.py +106 -0
  253. robosystems_client/models/sync_connection_request_sync_options_type_0.py +44 -0
  254. robosystems_client/models/sync_connection_response_syncconnection.py +44 -0
  255. robosystems_client/models/tier_upgrade_request.py +62 -0
  256. robosystems_client/models/transaction_summary_response.py +126 -0
  257. robosystems_client/models/update_api_key_request.py +92 -0
  258. robosystems_client/models/update_password_request.py +76 -0
  259. robosystems_client/models/update_user_request.py +92 -0
  260. robosystems_client/models/upgrade_subscription_request.py +82 -0
  261. robosystems_client/models/user_analytics_response.py +132 -0
  262. robosystems_client/models/user_analytics_response_api_usage.py +44 -0
  263. robosystems_client/models/user_analytics_response_graph_usage.py +44 -0
  264. robosystems_client/models/user_analytics_response_limits.py +44 -0
  265. robosystems_client/models/user_analytics_response_recent_activity_item.py +44 -0
  266. robosystems_client/models/user_analytics_response_user_info.py +44 -0
  267. robosystems_client/models/user_graph_summary.py +134 -0
  268. robosystems_client/models/user_graphs_response.py +96 -0
  269. robosystems_client/models/user_limits_response.py +95 -0
  270. robosystems_client/models/user_response.py +132 -0
  271. robosystems_client/models/user_subscriptions_response.py +90 -0
  272. robosystems_client/models/user_usage_response.py +90 -0
  273. robosystems_client/models/user_usage_response_graphs.py +44 -0
  274. robosystems_client/models/user_usage_summary_response.py +130 -0
  275. robosystems_client/models/user_usage_summary_response_usage_vs_limits.py +44 -0
  276. robosystems_client/models/validation_error.py +88 -0
  277. robosystems_client/py.typed +1 -0
  278. robosystems_client/sdk-config.yaml +5 -0
  279. robosystems_client/types.py +54 -0
  280. robosystems_client-0.1.9.dist-info/METADATA +302 -0
  281. robosystems_client-0.1.9.dist-info/RECORD +282 -0
  282. robosystems_client-0.1.9.dist-info/WHEEL +4 -0
@@ -0,0 +1,490 @@
1
+ """Integration Tests for RoboSystems SDK Extensions
2
+
3
+ These tests demonstrate real usage patterns and verify the extensions work correctly
4
+ with the generated SDK.
5
+ """
6
+
7
+ import pytest
8
+ import time
9
+ from unittest.mock import Mock, patch
10
+ from datetime import datetime
11
+
12
+ # Import extensions
13
+ from robosystems_client.extensions import (
14
+ RoboSystemsExtensionConfig,
15
+ QueryBuilder,
16
+ CacheManager,
17
+ ProgressTracker,
18
+ AuthenticatedExtensions,
19
+ create_extensions,
20
+ SSEClient,
21
+ SSEConfig,
22
+ EventType,
23
+ QueryClient,
24
+ estimate_query_cost,
25
+ validate_cypher_query,
26
+ format_duration,
27
+ )
28
+
29
+
30
+ class TestAuthenticatedIntegration:
31
+ """Test authenticated extensions integration"""
32
+
33
+ @pytest.fixture
34
+ def mock_api_key(self):
35
+ return "test_api_key_12345"
36
+
37
+ @pytest.fixture
38
+ def extensions(self, mock_api_key):
39
+ return AuthenticatedExtensions(
40
+ api_key=mock_api_key,
41
+ config=RoboSystemsExtensionConfig(
42
+ base_url="https://api.test.robosystems.ai", timeout=30
43
+ ),
44
+ )
45
+
46
+ def test_authenticated_extensions_initialization(self, extensions, mock_api_key):
47
+ """Test that authenticated extensions initialize correctly"""
48
+ assert extensions.config["base_url"] == "https://api.test.robosystems.ai"
49
+ assert extensions.config["headers"]["X-API-Key"] == mock_api_key
50
+ assert extensions.config["headers"]["Authorization"] == f"Bearer {mock_api_key}"
51
+
52
+ def test_create_extensions_factory(self, mock_api_key):
53
+ """Test the extensions factory function"""
54
+ # API Key method
55
+ ext = create_extensions(
56
+ "api_key", api_key=mock_api_key, base_url="https://api.test.robosystems.ai"
57
+ )
58
+ assert isinstance(ext, AuthenticatedExtensions)
59
+
60
+ # Cookie method
61
+ ext = create_extensions(
62
+ "cookie",
63
+ cookies={"auth-token": "cookie_token"},
64
+ base_url="https://api.test.robosystems.ai",
65
+ )
66
+ assert ext.config["base_url"] == "https://api.test.robosystems.ai"
67
+
68
+ # Token method
69
+ ext = create_extensions(
70
+ "token", token="jwt_token_here", base_url="https://api.test.robosystems.ai"
71
+ )
72
+ assert ext.config["headers"]["Authorization"] == "Bearer jwt_token_here"
73
+
74
+ @patch("robosystems_client.extensions.auth_integration.sync_detailed")
75
+ def test_cypher_query_execution(self, mock_sync_detailed, extensions):
76
+ """Test executing Cypher queries through authenticated client"""
77
+ # Mock the response
78
+ mock_response = Mock()
79
+ mock_response.parsed = Mock()
80
+ mock_response.parsed.data = [{"name": "Company A", "revenue": 1000000}]
81
+ mock_response.parsed.columns = ["name", "revenue"]
82
+ mock_response.parsed.row_count = 1
83
+ mock_response.parsed.execution_time_ms = 150
84
+ mock_sync_detailed.return_value = mock_response
85
+
86
+ result = extensions.execute_cypher_query(
87
+ graph_id="test_graph",
88
+ query="MATCH (c:Company) RETURN c.name, c.revenue",
89
+ parameters={"limit": 10},
90
+ )
91
+
92
+ assert result["data"] == [{"name": "Company A", "revenue": 1000000}]
93
+ assert result["columns"] == ["name", "revenue"]
94
+ assert result["row_count"] == 1
95
+ assert result["execution_time_ms"] == 150
96
+
97
+ # Verify the SDK was called correctly
98
+ mock_sync_detailed.assert_called_once()
99
+
100
+
101
+ class TestSSEIntegration:
102
+ """Test SSE client integration"""
103
+
104
+ @pytest.fixture
105
+ def sse_config(self):
106
+ return SSEConfig(
107
+ base_url="https://api.test.robosystems.ai", max_retries=2, timeout=10
108
+ )
109
+
110
+ @pytest.fixture
111
+ def sse_client(self, sse_config):
112
+ return SSEClient(sse_config)
113
+
114
+ def test_sse_event_parsing(self, sse_client):
115
+ """Test proper SSE event parsing according to specification"""
116
+ events_received = []
117
+
118
+ def event_handler(data):
119
+ events_received.append(data)
120
+
121
+ sse_client.on(EventType.OPERATION_PROGRESS.value, event_handler)
122
+
123
+ # Test multiline event parsing
124
+ event_buffer = {
125
+ "event": "operation_progress",
126
+ "data": ['{"message": "Step 1 complete"}', '{"percentage": 25}'],
127
+ "id": "123",
128
+ "retry": None,
129
+ }
130
+
131
+ sse_client._dispatch_event(event_buffer)
132
+
133
+ # Should receive the parsed event
134
+ assert len(events_received) == 1
135
+ # Note: Real SSE data would be joined with newlines, this tests the parsing logic
136
+
137
+ def test_sse_connection_management(self, sse_client):
138
+ """Test SSE connection lifecycle"""
139
+ assert not sse_client.is_connected()
140
+
141
+ # Test event listener registration
142
+ handler = Mock()
143
+ sse_client.on("test_event", handler)
144
+
145
+ # Test event emission
146
+ sse_client.emit("test_event", {"test": "data"})
147
+ handler.assert_called_once_with({"test": "data"})
148
+
149
+ # Test cleanup
150
+ sse_client.close()
151
+ assert sse_client.closed
152
+
153
+
154
+ class TestQueryIntegration:
155
+ """Test query client integration"""
156
+
157
+ @pytest.fixture
158
+ def query_client(self):
159
+ return QueryClient({"base_url": "https://api.test.robosystems.ai"})
160
+
161
+ def test_query_builder_integration(self):
162
+ """Test QueryBuilder creates valid queries"""
163
+ builder = QueryBuilder()
164
+ query, params = (
165
+ builder.match("(c:Company)")
166
+ .where("c.revenue > $min_revenue")
167
+ .return_("c.name", "c.revenue")
168
+ .limit(10)
169
+ .with_param("min_revenue", 100000)
170
+ .build()
171
+ )
172
+
173
+ # Validate the query
174
+ validation = validate_cypher_query(query)
175
+ assert validation["valid"]
176
+
177
+ # Estimate cost
178
+ cost = estimate_query_cost(query, params)
179
+ assert cost["complexity_category"] in ["low", "medium", "high", "very_high"]
180
+ assert cost["complexity_score"] > 0
181
+
182
+ # Test parameters
183
+ assert params["min_revenue"] == 100000
184
+
185
+ def test_query_validation_integration(self):
186
+ """Test query validation with various query types"""
187
+ test_cases = [
188
+ # Valid queries
189
+ ("MATCH (n) RETURN n", True),
190
+ ("MATCH (c:Company) WHERE c.revenue > 1000 RETURN c.name", True),
191
+ ("CREATE (n:Test) RETURN n", True),
192
+ # Invalid queries
193
+ ("MATCH (n RETURN n", False), # Missing closing parenthesis
194
+ ("", False), # Empty query
195
+ ("MATCH [n] RETURN n", False), # Wrong bracket type
196
+ ]
197
+
198
+ for query, should_be_valid in test_cases:
199
+ result = validate_cypher_query(query)
200
+ assert result["valid"] == should_be_valid, f"Query '{query}' validation failed"
201
+
202
+ def test_query_cost_estimation_accuracy(self):
203
+ """Test query cost estimation provides reasonable results"""
204
+ queries = [
205
+ # Simple query - should be low cost
206
+ ("MATCH (n:Company) RETURN n.name LIMIT 10", "low"),
207
+ # Complex query - should be higher cost
208
+ (
209
+ "MATCH (c:Company)-[:HAS_TRANSACTION]->(t:Transaction) "
210
+ + "WHERE c.revenue > 1000000 "
211
+ + "WITH c, COUNT(t) as tx_count "
212
+ + "ORDER BY tx_count DESC "
213
+ + "RETURN c.name, tx_count",
214
+ "high",
215
+ ),
216
+ # Very complex query
217
+ (
218
+ "MATCH (c:Company)-[:HAS_TRANSACTION]->(t:Transaction) "
219
+ + "MATCH (c)-[:LOCATED_IN]->(l:Location) "
220
+ + "MATCH (c)-[:HAS_SUBSIDIARY]->(s:Company) "
221
+ + "WHERE c.revenue > 1000000 AND t.amount > 10000 "
222
+ + "WITH c, l, COUNT(t) as tx_count, SUM(t.amount) as total_amount, "
223
+ + " AVG(t.amount) as avg_amount, MAX(t.amount) as max_amount "
224
+ + "ORDER BY total_amount DESC, tx_count DESC "
225
+ + "RETURN c.name, l.city, tx_count, total_amount, avg_amount",
226
+ "very_high",
227
+ ),
228
+ ]
229
+
230
+ for query, expected_complexity in queries:
231
+ result = estimate_query_cost(query)
232
+ actual_complexity = result["complexity_category"]
233
+
234
+ # Allow some flexibility in complexity categorization
235
+ complexity_levels = ["low", "medium", "high", "very_high"]
236
+ expected_idx = complexity_levels.index(expected_complexity)
237
+ actual_idx = complexity_levels.index(actual_complexity)
238
+
239
+ # Should be within 1 level of expected
240
+ assert abs(actual_idx - expected_idx) <= 1, (
241
+ f"Query complexity mismatch: expected {expected_complexity}, got {actual_complexity}"
242
+ )
243
+
244
+
245
+ class TestCacheIntegration:
246
+ """Test cache manager integration"""
247
+
248
+ @pytest.fixture
249
+ def cache_manager(self):
250
+ return CacheManager(max_size=10, ttl_seconds=5)
251
+
252
+ def test_cache_lifecycle(self, cache_manager):
253
+ """Test complete cache lifecycle"""
254
+ graph_id = "test_graph"
255
+ query = "MATCH (n:Company) RETURN COUNT(n)"
256
+
257
+ # Cache miss initially
258
+ result = cache_manager.get(graph_id, query)
259
+ assert result is None
260
+
261
+ # Store result
262
+ test_result = {"count": 100, "execution_time_ms": 50}
263
+ cache_manager.set(graph_id, query, test_result)
264
+
265
+ # Cache hit
266
+ cached_result = cache_manager.get(graph_id, query)
267
+ assert cached_result == test_result
268
+
269
+ # Test with parameters
270
+ query_with_params = (
271
+ "MATCH (n:Company) WHERE n.revenue > $min_revenue RETURN COUNT(n)"
272
+ )
273
+ params = {"min_revenue": 100000}
274
+
275
+ cache_manager.set(graph_id, query_with_params, test_result, params)
276
+ cached_with_params = cache_manager.get(graph_id, query_with_params, params)
277
+ assert cached_with_params == test_result
278
+
279
+ # Different parameters should be cache miss
280
+ different_params = {"min_revenue": 200000}
281
+ cache_miss = cache_manager.get(graph_id, query_with_params, different_params)
282
+ assert cache_miss is None
283
+
284
+ def test_cache_eviction(self, cache_manager):
285
+ """Test LRU eviction works correctly"""
286
+ # Fill cache to capacity
287
+ for i in range(10):
288
+ cache_manager.set(f"graph_{i}", f"query_{i}", f"result_{i}")
289
+
290
+ assert len(cache_manager.cache) == 10
291
+
292
+ # Access first few items to make them recently used
293
+ for i in range(3):
294
+ cache_manager.get(f"graph_{i}", f"query_{i}")
295
+
296
+ # Add one more item - should evict least recently used
297
+ cache_manager.set("graph_new", "query_new", "result_new")
298
+
299
+ assert len(cache_manager.cache) == 10 # Still at max capacity
300
+
301
+ # Recently accessed items should still be there
302
+ assert cache_manager.get("graph_0", "query_0") == "result_0"
303
+ assert cache_manager.get("graph_1", "query_1") == "result_1"
304
+ assert cache_manager.get("graph_2", "query_2") == "result_2"
305
+
306
+ # New item should be there
307
+ assert cache_manager.get("graph_new", "query_new") == "result_new"
308
+
309
+ def test_cache_expiration(self, cache_manager):
310
+ """Test cache TTL expiration"""
311
+ graph_id = "test_graph"
312
+ query = "MATCH (n) RETURN COUNT(n)"
313
+ result = {"count": 50}
314
+
315
+ # Store with short TTL
316
+ cache_manager.set(graph_id, query, result)
317
+
318
+ # Should be available immediately
319
+ assert cache_manager.get(graph_id, query) == result
320
+
321
+ # Wait for expiration (TTL is 5 seconds in fixture)
322
+ time.sleep(6)
323
+
324
+ # Should be expired now
325
+ expired_result = cache_manager.get(graph_id, query)
326
+ assert expired_result is None
327
+
328
+
329
+ class TestProgressTracking:
330
+ """Test progress tracking integration"""
331
+
332
+ def test_progress_tracker_lifecycle(self):
333
+ """Test complete progress tracking"""
334
+ operation_id = "test_operation_123"
335
+ tracker = ProgressTracker(operation_id)
336
+ tracker.set_total_steps(5)
337
+
338
+ # Simulate progress updates
339
+ steps = [
340
+ ("Initializing...", 0),
341
+ ("Loading data...", 20),
342
+ ("Processing...", 60),
343
+ ("Finalizing...", 90),
344
+ ("Complete", 100),
345
+ ]
346
+
347
+ for i, (message, percentage) in enumerate(steps, 1):
348
+ tracker.update(message, percentage, step=i)
349
+ time.sleep(0.1) # Small delay to see time progression
350
+
351
+ # Verify final state
352
+ summary = tracker.get_summary()
353
+ assert summary["operation_id"] == operation_id
354
+ assert summary["current_step"] == 5
355
+ assert summary["total_steps"] == 5
356
+ assert summary["latest_message"] == "Complete"
357
+ assert summary["percentage_complete"] == 100
358
+ assert summary["total_updates"] == 5
359
+
360
+ # Check elapsed time is reasonable
361
+ elapsed_time = tracker.get_elapsed_time()
362
+ assert elapsed_time.total_seconds() >= 0.5 # At least the sleep time
363
+
364
+ def test_estimated_completion(self):
365
+ """Test progress estimation"""
366
+ tracker = ProgressTracker("test_op")
367
+
368
+ # No estimation without progress
369
+ assert tracker.get_estimated_completion() is None
370
+
371
+ # Add progress
372
+ tracker.update("50% complete", 50.0)
373
+
374
+ # Should have an estimation now
375
+ estimation = tracker.get_estimated_completion()
376
+ assert estimation is not None
377
+ assert isinstance(estimation, datetime)
378
+
379
+
380
+ class TestUtilityIntegration:
381
+ """Test utility function integration"""
382
+
383
+ def test_duration_formatting(self):
384
+ """Test duration formatting utility"""
385
+ test_cases = [(100, "100ms"), (1500, "1.5s"), (65000, "1m 5s"), (3661000, "1h 1m")]
386
+
387
+ for ms, expected in test_cases:
388
+ result = format_duration(ms)
389
+ assert result == expected, (
390
+ f"Duration {ms}ms formatted as '{result}', expected '{expected}'"
391
+ )
392
+
393
+ def test_end_to_end_query_workflow(self):
394
+ """Test complete query workflow with utilities"""
395
+ # Build query
396
+ builder = QueryBuilder()
397
+ query, params = (
398
+ builder.match("(c:Company)-[:LOCATED_IN]->(l:Location)")
399
+ .where("c.revenue > $min_revenue")
400
+ .where("l.country = $country")
401
+ .return_("c.name", "c.revenue", "l.city")
402
+ .order_by("c.revenue DESC")
403
+ .limit(25)
404
+ .with_param("min_revenue", 1000000)
405
+ .with_param("country", "USA")
406
+ .build()
407
+ )
408
+
409
+ # Validate query
410
+ validation = validate_cypher_query(query)
411
+ assert validation["valid"], f"Generated query is invalid: {validation['issues']}"
412
+
413
+ # Estimate cost
414
+ cost = estimate_query_cost(query, params)
415
+ assert cost["complexity_score"] > 0
416
+ assert len(cost["cost_factors"]) > 0
417
+
418
+ # Cache the estimated result
419
+ cache = CacheManager()
420
+ mock_result = {
421
+ "data": [{"name": "TechCorp", "revenue": 5000000, "city": "San Francisco"}],
422
+ "columns": ["name", "revenue", "city"],
423
+ "row_count": 1,
424
+ "execution_time_ms": 250,
425
+ }
426
+
427
+ cache.set("production_graph", query, mock_result, params)
428
+
429
+ # Retrieve from cache
430
+ cached = cache.get("production_graph", query, params)
431
+ assert cached == mock_result
432
+
433
+ # Test execution time formatting
434
+ formatted_time = format_duration(mock_result["execution_time_ms"])
435
+ assert formatted_time == "250ms"
436
+
437
+
438
+ # Integration test runner
439
+ def run_integration_tests():
440
+ """Run all integration tests manually (for environments without pytest)"""
441
+ print("Running RoboSystems SDK Extensions Integration Tests...")
442
+
443
+ # Test classes to run
444
+ test_classes = [
445
+ TestAuthenticatedIntegration(),
446
+ TestSSEIntegration(),
447
+ TestQueryIntegration(),
448
+ TestCacheIntegration(),
449
+ TestProgressTracking(),
450
+ TestUtilityIntegration(),
451
+ ]
452
+
453
+ total_tests = 0
454
+ passed_tests = 0
455
+
456
+ for test_instance in test_classes:
457
+ class_name = test_instance.__class__.__name__
458
+ print(f"\n--- {class_name} ---")
459
+
460
+ # Get all test methods
461
+ test_methods = [
462
+ method
463
+ for method in dir(test_instance)
464
+ if method.startswith("test_") and callable(getattr(test_instance, method))
465
+ ]
466
+
467
+ for method_name in test_methods:
468
+ total_tests += 1
469
+ try:
470
+ # Create fixtures if needed
471
+ if hasattr(test_instance, "mock_api_key"):
472
+ test_instance.mock_api_key = lambda: "test_key_123"
473
+
474
+ # Run the test
475
+ test_method = getattr(test_instance, method_name)
476
+ test_method()
477
+
478
+ print(f" ✓ {method_name}")
479
+ passed_tests += 1
480
+
481
+ except Exception as e:
482
+ print(f" ✗ {method_name}: {e}")
483
+
484
+ print(f"\nIntegration Tests Completed: {passed_tests}/{total_tests} passed")
485
+ return passed_tests == total_tests
486
+
487
+
488
+ if __name__ == "__main__":
489
+ success = run_integration_tests()
490
+ exit(0 if success else 1)