Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion backend/ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ def _extract_json(text: str) -> dict[str, Any]:
def suggest_for_ticket(ticket_id: str) -> dict[str, Any]:
ticket = _fetch_ticket(ticket_id)
notes = _fetch_notes(ticket_id)
history = _fetch_recent_resolved(30)
# A Resolved/Closed ticket must not be offered as a "similar past ticket" to itself.
history = [t for t in _fetch_recent_resolved(30) if t.get("id") != ticket.get("id")]

if not history:
return {"matches": [], "note": "No resolved tickets available for comparison."}
Expand Down
53 changes: 53 additions & 0 deletions backend/test_ai_suggest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""Tests for ai.suggest_for_ticket (the real ai module, not the stub used in test_main)."""

import importlib
import sys
from unittest.mock import MagicMock

import pytest


@pytest.fixture
def ai(monkeypatch):
sys.modules.pop("ai", None)
module = importlib.import_module("ai")
yield module
sys.modules.pop("ai", None)


def test_suggest_excludes_the_ticket_itself(ai, monkeypatch):
target = {"id": "t1", "title": "Printer jam", "status": "Closed"}
other = {"id": "t2", "title": "Paper jam", "status": "Resolved"}
monkeypatch.setattr(ai, "_fetch_ticket", lambda _id: target)
monkeypatch.setattr(ai, "_fetch_notes", lambda _id: [])
monkeypatch.setattr(ai, "_fetch_recent_resolved", lambda limit=30: [dict(target), dict(other)])

captured = {}

def fake_build(ticket, notes, history):
captured["history"] = history
return "prompt"

monkeypatch.setattr(ai, "_build_prompt", fake_build)
client = MagicMock()
client.messages.create.return_value = MagicMock(
content=[MagicMock(type="text", text='{"matches": []}')]
)
monkeypatch.setattr(ai, "_get_client", lambda: client)

ai.suggest_for_ticket("t1")

assert [t["id"] for t in captured["history"]] == ["t2"]


def test_suggest_with_only_itself_in_history_returns_note(ai, monkeypatch):
target = {"id": "t1", "title": "Printer jam", "status": "Closed"}
monkeypatch.setattr(ai, "_fetch_ticket", lambda _id: target)
monkeypatch.setattr(ai, "_fetch_notes", lambda _id: [])
monkeypatch.setattr(ai, "_fetch_recent_resolved", lambda limit=30: [dict(target)])
monkeypatch.setattr(ai, "_get_client", lambda: pytest.fail("model must not be called"))

result = ai.suggest_for_ticket("t1")

assert result["matches"] == []
assert "No resolved tickets" in result["note"]
Loading