Files
delphi-database/tests/test_customers_search_utils.py
2025-08-14 19:16:28 -05:00

136 lines
4.1 KiB
Python

from types import SimpleNamespace
from sqlalchemy.dialects import sqlite
from app.services.customers_search import (
apply_customer_filters,
apply_customer_sorting,
prepare_customer_csv_rows,
)
class FakeQuery:
"""Lightweight stand-in for SQLAlchemy Query that captures filters and orderings.
We only need to verify that our helper functions add the expected number of
filter/order_by clauses and roughly target the expected columns. We do not
execute any SQL.
"""
def __init__(self):
self.filters = []
self.orderings = []
def filter(self, *args):
self.filters.extend(args)
return self
def order_by(self, *args):
self.orderings.extend(args)
return self
def compile_sql(expr):
"""Compile a SQLAlchemy expression to a SQLite SQL string for simple assertions."""
try:
return str(expr.compile(dialect=sqlite.dialect()))
except Exception:
return str(expr)
def test_apply_customer_filters_search_and_comma_pattern():
q = FakeQuery()
q = apply_customer_filters(q, search="Smith, John", group=None, state=None, groups=None, states=None)
# One filter clause added (combined search filter)
assert len(q.filters) == 1
sql = compile_sql(q.filters[0])
assert "last" in sql and "first" in sql
def test_apply_customer_filters_groups_and_states():
q = FakeQuery()
q = apply_customer_filters(q, search=None, group="A", state="NY", groups=None, states=None)
# Two filter clauses added: group and state
assert len(q.filters) == 2
sql_group = compile_sql(q.filters[0])
sql_state = compile_sql(q.filters[1])
assert "group" in sql_group
assert "abrev" in sql_state or "state" in sql_state
def test_apply_customer_filters_multi_groups_priority():
q = FakeQuery()
q = apply_customer_filters(q, search=None, group="A", state=None, groups=["X", "Y"], states=None)
# Only one filter (multi-groups) should be applied for groups
assert len(q.filters) == 1
assert "IN" in compile_sql(q.filters[0])
def test_apply_customer_sorting_fields_and_direction():
# name sorting => two orderings
q1 = FakeQuery()
q1 = apply_customer_sorting(q1, sort_by="name", sort_dir="asc")
assert len(q1.orderings) == 2
assert "last" in compile_sql(q1.orderings[0])
assert "first" in compile_sql(q1.orderings[1])
# id sorting desc => one ordering and DESC direction in SQL
q2 = FakeQuery()
q2 = apply_customer_sorting(q2, sort_by="id", sort_dir="desc")
assert len(q2.orderings) == 1
assert "DESC" in compile_sql(q2.orderings[0]).upper()
# unknown field falls back to id
q3 = FakeQuery()
q3 = apply_customer_sorting(q3, sort_by="unknown", sort_dir="asc")
assert len(q3.orderings) == 1
assert "id" in compile_sql(q3.orderings[0]).lower()
def test_prepare_customer_csv_rows_default_and_selected_fields():
cust1 = SimpleNamespace(
id="001",
first="John",
last="Smith",
group="G1",
city="New York",
abrev="NY",
email="john@example.com",
phone_numbers=[SimpleNamespace(phone="123-456-7890")],
)
cust2 = SimpleNamespace(
id="002",
first="Jane",
last="Doe",
group="G2",
city="Boston",
abrev="MA",
email="jane@example.com",
phone_numbers=[],
)
# Default fields
header, rows = prepare_customer_csv_rows([cust1, cust2], fields=None)
assert header == [
"Customer ID",
"Name",
"Group",
"City",
"State",
"Primary Phone",
"Email",
]
assert rows[0][0] == "001"
assert rows[0][1] == "John Smith"
assert rows[0][2] == "G1"
assert rows[0][3] == "New York"
assert rows[0][4] == "NY"
assert rows[0][5] == "123-456-7890"
assert rows[0][6] == "john@example.com"
# Selected subset of fields
header_sel, rows_sel = prepare_customer_csv_rows([cust1], fields=["id", "name", "email"]) # any case ok
assert header_sel == ["Customer ID", "Name", "Email"]
assert rows_sel[0] == ["001", "John Smith", "john@example.com"]