Files
StarPilot/openpilot/starpilot/ui/tests/test_spacepilot_large.py
T
firestar5683 02ae25b975 Make SpacePilot entry reliable at natural tapping speeds
Count distinct touch releases by their original timestamps, retain taps
during valid Park dwell, and let preparation earn its own admission.
Cancel only the pending C4 startup camera redirect for a freshly parked
open game. All session, physical, alert, control, noOutput, ignition and
input authority checks remain unchanged.

231 focused native cases, original before regressions, current successor
entry/decoder qualification, canonical lint/type checks and independent
review. Host functional evidence; no device changes or headroom claim.
2026-10-26 14:35:25 -05:00

84 lines
3.2 KiB
Python

"""Real native gesture dispatch in Big UI, including canceled and moving rows."""
from types import SimpleNamespace as NS
from unittest.mock import Mock
import pyray as rl
import pytest
from openpilot.starpilot.ui.spacepilot import large, native
from openpilot.starpilot.ui.presentation import Profile
from openpilot.starpilot.ui.tests.test_spacepilot_state import mature_gate, parked_ui, read
from openpilot.system.ui.lib.application import MouseEvent, MousePos, gui_app
@pytest.fixture
def adapter(monkeypatch):
monkeypatch.setattr(gui_app, 'font', lambda *_: rl.Font())
fonts = NS(profile=Profile.LARGE, vertical_ink=lambda _t, _r, size: (0, size),
measure=lambda text, _r, size: NS(width=len(text) * size / 2))
panel = NS(_scroller=NS(_items=[]), show_event=Mock(), hide_event=Mock(), _update_state=Mock())
ui = NS(params=NS(get=lambda _: '0.10.3'))
monkeypatch.setattr(large, 'ui_state', ui)
monkeypatch.setattr(native, 'ui_state', ui)
monkeypatch.setattr(large, 'live_witness', lambda: read(parked_ui()))
widget = large.SpacePilotDeveloperAdapter(panel, fonts, Mock(), Mock())
widget.set_rect(rl.Rectangle(0, 0, 2160, 1080))
widget.show_event()
widget.gate = mature_gate()
yield widget
widget.hide_event()
def deliver(widget, monkeypatch, index, *, drift=0, duration=.04):
bounds = widget._version_bounds()
pos = MousePos(bounds.x + 20, bounds.y + 10)
now = 10 + index * .2
monkeypatch.setattr(native.time, 'monotonic', lambda: now)
events = [MouseEvent(pos, 0, True, False, True, now)]
if drift:
events.append(MouseEvent(MousePos(pos.x + drift, pos.y), 0, False, False, True, now + .01))
events.append(MouseEvent(pos, 0, False, True, False, now + duration))
monkeypatch.setattr(gui_app, '_mouse_events', events)
widget._process_mouse_events()
def test_big_ui_five_version_value_taps_launch_same_native_game(adapter, monkeypatch):
push = Mock()
monkeypatch.setattr(gui_app, 'push_widget', push)
for i in range(4):
deliver(adapter, monkeypatch, i)
push.assert_not_called()
deliver(adapter, monkeypatch, 4)
push.assert_called_once()
assert isinstance(push.call_args.args[0], native.SpacePilotPage)
assert push.call_args.args[0].gate is not adapter.gate
@pytest.mark.parametrize('cancel', ['drag', 'long', 'page', 'hide', 'unsafe', 'outside', 'scroll'])
def test_big_ui_cancel_resets_deliberate_gesture(adapter, monkeypatch, cancel):
push = Mock()
monkeypatch.setattr(gui_app, 'push_widget', push)
for i in range(4):
deliver(adapter, monkeypatch, i)
if cancel == 'drag':
deliver(adapter, monkeypatch, 4, drift=30)
elif cancel == 'long':
deliver(adapter, monkeypatch, 4, duration=.5)
elif cancel == 'page':
adapter._emit(NS(kind='scroll', direction=1))
elif cancel == 'hide':
adapter.hide_event()
elif cancel == 'unsafe':
monkeypatch.setattr(large, 'live_witness', lambda: None)
adapter._update_state()
elif cancel == 'outside':
monkeypatch.setattr(gui_app, '_mouse_events', [MouseEvent(MousePos(10, 10), 0, True, False, True, 10.9)])
adapter._process_mouse_events()
else:
adapter.set_touch_valid_callback(lambda: False)
monkeypatch.setattr(gui_app, '_mouse_events', [])
adapter._process_mouse_events()
assert adapter.taps.count == 0
push.assert_not_called()