vibe/tests/cli/test_approval_app_grace_period.py
Mathias Gesbert d50704e694
v2.18.2 (#857)
Co-authored-by: Cyprien <courtot.c@gmail.com>
Co-authored-by: Guillaume LE GOFF <guillaume.lgf@gmail.com>
Co-authored-by: Laure Hugo <201583486+laure0303@users.noreply.github.com>
Co-authored-by: Paul VEZIA <166131032+le-codeur-rapide@users.noreply.github.com>
Co-authored-by: Peter Evers <peter.evers@mistral.ai>
Co-authored-by: Pierre Rossinès <pierre.rossines@mistral.ai>
Co-authored-by: Yousria <yousria.debaud@mistral.ai>
Co-authored-by: renovate-mistral[bot] <253709520+renovate-mistral[bot]@users.noreply.github.com>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
2026-06-29 17:35:54 +02:00

112 lines
3.9 KiB
Python

from __future__ import annotations
from unittest.mock import patch
from pydantic import BaseModel
import pytest
from textual import events
from vibe.cli.textual_ui.widgets.approval_app import ApprovalApp
from vibe.core.config import VibeConfig
_TEST_GRACE_PERIOD_S = 0.5
class FakeArgs(BaseModel):
command: str = "echo hello"
@pytest.fixture
def approval_app(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr(
"vibe.cli.textual_ui.widgets.approval_app._INPUT_GRACE_PERIOD_S",
_TEST_GRACE_PERIOD_S,
)
config = VibeConfig()
app = ApprovalApp(tool_name="bash", tool_args=FakeArgs(), config=config)
app._mount_time = 100.0
return app
class TestGracePeriod:
def test_actions_ignored_within_grace_period(self, approval_app: ApprovalApp):
with (
patch("vibe.cli.textual_ui.widgets.approval_app.time") as mock_time,
patch.object(approval_app, "post_message") as posted,
):
mock_time.monotonic.return_value = 100.0 + _TEST_GRACE_PERIOD_S - 0.01
assert approval_app.is_within_grace_period()
approval_app.action_select()
approval_app.action_select_1()
approval_app.action_select_2()
approval_app.action_select_3()
approval_app.action_reject()
posted.assert_not_called()
def test_actions_post_messages_after_grace_period(self, approval_app: ApprovalApp):
with (
patch("vibe.cli.textual_ui.widgets.approval_app.time") as mock_time,
patch.object(approval_app, "post_message") as posted,
):
mock_time.monotonic.return_value = 100.0 + _TEST_GRACE_PERIOD_S + 0.01
assert not approval_app.is_within_grace_period()
approval_app.action_select_1()
approval_app.action_reject()
assert posted.call_count == 2
assert isinstance(
posted.call_args_list[0].args[0], ApprovalApp.ApprovalGranted
)
assert isinstance(
posted.call_args_list[1].args[0], ApprovalApp.ApprovalRejected
)
def test_arrow_keys_work_during_grace_period(self, approval_app: ApprovalApp):
with (
patch("vibe.cli.textual_ui.widgets.approval_app.time") as mock_time,
patch.object(approval_app, "_update_options"),
):
mock_time.monotonic.return_value = 100.0 + 0.01
assert approval_app.is_within_grace_period()
assert approval_app.selected_option == 0
approval_app.action_move_down()
assert approval_app.selected_option == 1
approval_app.action_move_up()
assert approval_app.selected_option == 0
class TestVimKeybindings:
def test_j_moves_down(self, approval_app: ApprovalApp):
with patch.object(approval_app, "_update_options"):
assert approval_app.selected_option == 0
approval_app.on_key(events.Key("j", "j"))
assert approval_app.selected_option == 1
def test_k_moves_up(self, approval_app: ApprovalApp):
with patch.object(approval_app, "_update_options"):
assert approval_app.selected_option == 0
approval_app.on_key(events.Key("k", "k"))
# Wraps to last option (index 3)
assert approval_app.selected_option == 3
def test_vim_navigation_works_during_grace_period(self, approval_app: ApprovalApp):
with (
patch("vibe.cli.textual_ui.widgets.approval_app.time") as mock_time,
patch.object(approval_app, "_update_options"),
):
mock_time.monotonic.return_value = 100.0 + 0.01
assert approval_app.is_within_grace_period()
assert approval_app.selected_option == 0
approval_app.on_key(events.Key("j", "j"))
assert approval_app.selected_option == 1
approval_app.on_key(events.Key("k", "k"))
assert approval_app.selected_option == 0