Initial commit

Co-Authored-By: Quentin Torroba <quentin.torroba@mistral.ai>
Co-Authored-By: Laure Hugo <laure.hugo@mistral.ai>
Co-Authored-By: Benjamin Trom <benjamin.trom@mistral.ai>
Co-Authored-By: Mathias Gesbert <mathias.gesbert@ext.mistral.ai>
Co-Authored-By: Michel Thomazo <michel.thomazo@mistral.ai>
Co-Authored-By: Clément Drouin <clement.drouin@mistral.ai>
Co-Authored-By: Vincent Guilloux <vincent.guilloux@mistral.ai>
Co-Authored-By: Valentin Berard <val@mistral.ai>
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
Quentin Torroba 2025-12-09 13:13:22 +01:00 committed by Quentin Torroba
commit fa15fc977b
200 changed files with 30484 additions and 0 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -0,0 +1,52 @@
from __future__ import annotations
from rich.style import Style
from textual.widgets.text_area import TextAreaTheme
from tests.stubs.fake_backend import FakeBackend
from vibe.cli.textual_ui.app import VibeApp
from vibe.cli.textual_ui.widgets.chat_input import ChatTextArea
from vibe.core.agent import Agent
from vibe.core.config import SessionLoggingConfig, VibeConfig
def default_config() -> VibeConfig:
"""Default configuration for snapshot testing.
Remove as much interference as possible from the snapshot comparison, in order to get a clean pixel-to-pixel comparison.
- Injects a fake backend to prevent (or stub) LLM calls.
- Disables the welcome banner animation.
- Forces a value for the displayed workdir
- Hides the chat input cursor (as the blinking animation is not deterministic).
"""
return VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
textual_theme="gruvbox",
disable_welcome_banner_animation=True,
displayed_workdir="/test/workdir",
)
class BaseSnapshotTestApp(VibeApp):
CSS_PATH = "../../vibe/cli/textual_ui/app.tcss"
def __init__(self, config: VibeConfig | None = None, **kwargs):
config = config or default_config()
super().__init__(config=config, **kwargs)
self.agent = Agent(
config,
auto_approve=self.auto_approve,
enable_streaming=self.enable_streaming,
backend=FakeBackend(),
)
async def on_mount(self) -> None:
await super().on_mount()
self._hide_chat_input_cursor()
def _hide_chat_input_cursor(self) -> None:
text_area = self.query_one(ChatTextArea)
hidden_cursor_theme = TextAreaTheme(name="hidden_cursor", cursor_style=Style())
text_area.register_theme(hidden_cursor_theme)
text_area.theme = "hidden_cursor"

View file

@ -0,0 +1,20 @@
from __future__ import annotations
from collections.abc import Awaitable, Callable, Iterable
from pathlib import PurePath
from typing import Protocol
from textual.app import App
from textual.pilot import Pilot
class SnapCompare(Protocol):
def __call__(
self,
app: str | PurePath | App,
/,
*,
press: Iterable[str] = ...,
terminal_size: tuple[int, int] = ...,
run_before: (Callable[[Pilot], Awaitable[None] | None] | None) = ...,
) -> bool: ...

View file

@ -0,0 +1,43 @@
from __future__ import annotations
from textual.pilot import Pilot
from tests.mock.utils import mock_llm_chunk
from tests.snapshots.base_snapshot_test_app import BaseSnapshotTestApp, default_config
from tests.snapshots.snap_compare import SnapCompare
from tests.stubs.fake_backend import FakeBackend
from vibe.core.agent import Agent
class SnapshotTestAppWithConversation(BaseSnapshotTestApp):
def __init__(self) -> None:
config = default_config()
fake_backend = FakeBackend(
results=[
mock_llm_chunk(
content="I'm the Vibe agent and I'm ready to help.",
prompt_tokens=10_000,
completion_tokens=2_500,
)
]
)
super().__init__(config=config)
self.agent = Agent(
config,
auto_approve=self.auto_approve,
enable_streaming=self.enable_streaming,
backend=fake_backend,
)
def test_snapshot_shows_basic_conversation(snap_compare: SnapCompare) -> None:
async def run_before(pilot: Pilot) -> None:
await pilot.press(*"Hello there, who are you?")
await pilot.press("enter")
await pilot.pause(0.4)
assert snap_compare(
"test_ui_snapshot_basic_conversation.py:SnapshotTestAppWithConversation",
terminal_size=(120, 36),
run_before=run_before,
)

View file

@ -0,0 +1,38 @@
from __future__ import annotations
from textual.pilot import Pilot
from textual.widgets.markdown import MarkdownFence
from tests.snapshots.snap_compare import SnapCompare
from vibe.cli.textual_ui.widgets.messages import AssistantMessage
def test_snapshot_allows_horizontal_scrolling_for_long_code_blocks(
snap_compare: SnapCompare,
) -> None:
assistant_message_md = """Here's a very long print instruction:
```python
def lorem_ipsum():
# Print a very long line (Lorem Ipsum)
print("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.")
```
The `print` statement includes a very long line of Lorem Ipsum text to demonstrate a lengthy output."""
async def run_before(pilot: Pilot) -> None:
app = pilot.app
assistant_message = AssistantMessage(assistant_message_md)
messages_area = app.query_one("#messages")
await messages_area.mount(assistant_message)
await assistant_message.write_initial_content()
await pilot.pause(0.1)
markdown_fence = app.query_one(MarkdownFence)
markdown_fence.scroll_relative(x=15, immediate=True)
assert snap_compare(
"base_snapshot_test_app.py:BaseSnapshotTestApp",
run_before=run_before,
terminal_size=(120, 36),
)

View file

@ -0,0 +1,28 @@
from __future__ import annotations
from textual.pilot import Pilot
from tests.snapshots.base_snapshot_test_app import BaseSnapshotTestApp, default_config
from tests.snapshots.snap_compare import SnapCompare
from vibe.cli.update_notifier import FakeVersionUpdateGateway, VersionUpdate
class SnapshotTestAppWithUpdate(BaseSnapshotTestApp):
def __init__(self):
config = default_config()
config.enable_update_checks = True
version_update_notifier = FakeVersionUpdateGateway(
update=VersionUpdate(latest_version="0.2.0")
)
super().__init__(config=config, version_update_notifier=version_update_notifier)
def test_snapshot_shows_release_update_notification(snap_compare: SnapCompare) -> None:
async def run_before(pilot: Pilot) -> None:
await pilot.pause(0.2)
assert snap_compare(
"test_ui_snapshot_release_update_notification.py:SnapshotTestAppWithUpdate",
terminal_size=(120, 36),
run_before=run_before,
)