peregrine/tests/test_feedback_api.py

121 lines
4.6 KiB
Python

"""Tests for the feedback API backend."""
import pytest
from unittest.mock import patch, MagicMock
from pathlib import Path
# ── mask_pii ──────────────────────────────────────────────────────────────────
def test_mask_pii_email():
from scripts.feedback_api import mask_pii
assert mask_pii("contact foo@bar.com please") == "contact [email redacted] please"
def test_mask_pii_phone_dashes():
from scripts.feedback_api import mask_pii
assert mask_pii("call 555-123-4567 now") == "call [phone redacted] now"
def test_mask_pii_phone_parens():
from scripts.feedback_api import mask_pii
assert mask_pii("(555) 867-5309") == "[phone redacted]"
def test_mask_pii_clean_text():
from scripts.feedback_api import mask_pii
assert mask_pii("no sensitive data here") == "no sensitive data here"
def test_mask_pii_multiple_emails():
from scripts.feedback_api import mask_pii
result = mask_pii("a@b.com and c@d.com")
assert result == "[email redacted] and [email redacted]"
# ── collect_context ───────────────────────────────────────────────────────────
def test_collect_context_required_keys():
from scripts.feedback_api import collect_context
ctx = collect_context("Home")
for key in ("page", "version", "tier", "llm_backend", "os", "timestamp"):
assert key in ctx, f"missing key: {key}"
def test_collect_context_page_value():
from scripts.feedback_api import collect_context
ctx = collect_context("MyPage")
assert ctx["page"] == "MyPage"
def test_collect_context_timestamp_is_utc():
from scripts.feedback_api import collect_context
ctx = collect_context("X")
assert ctx["timestamp"].endswith("Z")
# ── collect_logs ──────────────────────────────────────────────────────────────
def test_collect_logs_returns_string(tmp_path):
from scripts.feedback_api import collect_logs
log = tmp_path / ".streamlit.log"
log.write_text("line1\nline2\nline3\n")
result = collect_logs(log_path=log, n=10)
assert isinstance(result, str)
assert "line3" in result
def test_collect_logs_tails_n_lines(tmp_path):
from scripts.feedback_api import collect_logs
log = tmp_path / ".streamlit.log"
log.write_text("\n".join(f"line{i}" for i in range(200)))
result = collect_logs(log_path=log, n=10)
assert "line199" in result
assert "line0" not in result
def test_collect_logs_masks_pii(tmp_path):
from scripts.feedback_api import collect_logs
log = tmp_path / "test.log"
log.write_text("user foo@bar.com connected\n")
result = collect_logs(log_path=log)
assert "foo@bar.com" not in result
assert "[email redacted]" in result
def test_collect_logs_missing_file(tmp_path):
from scripts.feedback_api import collect_logs
result = collect_logs(log_path=tmp_path / "nonexistent.log")
assert "no log file" in result.lower()
# ── collect_listings ──────────────────────────────────────────────────────────
def test_collect_listings_safe_fields_only(tmp_path):
"""Only title, company, url — no cover letters, notes, or emails."""
from scripts.db import init_db, insert_job
from scripts.feedback_api import collect_listings
db = tmp_path / "test.db"
init_db(db)
insert_job(db, {
"title": "CSM", "company": "Acme", "url": "https://example.com/1",
"source": "linkedin", "location": "Remote", "is_remote": True,
"salary": "", "description": "great role", "date_found": "2026-03-01",
})
results = collect_listings(db_path=db, n=5)
assert len(results) == 1
assert set(results[0].keys()) == {"title", "company", "url"}
assert results[0]["title"] == "CSM"
def test_collect_listings_respects_n(tmp_path):
from scripts.db import init_db, insert_job
from scripts.feedback_api import collect_listings
db = tmp_path / "test.db"
init_db(db)
for i in range(10):
insert_job(db, {
"title": f"Job {i}", "company": "Acme", "url": f"https://example.com/{i}",
"source": "linkedin", "location": "Remote", "is_remote": False,
"salary": "", "description": "", "date_found": "2026-03-01",
})
assert len(collect_listings(db_path=db, n=3)) == 3