Co-authored-by: Clément Sirieix <clement.sirieix@mistral.ai>
Co-authored-by: Guillaume LE GOFF <guillaume.lgf@gmail.com>
Co-authored-by: Hdandria <henri.dandria@mistral.ai>
Co-authored-by: Ivana Dunisijevic <ivana.dunisijevic@mistral.ai>
Co-authored-by: Jean Burellier <sheplu@users.noreply.github.com>
Co-authored-by: Mathias Gesbert <mathias.gesbert@mistral.ai>
Co-authored-by: Mert Unsal <mert.unsal@mistral.ai>
Co-authored-by: Michel Thomazo <51709227+michelTho@users.noreply.github.com>
Co-authored-by: Paul VEZIA <166131032+le-codeur-rapide@users.noreply.github.com>
Co-authored-by: Pierre Rossinès <pierre.rossines@mistral.ai>
Co-authored-by: Val <102326092+vdeva@users.noreply.github.com>
Co-authored-by: Vincent G <10739306+VinceOPS@users.noreply.github.com>
Co-authored-by: renovate-mistral[bot] <253709520+renovate-mistral[bot]@users.noreply.github.com>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
Clément Drouin 2026-06-19 11:01:24 +02:00 committed by GitHub
parent 564a14365e
commit 6bedf271ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
223 changed files with 10533 additions and 6947 deletions

View file

@ -24,7 +24,9 @@ class StubView(CompletionView):
def clear_completion_suggestions(self) -> None:
self.clears += 1
def replace_completion_range(self, start: int, end: int, replacement: str) -> None:
def replace_completion_range(
self, start: int, end: int, replacement: str, *, suppress_update: bool = False
) -> None:
self.replacements.append((start, end, replacement))

View file

@ -40,7 +40,9 @@ class StubView(CompletionView):
def clear_completion_suggestions(self) -> None:
self.reset_count += 1
def replace_completion_range(self, start: int, end: int, replacement: str) -> None:
def replace_completion_range(
self, start: int, end: int, replacement: str, *, suppress_update: bool = False
) -> None:
self.replacements.append(Replacement(start, end, replacement))

View file

@ -3,14 +3,13 @@ from __future__ import annotations
from pathlib import Path
import pytest
from textual.content import Content
from textual.style import Style
from textual.widgets import Markdown
from vibe.cli.textual_ui.app import VibeApp
from vibe.cli.textual_ui.widgets.chat_input.completion_popup import (
CompletionPopup,
_CompletionItem,
_CompletionRow,
)
from vibe.cli.textual_ui.widgets.chat_input.container import ChatInputContainer
@ -42,7 +41,7 @@ async def test_popup_hides_when_input_cleared(vibe_app: VibeApp) -> None:
@pytest.mark.asyncio
async def test_pressing_tab_writes_selected_command_and_leaves_popup_visible(
async def test_pressing_tab_completes_command_and_hides_popup_when_exact_match(
vibe_app: VibeApp,
) -> None:
async with vibe_app.run_test() as pilot:
@ -53,24 +52,18 @@ async def test_pressing_tab_writes_selected_command_and_leaves_popup_visible(
await pilot.press("tab")
assert chat_input.value == "/config"
assert popup.styles.display == "block"
assert popup.styles.display == "none"
def ensure_selected_command(popup: CompletionPopup, expected_alias: str) -> None:
selected_aliases: list[str] = []
for item in popup.query(_CompletionItem):
renderable = item.render()
assert isinstance(renderable, Content)
content = str(renderable)
for span in renderable.spans:
style = span.style
if isinstance(style, Style) and style.reverse:
alias_text = content[span.start : span.end].strip()
alias = alias_text.split()[0] if alias_text else ""
selected_aliases.append(alias)
assert len(selected_aliases) == 1
assert selected_aliases[0] == expected_alias
selected_rows = [
row
for row in popup.query(_CompletionRow)
if row.has_class("completion-selected")
]
assert len(selected_rows) == 1
command = selected_rows[0].query_one(".completion-command", _CompletionItem)
assert str(command.render()).strip() == expected_alias
@pytest.mark.asyncio
@ -297,20 +290,6 @@ async def test_finds_files_recursively_with_partial_path(
assert popup.styles.display == "block"
@pytest.mark.asyncio
async def test_popup_is_positioned_near_cursor(vibe_app: VibeApp) -> None:
async with vibe_app.run_test() as pilot:
popup = vibe_app.query_one(CompletionPopup)
await pilot.press(*"/com")
assert popup.styles.display == "block"
offset = popup.styles.offset
# The popup should have an explicit offset set by _position_popup
assert offset.x is not None
assert offset.y is not None
@pytest.mark.asyncio
async def test_does_not_trigger_completion_when_navigating_history(
file_tree: Path, vibe_app: VibeApp