v2.15.0 (#773)
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: Nelson PROIA <144663685+Nelson-PROIA@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: Quentin <quentin.torroba@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: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
parent
702d0f412e
commit
cafb6d4147
247 changed files with 12401 additions and 3029 deletions
200
tests/cli/textual_ui/test_message_queue_ui.py
Normal file
200
tests/cli/textual_ui/test_message_queue_ui.py
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
from tests.conftest import build_test_vibe_app
|
||||
from vibe.cli.textual_ui.app import VibeApp
|
||||
from vibe.cli.textual_ui.widgets.chat_input.container import ChatInputContainer
|
||||
from vibe.cli.textual_ui.widgets.messages import (
|
||||
BashOutputMessage,
|
||||
QueueHeaderMessage,
|
||||
WarningMessage,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vibe_app() -> VibeApp:
|
||||
return build_test_vibe_app()
|
||||
|
||||
|
||||
async def _wait_until(pilot, predicate, timeout: float = 2.0) -> bool:
|
||||
deadline = time.monotonic() + timeout
|
||||
while time.monotonic() < deadline:
|
||||
if predicate():
|
||||
return True
|
||||
await pilot.pause(0.05)
|
||||
return False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_no_queue_header_when_empty(vibe_app: VibeApp) -> None:
|
||||
async with vibe_app.run_test():
|
||||
headers = list(vibe_app.query(QueueHeaderMessage))
|
||||
assert headers == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bash_submitted_during_running_bash_is_queued(vibe_app: VibeApp) -> None:
|
||||
async with vibe_app.run_test() as pilot:
|
||||
chat_input = vibe_app.query_one(ChatInputContainer)
|
||||
chat_input.value = "!sleep 0.3"
|
||||
await pilot.press("enter")
|
||||
|
||||
await _wait_until(pilot, lambda: vibe_app._bash_task is not None, timeout=1.0)
|
||||
|
||||
chat_input.value = "!echo queued"
|
||||
await pilot.press("enter")
|
||||
|
||||
assert len(vibe_app._input_queue) == 1
|
||||
assert vibe_app._input_queue.items[0].content == "echo queued"
|
||||
|
||||
headers = list(vibe_app.query(QueueHeaderMessage))
|
||||
assert len(headers) == 1
|
||||
|
||||
queued_bashes = [w for w in vibe_app.query(BashOutputMessage) if w._queued]
|
||||
assert len(queued_bashes) == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_slash_command_rejected_with_warning_when_busy(vibe_app: VibeApp) -> None:
|
||||
async with vibe_app.run_test() as pilot:
|
||||
chat_input = vibe_app.query_one(ChatInputContainer)
|
||||
chat_input.value = "!sleep 0.3"
|
||||
await pilot.press("enter")
|
||||
|
||||
await _wait_until(pilot, lambda: vibe_app._bash_task is not None, timeout=1.0)
|
||||
|
||||
chat_input.value = "/help"
|
||||
await pilot.press("enter")
|
||||
|
||||
assert not list(vibe_app.query(WarningMessage))
|
||||
assert any(
|
||||
"Slash commands cannot be queued" in notification.message
|
||||
for notification in vibe_app._notifications
|
||||
)
|
||||
assert len(vibe_app._input_queue) == 0
|
||||
assert chat_input.value.startswith("/help")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ctrl_c_pops_last_queued_item_lifo(vibe_app: VibeApp) -> None:
|
||||
async with vibe_app.run_test() as pilot:
|
||||
chat_input = vibe_app.query_one(ChatInputContainer)
|
||||
chat_input.value = "!sleep 2"
|
||||
await pilot.press("enter")
|
||||
|
||||
await _wait_until(pilot, lambda: vibe_app._bash_task is not None, timeout=2.0)
|
||||
|
||||
chat_input.value = "!echo first"
|
||||
await pilot.press("enter")
|
||||
chat_input.value = "!echo second"
|
||||
await pilot.press("enter")
|
||||
|
||||
assert len(vibe_app._input_queue) == 2
|
||||
|
||||
await pilot.press("ctrl+c")
|
||||
assert len(vibe_app._input_queue) == 1
|
||||
assert vibe_app._input_queue.items[0].content == "echo first"
|
||||
|
||||
await pilot.press("escape")
|
||||
await _wait_until(pilot, lambda: vibe_app._bash_task is None, timeout=5.0)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_escape_pauses_queue_when_job_running(vibe_app: VibeApp) -> None:
|
||||
async with vibe_app.run_test() as pilot:
|
||||
chat_input = vibe_app.query_one(ChatInputContainer)
|
||||
chat_input.value = "!sleep 2"
|
||||
await pilot.press("enter")
|
||||
|
||||
await _wait_until(pilot, lambda: vibe_app._bash_task is not None, timeout=2.0)
|
||||
|
||||
chat_input.value = "!echo queued"
|
||||
await pilot.press("enter")
|
||||
assert len(vibe_app._input_queue) == 1
|
||||
|
||||
await pilot.press("escape")
|
||||
assert vibe_app._input_queue.paused
|
||||
assert len(vibe_app._input_queue) == 1
|
||||
|
||||
await _wait_until(pilot, lambda: vibe_app._bash_task is None, timeout=5.0)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_drain_runs_queued_bashes_in_fifo_order(vibe_app: VibeApp) -> None:
|
||||
async with vibe_app.run_test() as pilot:
|
||||
chat_input = vibe_app.query_one(ChatInputContainer)
|
||||
chat_input.value = "!sleep 0.2"
|
||||
await pilot.press("enter")
|
||||
|
||||
await _wait_until(pilot, lambda: vibe_app._bash_task is not None, timeout=1.0)
|
||||
|
||||
chat_input.value = "!echo first"
|
||||
await pilot.press("enter")
|
||||
chat_input.value = "!echo second"
|
||||
await pilot.press("enter")
|
||||
|
||||
await _wait_until(
|
||||
pilot,
|
||||
lambda: (
|
||||
len(list(vibe_app.query(BashOutputMessage))) == 3
|
||||
and all(not m._pending for m in vibe_app.query(BashOutputMessage))
|
||||
),
|
||||
timeout=5.0,
|
||||
)
|
||||
|
||||
msgs = list(vibe_app.query(BashOutputMessage))
|
||||
assert len(msgs) == 3
|
||||
assert vibe_app._input_queue.paused is False
|
||||
assert len(vibe_app._input_queue) == 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_enter_on_empty_input_flushes_paused_queue(vibe_app: VibeApp) -> None:
|
||||
async with vibe_app.run_test() as pilot:
|
||||
chat_input = vibe_app.query_one(ChatInputContainer)
|
||||
chat_input.value = "!sleep 2"
|
||||
await pilot.press("enter")
|
||||
|
||||
await _wait_until(pilot, lambda: vibe_app._bash_task is not None, timeout=2.0)
|
||||
|
||||
chat_input.value = "!echo queued"
|
||||
await pilot.press("enter")
|
||||
assert len(vibe_app._input_queue) == 1
|
||||
|
||||
await pilot.press("escape")
|
||||
assert vibe_app._input_queue.paused
|
||||
|
||||
await _wait_until(pilot, lambda: vibe_app._bash_task is None, timeout=10.0)
|
||||
|
||||
chat_input.value = ""
|
||||
await pilot.press("enter")
|
||||
|
||||
await _wait_until(
|
||||
pilot,
|
||||
lambda: (
|
||||
not vibe_app._input_queue.paused and len(vibe_app._input_queue) == 0
|
||||
),
|
||||
timeout=10.0,
|
||||
)
|
||||
|
||||
assert not vibe_app._input_queue.paused
|
||||
assert len(vibe_app._input_queue) == 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_quit_warning_shows_queue_count(vibe_app: VibeApp) -> None:
|
||||
async with vibe_app.run_test():
|
||||
vibe_app._input_queue.append_prompt("a")
|
||||
vibe_app._input_queue.append_prompt("b")
|
||||
warning = vibe_app._queue.quit_warning_extra()
|
||||
assert warning == "2 queued messages will be discarded"
|
||||
|
||||
vibe_app._input_queue.pop_last()
|
||||
warning = vibe_app._queue.quit_warning_extra()
|
||||
assert warning == "1 queued message will be discarded"
|
||||
|
||||
vibe_app._input_queue.pop_last()
|
||||
assert vibe_app._queue.quit_warning_extra() == ""
|
||||
Loading…
Add table
Add a link
Reference in a new issue