aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_filtering.py
diff options
context:
space:
mode:
authorLouis Burda <dev@sinitax.com>2026-02-28 18:54:19 +0100
committerLouis Burda <dev@sinitax.com>2026-02-28 18:54:19 +0100
commitbe1dd21f8e4fbd5361531b4d8727a0d0d243e8ec (patch)
treee7b540012e0510d1304d2dac8e137545ae103f75 /tests/test_filtering.py
parentd70a199a72bf9a69eb4a3fcf166b0435918b2e33 (diff)
downloadselectui-main.tar.gz
selectui-main.zip
Add tests and justfileHEADmain
Diffstat (limited to 'tests/test_filtering.py')
-rw-r--r--tests/test_filtering.py318
1 files changed, 318 insertions, 0 deletions
diff --git a/tests/test_filtering.py b/tests/test_filtering.py
new file mode 100644
index 0000000..43a2e9b
--- /dev/null
+++ b/tests/test_filtering.py
@@ -0,0 +1,318 @@
+from thefuzz import fuzz
+
+
+class TestExactFiltering:
+ """Test exact string matching."""
+
+ def test_filter_by_title_case_insensitive(self, sample_items):
+ """Test filtering by title (case insensitive)."""
+ query = "python"
+ filtered = []
+
+ for item in sample_items:
+ title = str(item.get("title", "")).lower()
+ subtitle = str(item.get("subtitle", "")).lower()
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 1
+ assert filtered[0]["title"] == "Python"
+
+ def test_filter_by_subtitle(self, sample_items):
+ """Test filtering by subtitle."""
+ query = "web"
+ filtered = []
+
+ for item in sample_items:
+ title = str(item.get("title", "")).lower()
+ subtitle = str(item.get("subtitle", "")).lower()
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 1
+ assert filtered[0]["title"] == "JavaScript"
+
+ def test_filter_no_matches(self, sample_items):
+ """Test filtering with no matches."""
+ query = "nonexistent"
+ filtered = []
+
+ for item in sample_items:
+ title = str(item.get("title", "")).lower()
+ subtitle = str(item.get("subtitle", "")).lower()
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 0
+
+ def test_filter_all_match(self, sample_items):
+ """Test filtering that matches all items."""
+ query = "language"
+ filtered = []
+
+ for item in sample_items:
+ title = str(item.get("title", "")).lower()
+ subtitle = str(item.get("subtitle", "")).lower()
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 4
+
+ def test_filter_partial_match(self, sample_items):
+ """Test partial string matching."""
+ query = "rust"
+ filtered = []
+
+ for item in sample_items:
+ title = str(item.get("title", "")).lower()
+ subtitle = str(item.get("subtitle", "")).lower()
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 1
+ assert filtered[0]["title"] == "Rust"
+
+
+class TestCaseSensitiveFiltering:
+ """Test case-sensitive filtering."""
+
+ def test_case_sensitive_title_match(self, sample_items):
+ """Test case-sensitive title matching."""
+ query = "Python"
+ filtered = []
+
+ for item in sample_items:
+ title = str(item.get("title", ""))
+ subtitle = str(item.get("subtitle", ""))
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 1
+ assert filtered[0]["title"] == "Python"
+
+ def test_case_sensitive_no_match(self, sample_items):
+ """Test case-sensitive no match."""
+ query = "python" # lowercase
+ filtered = []
+
+ for item in sample_items:
+ title = str(item.get("title", ""))
+ subtitle = str(item.get("subtitle", ""))
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 0
+
+ def test_case_sensitive_subtitle_match(self, sample_items):
+ """Test case-sensitive subtitle matching."""
+ query = "Programming"
+ filtered = []
+
+ for item in sample_items:
+ title = str(item.get("title", ""))
+ subtitle = str(item.get("subtitle", ""))
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 1
+
+
+class TestFuzzyFiltering:
+ """Test fuzzy search functionality."""
+
+ def test_fuzzy_match_with_typo(self, sample_items):
+ """Test fuzzy matching with a typo."""
+ query = "Pythn" # Missing 'o'
+ filtered = []
+
+ for item in sample_items:
+ title = str(item.get("title", ""))
+ subtitle = str(item.get("subtitle", ""))
+ title_score = fuzz.partial_ratio(query, title)
+ subtitle_score = fuzz.partial_ratio(query, subtitle)
+ if title_score > 60 or subtitle_score > 60:
+ filtered.append(item)
+
+ assert len(filtered) >= 1
+ assert any(item["title"] == "Python" for item in filtered)
+
+ def test_fuzzy_match_partial(self, sample_items):
+ """Test fuzzy partial matching."""
+ query = "Jav"
+ filtered = []
+
+ for item in sample_items:
+ title = str(item.get("title", ""))
+ subtitle = str(item.get("subtitle", ""))
+ title_score = fuzz.partial_ratio(query, title)
+ subtitle_score = fuzz.partial_ratio(query, subtitle)
+ if title_score > 60 or subtitle_score > 60:
+ filtered.append(item)
+
+ assert len(filtered) >= 1
+ assert any(item["title"] == "JavaScript" for item in filtered)
+
+ def test_fuzzy_match_transposition(self, sample_items):
+ """Test fuzzy match with character transposition."""
+ query = "Rsut" # Characters swapped
+ filtered = []
+
+ for item in sample_items:
+ title = str(item.get("title", ""))
+ subtitle = str(item.get("subtitle", ""))
+ title_score = fuzz.partial_ratio(query, title)
+ subtitle_score = fuzz.partial_ratio(query, subtitle)
+ if title_score > 60 or subtitle_score > 60:
+ filtered.append(item)
+
+ assert len(filtered) >= 1
+ assert any(item["title"] == "Rust" for item in filtered)
+
+ def test_fuzzy_no_match(self, sample_items):
+ """Test fuzzy search with no close matches."""
+ query = "xyz123"
+ filtered = []
+
+ for item in sample_items:
+ title = str(item.get("title", ""))
+ subtitle = str(item.get("subtitle", ""))
+ title_score = fuzz.partial_ratio(query, title)
+ subtitle_score = fuzz.partial_ratio(query, subtitle)
+ if title_score > 60 or subtitle_score > 60:
+ filtered.append(item)
+
+ assert len(filtered) == 0
+
+
+class TestFilteringWithCustomKeys:
+ """Test filtering with custom key configurations."""
+
+ def test_filter_custom_title_key(self, custom_key_items):
+ """Test filtering with custom title key."""
+ query = "alice"
+ filtered = []
+ title_key = "name"
+ subtitle_key = "role"
+
+ for item in custom_key_items:
+ title = str(item.get(title_key, "")).lower()
+ subtitle = str(item.get(subtitle_key, "")).lower()
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 1
+ assert filtered[0]["name"] == "Alice"
+
+ def test_filter_custom_subtitle_key(self, custom_key_items):
+ """Test filtering with custom subtitle key."""
+ query = "engineer"
+ filtered = []
+ title_key = "name"
+ subtitle_key = "role"
+
+ for item in custom_key_items:
+ title = str(item.get(title_key, "")).lower()
+ subtitle = str(item.get(subtitle_key, "")).lower()
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 1
+ assert filtered[0]["role"] == "Engineer"
+
+ def test_filter_no_subtitle_key(self, single_line_items):
+ """Test filtering when subtitle_key is None."""
+ query = "config"
+ filtered = []
+ title_key = "filename"
+
+ for item in single_line_items:
+ title = str(item.get(title_key, "")).lower()
+ if query in title:
+ filtered.append(item)
+
+ assert len(filtered) == 1
+ assert filtered[0]["filename"] == "config.json"
+
+
+class TestEmptyQueryFiltering:
+ """Test filtering with empty query."""
+
+ def test_empty_query_returns_all(self, sample_items):
+ """Test that empty query returns all items."""
+ query = ""
+ filtered = sample_items.copy() if not query else []
+
+ assert len(filtered) == len(sample_items)
+
+ def test_whitespace_query(self, sample_items):
+ """Test filtering with whitespace-only query."""
+ query = " "
+ filtered = []
+
+ # Whitespace query should not match anything
+ for item in sample_items:
+ title = str(item.get("title", "")).lower()
+ subtitle = str(item.get("subtitle", "")).lower()
+ if query.strip() and (query.strip() in title or query.strip() in subtitle):
+ filtered.append(item)
+
+ assert len(filtered) == 0
+
+
+class TestFilteringEdgeCases:
+ """Test edge cases in filtering."""
+
+ def test_filter_with_missing_fields(self):
+ """Test filtering when items are missing title/subtitle."""
+ items = [
+ {"other_field": "value"},
+ {"title": "Has Title"},
+ ]
+
+ query = "title"
+ filtered = []
+
+ for item in items:
+ title = str(item.get("title", "")).lower()
+ subtitle = str(item.get("subtitle", "")).lower()
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 1
+
+ def test_filter_with_numeric_values(self):
+ """Test filtering with numeric values in fields."""
+ items = [
+ {"title": "Item 123", "subtitle": "Test"},
+ {"title": "Item 456", "subtitle": "Test"},
+ ]
+
+ query = "123"
+ filtered = []
+
+ for item in items:
+ title = str(item.get("title", "")).lower()
+ subtitle = str(item.get("subtitle", "")).lower()
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 1
+
+ def test_filter_special_characters(self):
+ """Test filtering with special characters."""
+ items = [
+ {"title": "test@example.com", "subtitle": "Email"},
+ {"title": "user-name", "subtitle": "Username"},
+ ]
+
+ query = "@"
+ filtered = []
+
+ for item in items:
+ title = str(item.get("title", "")).lower()
+ subtitle = str(item.get("subtitle", "")).lower()
+ if query in title or query in subtitle:
+ filtered.append(item)
+
+ assert len(filtered) == 1
+ assert "@" in filtered[0]["title"]