import sys import os import unittest from unittest.mock import MagicMock, patch import json # Mock Gradio before importing app sys.modules['gradio'] = MagicMock() sys.modules['gradio'].__version__ = "4.0.0" # Mock other dependencies that might cause issues in this environment sys.modules['plotly.graph_objects'] = MagicMock() # Import app import app class TestUIFix(unittest.TestCase): def setUp(self): # Mock the trading AI and its components app.trading_ai = MagicMock() app.trading_ai.analyze_and_trade.return_value = { 'market_data': {'price': 150.0, 'change_24h': 5.0, 'rsi': 60}, 'ai_decision': {'action': 'LONG', 'confidence': 0.8, 'reason': 'Test reason'}, 'execution_result': {'status': 'Executed'}, 'portfolio_status': {'paper_balance': 10000}, 'learning_stats': {}, 'active_positions': [] } app.trading_ai.get_market_data.return_value = {'price': 150.0, 'change_24h': 5.0} app.trading_ai.learner.thinking_log = [{'decision': {'action': 'LONG', 'confidence': 0.8, 'reason': 'Test reason'}}] app.trading_ai.learner.last_api_input = "Test Input" app.trading_ai.learner.last_api_output = "Test Output" # Mock portfolio manager app.trading_ai.portfolio.position_manager.active_positions = { 'pos1': { 'symbol': 'SOL/USD', 'action': 'LONG', 'entry_price': 140.0, 'current_price': 150.0, 'unrealized_pnl_percent': 7.14, 'unrealized_pnl': 50.0, 'size_percent': 10 } } app.trading_ai.portfolio.position_manager.closed_positions = [] app.trading_ai.portfolio.real_wallet.get_balance_info.return_value = { 'wallet_balance_sol': 10.0, 'trading_balance_sol': 5.0, 'estimated_usd_value': 1500.0 } app.trading_ai.portfolio.update_all_positions.return_value = {'paper_balance': 10000} app.trading_ai.portfolio.get_portfolio_status.return_value = {'paper_balance': 10000} # Mock create_closed_positions_table app.create_closed_positions_table = MagicMock(return_value=[]) def test_autonomous_trade_cycle_return_types(self): # Create interface to trigger the definition of the function demo = app.create_interface() # Get the function passed to demo.load # demo.load is a mock, so we can check call_args # The call is demo.load(fn=autonomous_trade_cycle, ...) # We need to find the call to load # Since demo is the return value of create_interface, and create_interface returns 'demo' which is a MagicMock (from gr.Blocks context manager) # We need to see how gr.Blocks works in the mock. # with gr.Blocks() as demo: -> demo is the context manager's enter return value. # Let's assume app.create_interface returns the mock object that .load was called on. # We need to inspect the calls to that mock. # In app.py: # with gr.Blocks(...) as demo: # ... # demo.load(...) # return demo # So 'demo' returned by create_interface IS the mock that .load was called on. # Find the call to load load_call = None for call in demo.load.call_args_list: if 'fn' in call.kwargs: load_call = call break # If passed as positional arg, fn is the first one if len(call.args) > 0: load_call = call break if not load_call: self.fail("Could not find call to demo.load") # Get the function autonomous_trade_cycle = load_call.kwargs.get('fn') or load_call.args[0] # Run the cycle outputs = autonomous_trade_cycle('SOL/USD', 'PAPER') # Unpack outputs (there should be 11) ( thinking_text, market_price, ai_confidence, ai_action, ai_reason, last_execution, portfolio_status, active_positions_table, closed_positions_table, wallet_info, system_logs ) = outputs print("Verifying outputs...") # Check types self.assertIsInstance(last_execution, dict, "last_execution should be a dict, not a string") self.assertIsInstance(portfolio_status, dict, "portfolio_status should be a dict, not a string") self.assertIsInstance(wallet_info, str, "wallet_info should be a string (Markdown)") # Check for HF Logo in active positions print(f"Active Positions Table: {active_positions_table}") self.assertTrue(len(active_positions_table) > 0, "Should have active positions") self.assertIn("huggingface_logo", active_positions_table[0][0], "First column should contain HF logo URL") if __name__ == '__main__': unittest.main()