1+ import pytest
2+ from unittest .mock import AsyncMock , patch
3+
4+ import asyncio
5+
6+ @pytest .mark .asyncio
7+ async def test_get_all_positions_updates_stats (position_manager , mock_positions_data ):
8+ pm = position_manager
9+ result = await pm .get_all_positions ()
10+ assert len (result ) == len (mock_positions_data )
11+ assert pm .stats ["positions_tracked" ] == len (mock_positions_data )
12+ assert set (pm .tracked_positions .keys ()) == {d ["contractId" ] for d in mock_positions_data }
13+
14+ @pytest .mark .asyncio
15+ async def test_get_position_cache_vs_api (position_manager ):
16+ pm = position_manager
17+
18+ # a) Realtime disabled: should call API
19+ pm ._realtime_enabled = False
20+ with patch .object (pm .project_x , "search_open_positions" , wraps = pm .project_x .search_open_positions ) as mock_search :
21+ pos = await pm .get_position ("MGC" )
22+ assert pos .id
23+ mock_search .assert_called_once ()
24+
25+ # b) Realtime enabled: should use cache only
26+ pm ._realtime_enabled = True
27+ # Prepopulate cache
28+ mgc_pos = await pm .get_position ("MGC" )
29+ pm .tracked_positions ["MGC" ] = mgc_pos
30+ with patch .object (pm .project_x , "search_open_positions" , side_effect = Exception ("Should not be called" )):
31+ pos2 = await pm .get_position ("MGC" )
32+ assert pos2 is pm .tracked_positions ["MGC" ]
33+
34+ @pytest .mark .asyncio
35+ async def test_is_position_open (position_manager ):
36+ pm = position_manager
37+ await pm .get_all_positions ()
38+ assert pm .is_position_open ("MGC" ) is True
39+ assert pm .is_position_open ("UNKNOWN" ) is False
40+ # Simulate closed size
41+ pm .tracked_positions ["MGC" ].size = 0
42+ assert pm .is_position_open ("MGC" ) is False
43+
44+ @pytest .mark .asyncio
45+ async def test_refresh_positions (position_manager ):
46+ pm = position_manager
47+ prev_stats = dict (pm .stats )
48+ changed = await pm .refresh_positions ()
49+ assert changed is True
50+ assert pm .stats ["positions_tracked" ] == len (pm .tracked_positions )
51+
52+ @pytest .mark .asyncio
53+ async def test_cleanup (position_manager ):
54+ pm = position_manager
55+ # Prepopulate tracked_positions and position_alerts
56+ await pm .get_all_positions ()
57+ pm .position_alerts = {"foo" : "bar" }
58+ pm .order_manager = object ()
59+ pm ._order_sync_enabled = True
60+
61+ await pm .cleanup ()
62+ assert pm .tracked_positions == {}
63+ assert pm .position_alerts == {}
64+ assert pm .order_manager is None
65+ assert pm ._order_sync_enabled is False
0 commit comments