2.1.0 (#317)
Co-authored-by: Quentin Torroba <quentin.torroba@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: Clément Siriex <clement.sirieix@mistral.ai> Co-authored-by: Kim-Adeline Miguel <kimadeline.miguel@mistral.ai> Co-authored-by: Nicolas Karolak <nicolas@karolak.fr>
This commit is contained in:
parent
9809cfc831
commit
51fecc67d9
176 changed files with 8652 additions and 4451 deletions
172
tests/cli/test_ui_session_incremental_renderer.py
Normal file
172
tests/cli/test_ui_session_incremental_renderer.py
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
|
||||
import pytest
|
||||
from textual.widgets import Button
|
||||
|
||||
from tests.cli.plan_offer.adapters.fake_whoami_gateway import FakeWhoAmIGateway
|
||||
from tests.conftest import build_test_agent_loop
|
||||
from vibe.cli.plan_offer.ports.whoami_gateway import WhoAmIResponse
|
||||
from vibe.cli.textual_ui.app import ChatScroll, VibeApp
|
||||
from vibe.cli.textual_ui.widgets.load_more import (
|
||||
HistoryLoadMoreMessage,
|
||||
HistoryLoadMoreRequested,
|
||||
)
|
||||
from vibe.cli.textual_ui.widgets.messages import UserMessage
|
||||
from vibe.cli.textual_ui.windowing import (
|
||||
HISTORY_RESUME_TAIL_MESSAGES,
|
||||
LOAD_MORE_BATCH_SIZE,
|
||||
)
|
||||
from vibe.core.config import SessionLoggingConfig, VibeConfig
|
||||
from vibe.core.types import LLMMessage, Role
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vibe_config() -> VibeConfig:
|
||||
return VibeConfig(
|
||||
session_logging=SessionLoggingConfig(enabled=False), enable_update_checks=False
|
||||
)
|
||||
|
||||
|
||||
def _pro_plan_gateway() -> FakeWhoAmIGateway:
|
||||
return FakeWhoAmIGateway(
|
||||
response=WhoAmIResponse(
|
||||
is_pro_plan=True,
|
||||
advertise_pro_plan=False,
|
||||
prompt_switching_to_pro_plan=False,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def _wait_until(pause, predicate, timeout: float = 2.0) -> None:
|
||||
start = time.monotonic()
|
||||
while (time.monotonic() - start) < timeout:
|
||||
if predicate():
|
||||
return
|
||||
await pause(0.02)
|
||||
raise AssertionError("Condition was not met within the timeout")
|
||||
|
||||
|
||||
async def _wait_for_load_more(app: VibeApp, pause) -> None:
|
||||
await _wait_until(
|
||||
pause, lambda: len(app.query(HistoryLoadMoreMessage)) == 1, timeout=5.0
|
||||
)
|
||||
|
||||
|
||||
def _load_more_remaining(app: VibeApp) -> int:
|
||||
label = app.query_one(HistoryLoadMoreMessage).query_one(Button).label
|
||||
text = str(label)
|
||||
_, _, remainder = text.rpartition("(")
|
||||
return int(remainder.rstrip(")"))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ui_session_incremental_loader_shows_tail_and_load_more(
|
||||
vibe_config: VibeConfig,
|
||||
) -> None:
|
||||
agent_loop = build_test_agent_loop(config=vibe_config, enable_streaming=False)
|
||||
agent_loop.messages.extend([
|
||||
LLMMessage(role=Role.user, content=f"msg-{idx}") for idx in range(66)
|
||||
])
|
||||
|
||||
app = VibeApp(agent_loop=agent_loop, plan_offer_gateway=_pro_plan_gateway())
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await _wait_until(
|
||||
pilot.pause,
|
||||
lambda: len(app.query(UserMessage)) == HISTORY_RESUME_TAIL_MESSAGES,
|
||||
timeout=5.0,
|
||||
)
|
||||
await _wait_for_load_more(app, pilot.pause)
|
||||
|
||||
assert len(app.query(UserMessage)) == HISTORY_RESUME_TAIL_MESSAGES
|
||||
load_more = app.query_one(HistoryLoadMoreMessage)
|
||||
label = load_more.query_one(Button).label
|
||||
assert "(" in str(label)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ui_session_incremental_loader_load_more_shows_remaining_count(
|
||||
vibe_config: VibeConfig,
|
||||
) -> None:
|
||||
total_messages = 31
|
||||
agent_loop = build_test_agent_loop(config=vibe_config, enable_streaming=False)
|
||||
agent_loop.messages.extend([
|
||||
LLMMessage(role=Role.user, content=f"msg-{idx}")
|
||||
for idx in range(total_messages)
|
||||
])
|
||||
|
||||
app = VibeApp(agent_loop=agent_loop, plan_offer_gateway=_pro_plan_gateway())
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await _wait_until(
|
||||
pilot.pause,
|
||||
lambda: len(app.query(UserMessage)) == HISTORY_RESUME_TAIL_MESSAGES,
|
||||
timeout=5.0,
|
||||
)
|
||||
await _wait_for_load_more(app, pilot.pause)
|
||||
|
||||
initial_remaining = total_messages - HISTORY_RESUME_TAIL_MESSAGES
|
||||
assert _load_more_remaining(app) == initial_remaining
|
||||
|
||||
app.post_message(HistoryLoadMoreRequested())
|
||||
expected_remaining = initial_remaining - LOAD_MORE_BATCH_SIZE
|
||||
await _wait_until(
|
||||
pilot.pause,
|
||||
lambda: _load_more_remaining(app) == expected_remaining,
|
||||
timeout=5.0,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ui_session_incremental_loader_load_more_batches_until_done(
|
||||
vibe_config: VibeConfig,
|
||||
) -> None:
|
||||
agent_loop = build_test_agent_loop(config=vibe_config, enable_streaming=False)
|
||||
agent_loop.messages.extend([
|
||||
LLMMessage(role=Role.user, content=f"msg-{idx}") for idx in range(31)
|
||||
])
|
||||
|
||||
app = VibeApp(agent_loop=agent_loop, plan_offer_gateway=_pro_plan_gateway())
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await _wait_until(
|
||||
pilot.pause,
|
||||
lambda: len(app.query(UserMessage)) == HISTORY_RESUME_TAIL_MESSAGES,
|
||||
timeout=5.0,
|
||||
)
|
||||
await _wait_for_load_more(app, pilot.pause)
|
||||
|
||||
total_messages = 31
|
||||
while len(app.query(HistoryLoadMoreMessage)) == 1:
|
||||
current_count = len(app.query(UserMessage))
|
||||
app.post_message(HistoryLoadMoreRequested())
|
||||
await _wait_until(
|
||||
pilot.pause,
|
||||
lambda current_count=current_count: len(app.query(UserMessage))
|
||||
> current_count,
|
||||
)
|
||||
|
||||
await _wait_until(
|
||||
pilot.pause, lambda: len(app.query(UserMessage)) == total_messages
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ui_session_incremental_loader_keeps_top_alignment_when_not_scrollable(
|
||||
vibe_config: VibeConfig,
|
||||
) -> None:
|
||||
agent_loop = build_test_agent_loop(config=vibe_config, enable_streaming=False)
|
||||
agent_loop.messages.extend([
|
||||
LLMMessage(role=Role.user, content=f"msg-{idx}")
|
||||
for idx in range(HISTORY_RESUME_TAIL_MESSAGES + 1)
|
||||
])
|
||||
|
||||
app = VibeApp(agent_loop=agent_loop, plan_offer_gateway=_pro_plan_gateway())
|
||||
|
||||
async with app.run_test(size=(120, 80)) as pilot:
|
||||
await _wait_for_load_more(app, pilot.pause)
|
||||
chat = app.query_one("#chat", ChatScroll)
|
||||
assert chat.max_scroll_y == 0
|
||||
assert chat.scroll_y == 0
|
||||
Loading…
Add table
Add a link
Reference in a new issue