mirror of
https://github.com/open-jarvis/OpenJarvis.git
synced 2026-07-27 21:05:34 +00:00
* fix(channels): wire channel→agent handler and fix Telegram send pipeline * format code * add supported tests
155 lines
5.2 KiB
Python
155 lines
5.2 KiB
Python
"""Tests for the ``jarvis telemetry`` CLI commands."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import time
|
|
from pathlib import Path
|
|
from unittest import mock
|
|
|
|
from click.testing import CliRunner
|
|
|
|
from openjarvis.cli import cli
|
|
from openjarvis.core.types import TelemetryRecord
|
|
from openjarvis.telemetry.store import TelemetryStore
|
|
|
|
|
|
def _populate_db(db_path: Path, n: int = 3) -> None:
|
|
"""Create a telemetry DB with *n* records."""
|
|
store = TelemetryStore(db_path)
|
|
for i in range(n):
|
|
store.record(
|
|
TelemetryRecord(
|
|
timestamp=time.time() - (n - i),
|
|
model_id=f"model-{i % 2}",
|
|
engine="ollama",
|
|
prompt_tokens=10 * (i + 1),
|
|
completion_tokens=5 * (i + 1),
|
|
total_tokens=15 * (i + 1),
|
|
latency_seconds=0.5 * (i + 1),
|
|
cost_usd=0.001 * (i + 1),
|
|
)
|
|
)
|
|
store.close()
|
|
|
|
|
|
def _patch_config(tmp_path: Path):
|
|
"""Patch load_config to use a temp DB."""
|
|
db_path = tmp_path / "telemetry.db"
|
|
cfg = mock.MagicMock()
|
|
cfg.telemetry.db_path = str(db_path)
|
|
return mock.patch(
|
|
"openjarvis.cli.telemetry_cmd.load_config",
|
|
return_value=cfg,
|
|
), db_path
|
|
|
|
|
|
class TestTelemetrySubcommands:
|
|
def test_subcommands_exist_in_help(self) -> None:
|
|
result = CliRunner().invoke(cli, ["telemetry", "--help"])
|
|
assert result.exit_code == 0
|
|
assert "stats" in result.output
|
|
assert "export" in result.output
|
|
assert "clear" in result.output
|
|
|
|
|
|
class TestTelemetryStats:
|
|
def test_stats_empty_db(self, tmp_path: Path) -> None:
|
|
patch, db_path = _patch_config(tmp_path)
|
|
# Create empty DB
|
|
store = TelemetryStore(db_path)
|
|
store.close()
|
|
with patch:
|
|
result = CliRunner().invoke(cli, ["telemetry", "stats"])
|
|
assert result.exit_code == 0
|
|
assert "No telemetry data" in result.output
|
|
|
|
def test_stats_with_data(self, tmp_path: Path) -> None:
|
|
patch, db_path = _patch_config(tmp_path)
|
|
_populate_db(db_path)
|
|
with patch:
|
|
result = CliRunner().invoke(cli, ["telemetry", "stats"])
|
|
assert result.exit_code == 0
|
|
assert "Total Calls" in result.output
|
|
assert "3" in result.output
|
|
|
|
def test_top_flag(self, tmp_path: Path) -> None:
|
|
patch, db_path = _patch_config(tmp_path)
|
|
_populate_db(db_path, n=5)
|
|
with patch:
|
|
result = CliRunner().invoke(cli, ["telemetry", "stats", "-n", "1"])
|
|
assert result.exit_code == 0
|
|
assert "Top 1 Models" in result.output
|
|
|
|
|
|
class TestTelemetryExport:
|
|
def test_export_json_empty(self, tmp_path: Path) -> None:
|
|
patch, db_path = _patch_config(tmp_path)
|
|
store = TelemetryStore(db_path)
|
|
store.close()
|
|
with patch:
|
|
result = CliRunner().invoke(cli, ["telemetry", "export"])
|
|
assert result.exit_code == 0
|
|
data = json.loads(result.output)
|
|
assert data == []
|
|
|
|
def test_export_json_with_data(self, tmp_path: Path) -> None:
|
|
patch, db_path = _patch_config(tmp_path)
|
|
_populate_db(db_path)
|
|
with patch:
|
|
result = CliRunner().invoke(cli, ["telemetry", "export"])
|
|
assert result.exit_code == 0
|
|
data = json.loads(result.output)
|
|
assert len(data) == 3
|
|
|
|
def test_export_csv(self, tmp_path: Path) -> None:
|
|
patch, db_path = _patch_config(tmp_path)
|
|
_populate_db(db_path, n=2)
|
|
with patch:
|
|
result = CliRunner().invoke(cli, ["telemetry", "export", "-f", "csv"])
|
|
assert result.exit_code == 0
|
|
lines = result.output.strip().splitlines()
|
|
assert len(lines) == 3 # header + 2 rows
|
|
assert "model_id" in lines[0]
|
|
|
|
def test_export_to_file(self, tmp_path: Path) -> None:
|
|
patch, db_path = _patch_config(tmp_path)
|
|
_populate_db(db_path)
|
|
out_file = tmp_path / "export.json"
|
|
with patch:
|
|
result = CliRunner().invoke(
|
|
cli,
|
|
["telemetry", "export", "-o", str(out_file)],
|
|
)
|
|
assert result.exit_code == 0
|
|
assert out_file.exists()
|
|
data = json.loads(out_file.read_text())
|
|
assert len(data) == 3
|
|
|
|
|
|
class TestTelemetryClear:
|
|
def test_clear_empty(self, tmp_path: Path) -> None:
|
|
patch, db_path = _patch_config(tmp_path)
|
|
store = TelemetryStore(db_path)
|
|
store.close()
|
|
with patch:
|
|
result = CliRunner().invoke(cli, ["telemetry", "clear", "--yes"])
|
|
assert result.exit_code == 0
|
|
assert "Deleted 0" in result.output
|
|
|
|
def test_clear_with_yes(self, tmp_path: Path) -> None:
|
|
patch, db_path = _patch_config(tmp_path)
|
|
_populate_db(db_path)
|
|
with patch:
|
|
result = CliRunner().invoke(cli, ["telemetry", "clear", "--yes"])
|
|
assert result.exit_code == 0
|
|
assert "Deleted 3" in result.output
|
|
|
|
def test_clear_abort_without_yes(self, tmp_path: Path) -> None:
|
|
patch, db_path = _patch_config(tmp_path)
|
|
_populate_db(db_path)
|
|
with patch:
|
|
result = CliRunner().invoke(cli, ["telemetry", "clear"], input="n\n")
|
|
assert result.exit_code == 0
|
|
assert "Aborted" in result.output
|