Files
FabledScribe/tests/test_tool_use_fixes.py
T
2026-05-12 16:42:34 -04:00

112 lines
4.4 KiB
Python

"""Tests for the tool-use fixes from the 2026-05-08 journal session."""
from types import SimpleNamespace
from unittest.mock import AsyncMock, patch
import pytest
def _project(pid: int, title: str, description: str = "", auto_summary: str = ""):
return SimpleNamespace(
id=pid, title=title, description=description, auto_summary=auto_summary,
)
@pytest.mark.asyncio
async def test_search_projects_tool_returns_success_true():
"""The dispatcher sets status from result['success']; without this key
the call gets labeled 'error' even when data is returned."""
from fabledassistant.services.tools import projects as projects_tool
fake_projects = [_project(5, "Famous-Supply Work topics", "AT&T fiber circuit")]
with patch.object(projects_tool, "list_projects", new=AsyncMock(return_value=fake_projects)):
result = await projects_tool.search_projects_tool(
user_id=1, arguments={"query": "famous supply"},
)
assert result["success"] is True
assert result["type"] == "projects_list"
assert len(result["data"]["projects"]) == 1
def test_strip_type_nouns_removes_task_word():
from fabledassistant.services.notes import _strip_type_nouns
assert _strip_type_nouns("sebring secondary task") == ["sebring", "secondary"]
def test_strip_type_nouns_removes_all_variants():
from fabledassistant.services.notes import _strip_type_nouns
assert _strip_type_nouns("project notes task") == []
def test_strip_type_nouns_case_insensitive():
from fabledassistant.services.notes import _strip_type_nouns
assert _strip_type_nouns("Sebring Task NOTES") == ["Sebring"]
def test_strip_type_nouns_preserves_real_content_words():
from fabledassistant.services.notes import _strip_type_nouns
assert _strip_type_nouns("circuit configuration") == ["circuit", "configuration"]
def test_strip_type_nouns_handles_empty_string():
from fabledassistant.services.notes import _strip_type_nouns
assert _strip_type_nouns("") == []
assert _strip_type_nouns(" ") == []
def test_score_project_match_exact_title_returns_1():
from fabledassistant.services.tools._helpers import score_project_match
p = _project(5, "Famous-Supply Work topics")
assert score_project_match("Famous-Supply Work topics", p) == 1.0
def test_score_project_match_colloquial_substring_at_least_85():
"""'famous supply' is a substring of normalized 'famous supply work topics'
after stripping the hyphen. Substring match returns 0.85."""
from fabledassistant.services.tools._helpers import score_project_match
p = _project(5, "Famous-Supply Work topics", auto_summary="AT&T fiber circuit")
score = score_project_match("famous supply project", p)
assert score >= 0.85, f"expected substring tier (>=0.85), got {score}"
def test_score_project_match_query_in_summary_returns_70():
from fabledassistant.services.tools._helpers import score_project_match
p = _project(12, "Minstrel", auto_summary="self-hosted music server")
assert score_project_match("music server", p) == 0.70
def test_score_project_match_unrelated_returns_low():
from fabledassistant.services.tools._helpers import score_project_match
p = _project(12, "Minstrel", auto_summary="self-hosted music server")
assert score_project_match("garden renovation", p) < 0.5
def test_score_project_match_empty_query_returns_zero():
from fabledassistant.services.tools._helpers import score_project_match
p = _project(5, "Famous-Supply Work topics")
assert score_project_match("", p) == 0.0
@pytest.mark.asyncio
async def test_search_projects_tool_ranks_substring_match_above_others():
"""Substring hits (score 0.85) must rank above SequenceMatcher misses
for unrelated projects."""
from fabledassistant.services.tools import projects as projects_tool
fake_projects = [
_project(12, "Minstrel", auto_summary="self-hosted music server"),
_project(5, "Famous-Supply Work topics", auto_summary="AT&T fiber circuit"),
_project(13, "ImageRepo", auto_summary="self-hosted Flask app"),
]
with patch.object(projects_tool, "list_projects", new=AsyncMock(return_value=fake_projects)):
result = await projects_tool.search_projects_tool(
user_id=1, arguments={"query": "famous supply project"},
)
top = result["data"]["projects"][0]
assert top["id"] == 5, f"expected Famous-Supply to rank first, got {top}"
assert top["score"] >= 0.85