tests/aliases: gap-fill list_term_aliases + tokenizer helpers (10 new tests)
The aliases.py public surface had 18 tests covering happy-paths,
audit discipline, domain isolation, lowercase normalization, and
expand-query semantics. Three direct gaps:
- list_term_aliases (no test at all): filter-by-domain, filter-by-
term-substring, unreachable-db fail-closed, missing-table fail-
closed
- _tokenize_fts_query (only via expand-query smoke): preserve
quoted phrases, parentheses-as-tokens (OR-expansion contract),
unterminated-quote fallback
- _quote_for_fts + _match_quoting (no direct test): pass-through
quoted, defensive quote-multi-word, quoted-reference symmetry
10 new tests; aliases.py test count 18 → 28. Same fixture pattern
as the existing tests (sqlite tmp DB with SCHEMA_SQL applied).
This commit is contained in:
parent
0b038f1e36
commit
1104cf97ca
1 changed files with 118 additions and 0 deletions
|
|
@ -255,3 +255,121 @@ def test_expand_query_unreachable_db_returns_original():
|
|||
"incidence", "geometry", "/nonexistent/path/aliases.db"
|
||||
)
|
||||
assert expanded == "incidence"
|
||||
|
||||
|
||||
# --- list_term_aliases (gap-fill 2026-05-10) -------------------------
|
||||
|
||||
|
||||
def test_list_term_aliases_filters_by_domain(db):
|
||||
"""`list_term_aliases(domain=X)` returns only rows in that
|
||||
domain. Same pattern as list_citation_aliases filter."""
|
||||
add_term_alias(
|
||||
db, term="set", alternate_term="class",
|
||||
domain="set-theory", decision_by="fox",
|
||||
)
|
||||
add_term_alias(
|
||||
db, term="line", alternate_term="ray",
|
||||
domain="geometry", decision_by="fox",
|
||||
)
|
||||
add_term_alias(
|
||||
db, term="incidence", alternate_term="connection",
|
||||
domain="geometry", decision_by="fox",
|
||||
)
|
||||
from arborist.qa.aliases import list_term_aliases
|
||||
|
||||
geom = list_term_aliases(db, domain="geometry")
|
||||
assert len(geom) == 2
|
||||
assert all(a.domain == "geometry" for a in geom)
|
||||
set_th = list_term_aliases(db, domain="set-theory")
|
||||
assert len(set_th) == 1
|
||||
assert set_th[0].term == "set"
|
||||
|
||||
|
||||
def test_list_term_aliases_filters_by_term_substring(db):
|
||||
"""`term_filter` is a substring match (LIKE %X%) on term."""
|
||||
add_term_alias(db, term="incidence", alternate_term="connection",
|
||||
domain="geometry", decision_by="fox")
|
||||
add_term_alias(db, term="line incidence", alternate_term="line connection",
|
||||
domain="geometry", decision_by="fox")
|
||||
add_term_alias(db, term="parallel", alternate_term="parallels",
|
||||
domain="geometry", decision_by="fox")
|
||||
from arborist.qa.aliases import list_term_aliases
|
||||
|
||||
inc = list_term_aliases(db, term_filter="incidence")
|
||||
assert len(inc) == 2
|
||||
assert all("incidence" in a.term for a in inc)
|
||||
|
||||
|
||||
def test_list_term_aliases_unreachable_db_returns_empty():
|
||||
"""Same fail-closed contract as expand_query_with_term_aliases:
|
||||
nonexistent DB → empty list, no exception."""
|
||||
from arborist.qa.aliases import list_term_aliases
|
||||
|
||||
assert list_term_aliases("/nonexistent/path/aliases.db") == []
|
||||
|
||||
|
||||
def test_list_term_aliases_handles_missing_table(tmp_path):
|
||||
"""A SQLite file without the term_aliases table → empty list,
|
||||
not an OperationalError."""
|
||||
import sqlite3
|
||||
|
||||
bad_db = tmp_path / "no-schema.db"
|
||||
sqlite3.connect(str(bad_db)).execute("CREATE TABLE foo (x TEXT)").connection.close()
|
||||
from arborist.qa.aliases import list_term_aliases
|
||||
|
||||
assert list_term_aliases(str(bad_db)) == []
|
||||
|
||||
|
||||
# --- internal helper coverage (small surfaces, easy regression risk) -
|
||||
|
||||
|
||||
def test_tokenize_fts_query_preserves_quoted_phrase():
|
||||
from arborist.qa.aliases import _tokenize_fts_query
|
||||
|
||||
assert _tokenize_fts_query('"line incidence"') == ['"line incidence"']
|
||||
assert _tokenize_fts_query('foo "bar baz" qux') == [
|
||||
"foo", '"bar baz"', "qux"
|
||||
]
|
||||
|
||||
|
||||
def test_tokenize_fts_query_handles_parentheses_as_tokens():
|
||||
"""OR-expansion produces queries like `(a OR b)`; the tokenizer
|
||||
must preserve `(` and `)` as standalone tokens (round-trip)."""
|
||||
from arborist.qa.aliases import _tokenize_fts_query
|
||||
|
||||
assert _tokenize_fts_query("(a OR b)") == ["(", "a", "OR", "b", ")"]
|
||||
|
||||
|
||||
def test_tokenize_fts_query_unterminated_quote_falls_back():
|
||||
"""A user query with a stray opening quote shouldn't lose data —
|
||||
the unmatched-quote tail becomes one token."""
|
||||
from arborist.qa.aliases import _tokenize_fts_query
|
||||
|
||||
out = _tokenize_fts_query('foo "bar baz')
|
||||
assert out[0] == "foo"
|
||||
assert "bar baz" in out[-1]
|
||||
|
||||
|
||||
def test_quote_for_fts_passes_through_already_quoted():
|
||||
from arborist.qa.aliases import _quote_for_fts
|
||||
|
||||
assert _quote_for_fts('"line incidence"') == '"line incidence"'
|
||||
assert _quote_for_fts("incidence") == "incidence"
|
||||
|
||||
|
||||
def test_quote_for_fts_quotes_multiword_bare_token():
|
||||
"""Defense-in-depth: a bare token that contains a space gets
|
||||
quoted (shouldn't happen via _tokenize_fts_query but the helper
|
||||
is defensive)."""
|
||||
from arborist.qa.aliases import _quote_for_fts
|
||||
|
||||
assert _quote_for_fts("two words") == '"two words"'
|
||||
|
||||
|
||||
def test_match_quoting_quoted_reference():
|
||||
from arborist.qa.aliases import _match_quoting
|
||||
|
||||
# Quoted reference → quoted alt.
|
||||
assert _match_quoting('"line incidence"', "line connection") == '"line connection"'
|
||||
# Bare reference → bare alt.
|
||||
assert _match_quoting("incidence", "connection") == "connection"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue