v2.7.6 (#600)
Co-authored-by: Clément Sirieix <clement.sirieix@mistral.ai> Co-authored-by: Kim-Adeline Miguel <51720070+kimadeline@users.noreply.github.com> Co-authored-by: Mathias Gesbert <mathias.gesbert@mistral.ai> Co-authored-by: Maxime Dolores <maxime.dolores@ext.mistral.ai> Co-authored-by: Michel Thomazo <51709227+michelTho@users.noreply.github.com> Co-authored-by: Paul Cacheux <paul.cacheux@mistral.ai> Co-authored-by: Quentin <quentin.torroba@mistral.ai> Co-authored-by: Simon <80467011+sorgfresser@users.noreply.github.com> Co-authored-by: angelapopopo <angele.lenglemetz@mistral.ai> Co-authored-by: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
parent
e1a25caa52
commit
95336528f6
59 changed files with 3992 additions and 403 deletions
|
|
@ -142,7 +142,9 @@ class TestMCPAppInit:
|
|||
app = MCPApp(mcp_servers=servers, tool_manager=mgr)
|
||||
app._viewing_server = "srv"
|
||||
render_calls: list[str | None] = []
|
||||
app._refresh_view = lambda server_name: render_calls.append(server_name)
|
||||
app._refresh_view = lambda server_name, *, kind=None: render_calls.append(
|
||||
server_name
|
||||
)
|
||||
app.action_back()
|
||||
assert render_calls == [None]
|
||||
|
||||
|
|
@ -151,6 +153,8 @@ class TestMCPAppInit:
|
|||
app = MCPApp(mcp_servers=[], tool_manager=mgr)
|
||||
app._viewing_server = None
|
||||
render_calls: list[str | None] = []
|
||||
app._refresh_view = lambda server_name: render_calls.append(server_name)
|
||||
app._refresh_view = lambda server_name, *, kind=None: render_calls.append(
|
||||
server_name
|
||||
)
|
||||
app.action_back()
|
||||
assert render_calls == []
|
||||
|
|
|
|||
|
|
@ -278,6 +278,65 @@ class TestQuestionAppActions:
|
|||
assert app._get_other_text(0) == "Text for Q1"
|
||||
assert app._get_other_text(1) == ""
|
||||
|
||||
def test_switch_question_restores_cursor_to_answered_option(
|
||||
self, multi_question_args
|
||||
):
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
app = QuestionApp(multi_question_args)
|
||||
# Answer question 0 with MongoDB (index 1)
|
||||
app.answers[0] = ("MongoDB", False)
|
||||
|
||||
# Switch away then back
|
||||
app._switch_question(1)
|
||||
app._switch_question(0)
|
||||
|
||||
assert app.selected_option == 1
|
||||
|
||||
def test_switch_question_restores_cursor_to_other(self, multi_question_args):
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
app = QuestionApp(multi_question_args)
|
||||
# Answer question 0 with Other
|
||||
app.answers[0] = ("Custom DB", True)
|
||||
|
||||
app._switch_question(1)
|
||||
app._switch_question(0)
|
||||
|
||||
assert app.selected_option == len(app.questions[0].options)
|
||||
assert app._is_other_selected
|
||||
|
||||
def test_switch_question_defaults_to_zero_if_unanswered(self, multi_question_args):
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
app = QuestionApp(multi_question_args)
|
||||
|
||||
app._switch_question(1)
|
||||
assert app.selected_option == 0
|
||||
|
||||
def test_switch_question_restores_cursor_multi_select(self):
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
args = AskUserQuestionArgs(
|
||||
questions=[
|
||||
Question(
|
||||
question="Q1?", options=[Choice(label="A"), Choice(label="B")]
|
||||
),
|
||||
Question(
|
||||
question="Q2?",
|
||||
options=[Choice(label="X"), Choice(label="Y"), Choice(label="Z")],
|
||||
multi_select=True,
|
||||
),
|
||||
]
|
||||
)
|
||||
app = QuestionApp(args)
|
||||
# Select Y (1) and Z (2) for question 1
|
||||
app.multi_selections[1] = {1, 2}
|
||||
|
||||
app._switch_question(1)
|
||||
|
||||
assert app.selected_option == 1 # min of {1, 2}
|
||||
|
||||
|
||||
class TestMultiSelectOtherBehavior:
|
||||
def test_multi_select_other_does_not_advance_on_save(self, multi_select_args):
|
||||
|
|
@ -489,6 +548,152 @@ class TestMultiSelectAutoSelect:
|
|||
assert app._other_option_idx in app.multi_selections[0]
|
||||
|
||||
|
||||
class TestNumberKeyShortcuts:
|
||||
def test_number_key_selects_predefined_option(self, single_question_args):
|
||||
from unittest.mock import patch
|
||||
|
||||
from textual import events
|
||||
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
app = QuestionApp(single_question_args)
|
||||
app.selected_option = 0
|
||||
|
||||
# Press "2" -> should select MongoDB (index 1) and save
|
||||
event = events.Key("2", "2")
|
||||
with patch.object(app, "_advance_or_submit"):
|
||||
app._handle_number_key(event)
|
||||
|
||||
assert app.selected_option == 1
|
||||
assert 0 in app.answers
|
||||
answer_text, is_other = app.answers[0]
|
||||
assert answer_text == "MongoDB"
|
||||
assert is_other is False
|
||||
|
||||
def test_number_key_first_option(self, single_question_args):
|
||||
from unittest.mock import patch
|
||||
|
||||
from textual import events
|
||||
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
app = QuestionApp(single_question_args)
|
||||
|
||||
event = events.Key("1", "1")
|
||||
with patch.object(app, "_advance_or_submit"):
|
||||
app._handle_number_key(event)
|
||||
|
||||
assert app.selected_option == 0
|
||||
assert 0 in app.answers
|
||||
answer_text, _ = app.answers[0]
|
||||
assert answer_text == "PostgreSQL"
|
||||
|
||||
def test_number_key_other_empty_focuses(self, single_question_args):
|
||||
from textual import events
|
||||
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
app = QuestionApp(single_question_args)
|
||||
# Other is option index 2 -> key "3"
|
||||
event = events.Key("3", "3")
|
||||
app._handle_number_key(event)
|
||||
|
||||
# Should navigate to Other but not validate (no text)
|
||||
assert app.selected_option == 2
|
||||
assert app._is_other_selected is True
|
||||
assert 0 not in app.answers
|
||||
|
||||
def test_number_key_other_with_text_focuses_without_validating(
|
||||
self, single_question_args
|
||||
):
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from textual import events
|
||||
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
app = QuestionApp(single_question_args)
|
||||
app.other_texts[0] = "SQLite"
|
||||
app.other_input = MagicMock()
|
||||
app.other_input.has_focus = False
|
||||
|
||||
event = events.Key("3", "3")
|
||||
app._handle_number_key(event)
|
||||
|
||||
# Should navigate to Other but not validate — just focus the input
|
||||
assert app.selected_option == 2
|
||||
assert app._is_other_selected is True
|
||||
assert 0 not in app.answers
|
||||
|
||||
def test_number_key_out_of_range_ignored(self, single_question_args):
|
||||
from textual import events
|
||||
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
app = QuestionApp(single_question_args)
|
||||
# 3 options total (2 + Other), so "4" is out of range
|
||||
event = events.Key("4", "4")
|
||||
app._handle_number_key(event)
|
||||
|
||||
assert app.selected_option == 0
|
||||
assert 0 not in app.answers
|
||||
|
||||
def test_number_key_zero_ignored(self, single_question_args):
|
||||
from textual import events
|
||||
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
app = QuestionApp(single_question_args)
|
||||
event = events.Key("0", "0")
|
||||
app._handle_number_key(event)
|
||||
|
||||
assert app.selected_option == 0
|
||||
assert 0 not in app.answers
|
||||
|
||||
def test_number_key_ignored_when_input_focused(self, single_question_args):
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from textual import events
|
||||
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
app = QuestionApp(single_question_args)
|
||||
app.other_input = MagicMock()
|
||||
app.other_input.has_focus = True
|
||||
|
||||
event = events.Key("1", "1")
|
||||
app._handle_number_key(event)
|
||||
|
||||
assert app.selected_option == 0
|
||||
assert 0 not in app.answers
|
||||
|
||||
def test_number_key_multi_select_toggles(self, multi_select_args):
|
||||
from textual import events
|
||||
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
app = QuestionApp(multi_select_args)
|
||||
|
||||
# Press "1" in multi-select -> should toggle Auth
|
||||
event = events.Key("1", "1")
|
||||
app._handle_number_key(event)
|
||||
|
||||
assert 0 in app.multi_selections.get(0, set())
|
||||
|
||||
def test_number_key_multi_select_submit_ignored(self, multi_select_args):
|
||||
from textual import events
|
||||
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
||||
app = QuestionApp(multi_select_args)
|
||||
# Submit is at index 4 -> key "5"
|
||||
event = events.Key("5", "5")
|
||||
app._handle_number_key(event)
|
||||
|
||||
# Should not navigate to submit
|
||||
assert app.selected_option == 0
|
||||
|
||||
|
||||
class TestMultiSelectSubmit:
|
||||
def test_navigate_to_submit(self, multi_select_args):
|
||||
from vibe.cli.textual_ui.widgets.question_app import QuestionApp
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue