journal-bot/tests/test_processor_lmstudio.py

88 lines
2.6 KiB
Python

import json
import httpx
import respx
import pytest
from journal_bot.processor_lmstudio import LMStudioProcessor
from journal_bot.processor_protocol import ProcessorInput
@pytest.fixture
def processor():
return LMStudioProcessor(
base_url="http://localhost:1234/v1",
model="qwen/qwen3-vl-8b",
system_prompt="SYS",
)
def make_input(text="Hallo Welt"):
return ProcessorInput(
today="2026-06-14",
weekday="Sonntag",
received_time="14:32",
persons=[],
projects=[],
text=text,
)
@respx.mock
def test_health_check_ok(processor):
respx.get("http://localhost:1234/v1/models").mock(
return_value=httpx.Response(200, json={"data": [{"id": "qwen/qwen3-vl-8b"}]})
)
assert processor.health_check() is True
@respx.mock
def test_health_check_down(processor):
respx.get("http://localhost:1234/v1/models").mock(
side_effect=httpx.ConnectError("no")
)
assert processor.health_check() is False
@respx.mock
def test_process_returns_validated_output(processor):
payload = {
"target_date": "2026-06-14",
"target_path": "05 Daily Notes/2026-06-14.md",
"entry_markdown": "## 14:32\nHallo Welt",
"clarifications": [],
"raw_excluded": [],
}
respx.post("http://localhost:1234/v1/chat/completions").mock(
return_value=httpx.Response(200, json={
"choices": [{"message": {"content": json.dumps(payload)}}],
})
)
out = processor.process(make_input())
assert out.target_date == "2026-06-14"
assert out.entry_markdown.startswith("## 14:32")
@respx.mock
def test_process_retries_on_schema_mismatch(processor):
bad = {"choices": [{"message": {"content": json.dumps({"target_date": "bad"})}}]}
good = {"choices": [{"message": {"content": json.dumps({
"target_date": "2026-06-14",
"target_path": "05 Daily Notes/2026-06-14.md",
"entry_markdown": "## 14:32\nHallo",
"clarifications": [], "raw_excluded": [],
})}}]}
respx.post("http://localhost:1234/v1/chat/completions").mock(
side_effect=[httpx.Response(200, json=bad), httpx.Response(200, json=good)]
)
out = processor.process(make_input())
assert out.target_date == "2026-06-14"
@respx.mock
def test_process_raises_after_max_retries(processor):
bad = {"choices": [{"message": {"content": "not json"}}]}
respx.post("http://localhost:1234/v1/chat/completions").mock(
return_value=httpx.Response(200, json=bad)
)
with pytest.raises(Exception):
processor.process(make_input())