Co-authored-by: Clément Drouin <clement.drouin@mistral.ai> Co-authored-by: Corentin André <corentin.andre@mistral.ai> Co-authored-by: Guillaume LE GOFF <guillaume.lgf@gmail.com> Co-authored-by: Kim-Adeline Miguel <51720070+kimadeline@users.noreply.github.com> Co-authored-by: Maxime Dolores <maxime.dolores@ext.mistral.ai> Co-authored-by: Nelson PROIA <144663685+Nelson-PROIA@users.noreply.github.com> Co-authored-by: Peter Evers <pevers90@gmail.com> Co-authored-by: Pierre Rossinès <pierre.rossines@mistral.ai> Co-authored-by: Quentin <quentin.torroba@mistral.ai> Co-authored-by: Vincent G <10739306+VinceOPS@users.noreply.github.com> Co-authored-by: MichisGitIsKing <MichisGitIsKing@users.noreply.github.com> Co-authored-by: Mistral Vibe <vibe@mistral.ai>
111 lines
3.8 KiB
Python
111 lines
3.8 KiB
Python
from __future__ import annotations
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
from textual import events
|
|
|
|
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
|
from vibe.core.tools.builtins.ask_user_question import (
|
|
AskUserQuestionArgs,
|
|
Choice,
|
|
Question,
|
|
)
|
|
|
|
_TEST_GRACE_PERIOD_S = 0.5
|
|
|
|
|
|
@pytest.fixture
|
|
def question_app(monkeypatch: pytest.MonkeyPatch):
|
|
monkeypatch.setattr(
|
|
"vibe.cli.textual_ui.widgets.question_app._INPUT_GRACE_PERIOD_S",
|
|
_TEST_GRACE_PERIOD_S,
|
|
)
|
|
args = AskUserQuestionArgs(
|
|
questions=[
|
|
Question(
|
|
question="Pick one",
|
|
header="Pick",
|
|
options=[Choice(label="A"), Choice(label="B")],
|
|
)
|
|
]
|
|
)
|
|
app = QuestionApp(args)
|
|
app._mount_time = 100.0
|
|
return app
|
|
|
|
|
|
class TestQuestionAppGracePeriod:
|
|
def test_select_and_cancel_ignored_within_grace_period(
|
|
self, question_app: QuestionApp
|
|
):
|
|
with (
|
|
patch("vibe.cli.textual_ui.widgets.question_app.time") as mock_time,
|
|
patch.object(question_app, "post_message") as posted,
|
|
):
|
|
mock_time.monotonic.return_value = 100.0 + _TEST_GRACE_PERIOD_S - 0.01
|
|
assert question_app.is_within_grace_period()
|
|
|
|
question_app.action_select()
|
|
question_app.action_cancel()
|
|
|
|
posted.assert_not_called()
|
|
|
|
def test_cancel_posts_message_after_grace_period(self, question_app: QuestionApp):
|
|
with (
|
|
patch("vibe.cli.textual_ui.widgets.question_app.time") as mock_time,
|
|
patch.object(question_app, "post_message") as posted,
|
|
):
|
|
mock_time.monotonic.return_value = 100.0 + _TEST_GRACE_PERIOD_S + 0.01
|
|
|
|
question_app.action_cancel()
|
|
|
|
posted.assert_called_once()
|
|
assert isinstance(posted.call_args.args[0], QuestionApp.Cancelled)
|
|
|
|
def test_navigation_works_during_grace_period(self, question_app: QuestionApp):
|
|
with patch("vibe.cli.textual_ui.widgets.question_app.time") as mock_time:
|
|
mock_time.monotonic.return_value = 100.0 + 0.01
|
|
assert question_app.is_within_grace_period()
|
|
|
|
assert question_app.selected_option == 0
|
|
question_app.action_move_down()
|
|
assert question_app.selected_option == 1
|
|
question_app.action_move_up()
|
|
assert question_app.selected_option == 0
|
|
|
|
def test_number_key_consumed_but_not_acted_within_grace_period(
|
|
self, question_app: QuestionApp
|
|
):
|
|
with (
|
|
patch("vibe.cli.textual_ui.widgets.question_app.time") as mock_time,
|
|
patch.object(question_app, "post_message") as posted,
|
|
):
|
|
mock_time.monotonic.return_value = 100.0 + _TEST_GRACE_PERIOD_S - 0.01
|
|
event = MagicMock(spec=events.Key)
|
|
event.character = "1"
|
|
|
|
handled = question_app._handle_number_key(event)
|
|
|
|
assert handled is True
|
|
event.stop.assert_called_once()
|
|
event.prevent_default.assert_called_once()
|
|
posted.assert_not_called()
|
|
|
|
def test_number_key_selects_option_after_grace_period(
|
|
self, question_app: QuestionApp
|
|
):
|
|
with (
|
|
patch("vibe.cli.textual_ui.widgets.question_app.time") as mock_time,
|
|
patch.object(question_app, "post_message") as posted,
|
|
):
|
|
mock_time.monotonic.return_value = 100.0 + _TEST_GRACE_PERIOD_S + 0.01
|
|
event = MagicMock(spec=events.Key)
|
|
event.character = "1"
|
|
|
|
handled = question_app._handle_number_key(event)
|
|
|
|
assert handled is True
|
|
assert question_app.selected_option == 0
|
|
posted.assert_called_once()
|
|
assert isinstance(posted.call_args.args[0], QuestionApp.Answered)
|