88 lines
2.6 KiB
Python
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())
|