fixes and refactor
This commit is contained in:
@@ -22,6 +22,7 @@ from tests.helpers import assert_validation_error # noqa: E402
|
||||
from app.api.financial import LedgerCreate # noqa: E402
|
||||
from app.database.base import SessionLocal # noqa: E402
|
||||
from app.models.qdro import QDRO # noqa: E402
|
||||
from app.config import settings # noqa: E402
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
@@ -37,6 +38,8 @@ def client():
|
||||
app.dependency_overrides[get_current_user] = lambda: _User()
|
||||
|
||||
try:
|
||||
# Disable cache for search API tests unless explicitly testing caching
|
||||
settings.cache_enabled = False
|
||||
yield TestClient(app)
|
||||
finally:
|
||||
app.dependency_overrides.pop(get_current_user, None)
|
||||
@@ -284,3 +287,181 @@ def test_global_search_highlights_mixed_case_for_customer_file_qdro(client: Test
|
||||
assert q is not None and isinstance(q.get("highlight"), str)
|
||||
assert "<strong>" in q["highlight"]
|
||||
assert f"<strong>{token_mixed}</strong>" in q["highlight"]
|
||||
|
||||
|
||||
def test_file_search_whole_words_and_exact_phrase(client: TestClient):
|
||||
token = f"FW-{uuid.uuid4().hex[:6]}"
|
||||
owner_id = _create_customer(client, f"Owner-{token}")
|
||||
f_exact = _create_file(client, owner_id, regarding_token="The apple pie is fresh")
|
||||
f_plural = _create_file(client, owner_id, regarding_token="The apple pies are fresh")
|
||||
|
||||
# whole_words=True should match 'pie' but not 'pies'
|
||||
payload = {
|
||||
"query": "pie",
|
||||
"search_types": ["file"],
|
||||
"whole_words": True,
|
||||
"limit": 50,
|
||||
}
|
||||
resp = client.post("/api/search/advanced", json=payload)
|
||||
assert resp.status_code == 200
|
||||
results = resp.json()["results"]
|
||||
ids = {r["id"] for r in results}
|
||||
assert f_exact in ids
|
||||
assert f_plural not in ids
|
||||
|
||||
# exact_phrase should match the exact wording only
|
||||
payload = {
|
||||
"query": "apple pie",
|
||||
"search_types": ["file"],
|
||||
"exact_phrase": True,
|
||||
"limit": 50,
|
||||
}
|
||||
resp = client.post("/api/search/advanced", json=payload)
|
||||
assert resp.status_code == 200
|
||||
results = resp.json()["results"]
|
||||
ids = {r["id"] for r in results}
|
||||
assert f_exact in ids
|
||||
assert f_plural not in ids
|
||||
|
||||
# default (substring) matching should include both
|
||||
payload = {
|
||||
"query": "pie",
|
||||
"search_types": ["file"],
|
||||
"limit": 50,
|
||||
}
|
||||
resp = client.post("/api/search/advanced", json=payload)
|
||||
assert resp.status_code == 200
|
||||
results = resp.json()["results"]
|
||||
ids = {r["id"] for r in results}
|
||||
assert f_exact in ids and f_plural in ids
|
||||
|
||||
|
||||
def test_ledger_search_whole_words(client: TestClient):
|
||||
token = f"LW-{uuid.uuid4().hex[:6]}"
|
||||
# Create a file for ledger linkage
|
||||
owner_id = _create_customer(client, f"Owner-{token}")
|
||||
file_no = _create_file(client, owner_id, regarding_token=token)
|
||||
|
||||
# Ledger entries: 'retainer' vs 'retained'
|
||||
resp = client.post(
|
||||
"/api/financial/ledger/",
|
||||
json=LedgerCreate(
|
||||
file_no=file_no,
|
||||
date=date.today().isoformat(),
|
||||
t_code="NOTE",
|
||||
t_type="2",
|
||||
empl_num="E01",
|
||||
quantity=0.0,
|
||||
rate=0.0,
|
||||
amount=0.0,
|
||||
billed="N",
|
||||
note="retainer fee approved",
|
||||
).model_dump(mode="json"),
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
|
||||
resp = client.post(
|
||||
"/api/financial/ledger/",
|
||||
json=LedgerCreate(
|
||||
file_no=file_no,
|
||||
date=date.today().isoformat(),
|
||||
t_code="NOTE",
|
||||
t_type="2",
|
||||
empl_num="E01",
|
||||
quantity=0.0,
|
||||
rate=0.0,
|
||||
amount=0.0,
|
||||
billed="N",
|
||||
note="retained amount on file",
|
||||
).model_dump(mode="json"),
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
|
||||
payload = {
|
||||
"query": "retainer",
|
||||
"search_types": ["ledger"],
|
||||
"whole_words": True,
|
||||
"limit": 50,
|
||||
}
|
||||
resp = client.post("/api/search/advanced", json=payload)
|
||||
assert resp.status_code == 200
|
||||
results = resp.json()["results"]
|
||||
# Should contain the entry with 'retainer fee approved' and exclude 'retained amount on file'
|
||||
texts = [r.get("description", "") for r in results]
|
||||
assert any("retainer fee approved" in t for t in texts)
|
||||
assert all("retained amount on file" not in t for t in texts)
|
||||
|
||||
|
||||
def test_qdro_search_whole_words_and_exact_phrase(client: TestClient):
|
||||
token = f"QW-{uuid.uuid4().hex[:6]}"
|
||||
owner_id = _create_customer(client, f"Owner-{token}")
|
||||
file_no = _create_file(client, owner_id, regarding_token=token)
|
||||
q1 = _create_qdro_with_form_name(file_no, form_name="Order for benefit under plan")
|
||||
q2 = _create_qdro_with_form_name(file_no, form_name="Order benefiting alternate payee")
|
||||
|
||||
# whole_words=True should match 'benefit' but not 'benefiting'
|
||||
payload = {
|
||||
"query": "benefit",
|
||||
"search_types": ["qdro"],
|
||||
"whole_words": True,
|
||||
"limit": 50,
|
||||
}
|
||||
resp = client.post("/api/search/advanced", json=payload)
|
||||
assert resp.status_code == 200
|
||||
results = resp.json()["results"]
|
||||
ids = {r["id"] for r in results}
|
||||
assert q1 in ids
|
||||
assert q2 not in ids
|
||||
|
||||
# exact_phrase should only match the precise phrase
|
||||
payload = {
|
||||
"query": "Order for benefit",
|
||||
"search_types": ["qdro"],
|
||||
"exact_phrase": True,
|
||||
"limit": 50,
|
||||
}
|
||||
resp = client.post("/api/search/advanced", json=payload)
|
||||
assert resp.status_code == 200
|
||||
results = resp.json()["results"]
|
||||
ids = {r["id"] for r in results}
|
||||
assert q1 in ids
|
||||
assert q2 not in ids
|
||||
|
||||
|
||||
def test_advanced_facets_include_state_and_transaction_type(client: TestClient):
|
||||
token = f"FAC-{uuid.uuid4().hex[:6]}"
|
||||
# Ensure at least one TX customer
|
||||
_ = _create_customer(client, f"Facet-{token}")
|
||||
# Ensure at least one ledger with t_type '2'
|
||||
owner_id = _create_customer(client, f"Owner-{token}")
|
||||
file_no = _create_file(client, owner_id, regarding_token=token)
|
||||
resp = client.post(
|
||||
"/api/financial/ledger/",
|
||||
json=LedgerCreate(
|
||||
file_no=file_no,
|
||||
date=date.today().isoformat(),
|
||||
t_code="NOTE",
|
||||
t_type="2",
|
||||
empl_num="E01",
|
||||
quantity=0.0,
|
||||
rate=0.0,
|
||||
amount=0.0,
|
||||
billed="N",
|
||||
note="Fee for facets token",
|
||||
).model_dump(mode="json"),
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
|
||||
# Query can be empty; we'll aggregate facets across returned results
|
||||
payload = {
|
||||
"search_types": ["customer", "ledger"],
|
||||
"limit": 200,
|
||||
}
|
||||
resp = client.post("/api/search/advanced", json=payload)
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
facets = data.get("facets", {})
|
||||
assert "state" in facets and isinstance(facets["state"], dict)
|
||||
assert any(k in ("TX", "Tx", "tx") for k in facets["state"].keys())
|
||||
assert "transaction_type" in facets and isinstance(facets["transaction_type"], dict)
|
||||
assert "2" in facets["transaction_type"] or 2 in facets["transaction_type"]
|
||||
Reference in New Issue
Block a user