1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
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"]
|