Files
wehub-resource-sync e4dcfc49aa
Tests / Import Check (Python 3.13) (push) Has been cancelled
Tests / Import Check (Python 3.14) (push) Has been cancelled
Tests / Python Tests (Python 3.11) (push) Has been cancelled
Tests / Python Tests (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.14) (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled
Tests / Lint and Format (push) Has been cancelled
Tests / Web Node Tests (push) Has been cancelled
Tests / Import Check (Python 3.11) (push) Has been cancelled
Tests / Import Check (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.13) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:00:43 +08:00

216 lines
7.1 KiB
Python

"""CLI smoke tests for the standalone ``deeptutor-cli`` package."""
from __future__ import annotations
import json
from typing import Any
import pytest
from typer.testing import CliRunner
from deeptutor.app import DeepTutorApp, TurnRequest
from deeptutor.runtime.bootstrap.builtin_capabilities import BUILTIN_CAPABILITY_CLASSES
from deeptutor_cli.main import app
runner = CliRunner()
def _install_fake_runtime(monkeypatch, captured_requests: list[TurnRequest]) -> None:
async def _start_turn(self, request): # noqa: ANN001
if isinstance(request, dict):
request = TurnRequest(**request)
captured_requests.append(request)
return {"id": request.session_id or "session-1"}, {"id": "turn-1"}
async def _stream_turn(self, turn_id: str, after_seq: int = 0): # noqa: ANN001
yield {"type": "session", "turn_id": turn_id, "seq": after_seq}
yield {"type": "stage_start", "stage": "responding"}
yield {"type": "content", "content": "response body"}
yield {"type": "result", "metadata": {"response": "response body"}}
yield {"type": "done"}
monkeypatch.setattr("deeptutor.app.facade.DeepTutorApp.start_turn", _start_turn)
monkeypatch.setattr("deeptutor.app.facade.DeepTutorApp.stream_turn", _stream_turn)
def test_run_command_json_mode(monkeypatch) -> None:
captured_requests: list[TurnRequest] = []
_install_fake_runtime(monkeypatch, captured_requests)
capabilities = list(BUILTIN_CAPABILITY_CLASSES)
for cap in capabilities:
result = runner.invoke(
app,
[
"run",
cap,
"hello world",
"--format",
"json",
"--tool",
"rag",
"--kb",
"demo-kb",
"--history-ref",
"session-old",
"--notebook-ref",
"nb1:rec1,rec2",
],
)
assert result.exit_code == 0, result.output
lines = [json.loads(line) for line in result.output.splitlines() if line.strip()]
assert any(line["type"] == "result" for line in lines)
assert len(captured_requests) == len(capabilities)
assert captured_requests[0].capability == "chat"
assert captured_requests[0].tools == ["rag"]
assert captured_requests[0].knowledge_bases == ["demo-kb"]
assert captured_requests[0].history_references == ["session-old"]
assert captured_requests[0].notebook_references == [
{"notebook_id": "nb1", "record_ids": ["rec1", "rec2"]}
]
assert {request.capability for request in captured_requests} == set(capabilities)
def test_builtin_capability_aliases_resolve_to_canonical_names() -> None:
runtime = DeepTutorApp()
assert runtime.resolve_capability("solve") == "deep_solve"
assert runtime.resolve_capability("quiz") == "deep_question"
assert runtime.resolve_capability("research") == "deep_research"
assert runtime.resolve_capability("viz") == "visualize"
assert runtime.resolve_capability("animate") == "math_animator"
assert runtime.resolve_capability("mastery") == "mastery_path"
with pytest.raises(ValueError, match="Unknown capability `auto`"):
runtime.resolve_capability("auto")
def test_run_command_rejects_removed_auto_capability() -> None:
result = runner.invoke(app, ["run", "auto", "hello"])
assert result.exit_code != 0
assert isinstance(result.exception, ValueError)
assert "Unknown capability `auto`" in str(result.exception)
def test_run_command_rich_mode(monkeypatch) -> None:
captured_requests: list[TurnRequest] = []
_install_fake_runtime(monkeypatch, captured_requests)
result = runner.invoke(app, ["run", "chat", "hello rich"])
assert result.exit_code == 0, result.output
assert "response body" in result.output
assert captured_requests[0].capability == "chat"
def test_run_command_with_config(monkeypatch) -> None:
captured_requests: list[TurnRequest] = []
_install_fake_runtime(monkeypatch, captured_requests)
result = runner.invoke(
app,
[
"run",
"deep_research",
"compare retrieval stacks",
"--config-json",
'{"mode":"report","depth":"deep"}',
],
)
assert result.exit_code == 0, result.output
request = captured_requests[0]
assert request.capability == "deep_research"
assert request.config == {
"mode": "report",
"depth": "deep",
}
def test_chat_repl_config_commands_match_docs_syntax(monkeypatch) -> None:
captured_requests: list[TurnRequest] = []
_install_fake_runtime(monkeypatch, captured_requests)
result = runner.invoke(
app,
["chat", "--config", "initial=true"],
input=(
"/config set num_questions 5\n"
'/config set question_types \'["short_answer","mcq"]\'\n'
"/refs\n"
"Generate questions\n"
"/quit\n"
),
)
assert result.exit_code == 0, result.output
assert '"num_questions": 5' in result.output
assert '"question_types"' in result.output
assert captured_requests[0].config == {
"initial": True,
"num_questions": 5,
"question_types": ["short_answer", "mcq"],
}
def test_chat_repl_backslash_continuation_sends_single_message(monkeypatch) -> None:
captured_requests: list[TurnRequest] = []
_install_fake_runtime(monkeypatch, captured_requests)
result = runner.invoke(
app,
["chat"],
input="Please review this code:\\\ndef fib(n): return n\n/quit\n",
)
assert result.exit_code == 0, result.output
assert captured_requests[0].content == "Please review this code:\ndef fib(n): return n"
def test_plugin_info_includes_capability_aliases_and_availability() -> None:
result = runner.invoke(app, ["plugin", "info", "deep_solve"])
assert result.exit_code == 0, result.output
payload = json.loads(result.output)
assert payload["name"] == "deep_solve"
assert payload["cli_aliases"] == ["solve"]
assert payload["availability"]["available"] is True
def test_session_list_command_uses_shared_store(monkeypatch) -> None:
async def _list_sessions(self, limit: int = 50, offset: int = 0): # noqa: ANN001
return [
{
"id": "session-1",
"title": "Algebra",
"capability": "chat",
"status": "completed",
"message_count": 4,
}
]
monkeypatch.setattr("deeptutor.app.facade.DeepTutorApp.list_sessions", _list_sessions)
result = runner.invoke(app, ["session", "list"])
assert result.exit_code == 0, result.output
assert "session-1" in result.output
assert "Algebra" in result.output
def test_start_command_delegates_to_runtime_launcher(monkeypatch) -> None:
calls: list[object] = []
def _fake_start(home=None): # noqa: ANN001
calls.append(home)
monkeypatch.setattr("deeptutor.runtime.launcher.start", _fake_start)
result = runner.invoke(app, ["start"])
assert result.exit_code == 0, result.output
assert calls == [None]