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:
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 |
52
tests/snapshots/base_snapshot_test_app.py
Normal file
52
tests/snapshots/base_snapshot_test_app.py
Normal 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"
|
||||
20
tests/snapshots/snap_compare.py
Normal file
20
tests/snapshots/snap_compare.py
Normal 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: ...
|
||||
43
tests/snapshots/test_ui_snapshot_basic_conversation.py
Normal file
43
tests/snapshots/test_ui_snapshot_basic_conversation.py
Normal 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,
|
||||
)
|
||||
|
|
@ -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),
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue