Search, Filters and Sorting
How search, filters and sorting work behind the scenes, where they usually break, and how to test them on websites and mobile apps, with a hands-on bug hunt in a broken shop.
You type “running shoes” into a shopping app, tap Men, tap Under $100, sort by Top rated, and expect a tidy list of exactly what you asked for. You do this in shops, food delivery apps, banking transaction lists, travel sites and music players, often dozens of times a day.
Because people use search constantly, they notice instantly when it’s wrong: a missing product, a count that doesn’t add up, a price list in a strange order. And a shopper who can’t find a product can’t buy it. Search bugs cost real money. Let’s learn how these features work and how testers break them.
How it works
Search, filters and sorting are three separate features that work together on one results screen.
Search: from query to results
- The user types a query. For example
mug. Many apps start searching while you type (“search as you type”); others wait for the Search key or button. - The app waits a moment (debounce). A good app doesn’t send a request on every keystroke. It waits until you pause typing for around 200–500 ms. This is called a debounceDebounceWaiting until the user stops typing for a moment before reacting, for example before searching.Open in glossary →.
- The app sends a request. Something like
GET /api/search?q=muggoes to the server’s APIAPIThe way different software parts talk to each other, like an app asking a server for data.Open in glossary →. Filters and sort order are usually sent along:&cat=kitchen&sort=price_asc. - The server finds matches. It normalizes the query (trims spaces, ignores upper/lower case, often ignores accents like é) and ranks results by relevance.
- The app shows the results. It shows a loading stateLoading stateWhat the UI shows while it waits for data or an action to finish, such as a spinner or skeleton.Open in glossary → while waiting, then the results, a results count and the matched words highlighted. If nothing matches, it shows an empty stateEmpty stateThe screen a user sees when there is no content yet, like an empty cart or no search results.Open in glossary → with a helpful message.
- More results load on demand. Long lists are split into pages: numbered pagination (“Page 2 of 8”) or infinite scroll (the next batch loads as you reach the bottom).
Extra helpers you’ll often meet:
- Autocomplete / suggestions: a dropdown under the search box with suggested queries or products while you type (“mug” → “mug set”, “travel mug”).
- Recent searches: your last few queries, shown when you tap the empty search box. They should be removable and private to your account or device.
- Spelling tolerance: “headphnes” still finds headphones, or the app asks “Did you mean headphones?”
See for yourself why debouncing matters. Type quickly with the debounce on, then turn it off and try again:
Try it: type “wireless earbuds” quickly
Keystrokes
0
Requests sent
0
Network log
- No requests yet…
Filters: narrowing the list
Filters let the user narrow results by attributes: category, price range, size, rating, availability.
| Filter type | Looks like | Example |
|---|---|---|
| Chips | Small pill buttons you tap on and off | Kitchen, In stock, 4★ & up |
| Checkboxes | A list in a side panel or bottom sheet | Brand: ☐ Nike ☐ Adidas ☐ Puma |
| Range | A slider with two handles, or min/max fields | Price: $20 – $100 |
| Single choice | Radio buttons or a dropdown | Delivery: Today / This week |
| Toggle | A switch | Free shipping only |
Things every filter UI should have:
- A filter count badge, like Filters (3), so the user knows filters are active even when the panel is closed.
- Clear all to remove every filter at once, and a way to remove a single filter (often an × on the chip).
- An updated results count after every change.
Sorting: putting results in order
Sorting changes the order, never the set of results. The count must stay the same when you change the sort.
| Sort option | Correct order | Watch out for |
|---|---|---|
| Relevance (default) | Best match first | Exact matches should beat partial ones |
| Price: low to high | $5.49, $8.99, $12.50, $100 | Sorting prices as text gives $100 before $12.50 |
| Price: high to low | The reverse | Sale prices vs. original prices: which one is used? |
| Top rated | 4.9 before 4.1 | Products with 1 review of 5★ ranking above 2,000 reviews of 4.8★ |
| Newest | Most recently added first | Time zones and items with the same date |
Ties happen all the time: two products cost $19.99. A good sort is stable: items that tie keep a consistent order (for example, by relevance), so they don’t jump around every time you reload or load the next page. Unstable ties can even cause a product to appear on page 1 and page 2, while another product never appears at all.
URL state on the web
On a website, the current search, filters and sort should live in the address bar:
shop.example.com/search?q=mug&cat=kitchen&sort=price_asc
This gives users three important things:
- Shareable links: paste the URL to a friend and they see the same results.
- Back button works: open a product, press Back, and you return to the same filtered list, ideally at the same scroll position.
- Refresh keeps state: reloading the page doesn’t wipe your filters.
Mobile apps don’t have an address bar, but the same idea applies: going back from a product should keep your query, filters, sort and scroll position. Some apps also support deep linksDeep linkA link that opens a specific screen inside an app instead of just its home screen.Open in glossary → that open a pre-filtered search.
Example requirements
Notice how testable each line is. Criterion 7 alone gives you a check to run after every other test. Learn more in acceptance criteriaAcceptance criteriaConditions a user story must meet to be considered done and accepted.Open in glossary → and user storyUser storyA short description of a feature from the user's point of view.Open in glossary →.
What usually goes wrong
| # | Bug | What you see | Typical severity |
|---|---|---|---|
| 1 | Out-of-order responses | You typed “mug” but see results for “m”, usually after typing fast | High |
| 2 | Strict text matching | “cafe” doesn’t find “Café”, “Mug” finds things “mug” doesn’t, “mugs” finds nothing | Medium–High |
| 3 | Wrong results count | “24 results” above a list of 9 products | Medium |
| 4 | Clear all only clears the UI | Chips look unselected, but the list is still filtered | High |
| 5 | Text sorting of numbers | $100 listed before $12.50 when sorting low to high | High |
| 6 | Missing empty state | Blank screen or a spinner that never stops when nothing matches | Medium |
| 7 | Filter and search ignore each other | Applying a filter clears the query, or a new search drops the filters | High |
| 8 | Wrong AND/OR logic | Selecting two categories shows fewer results instead of more | High |
| 9 | Lost state on Back | Returning from a product resets filters and scrolls to the top | Medium |
| 10 | Pagination duplicates | The same product appears on page 1 and page 2, or one never appears | Medium |
| 11 | Unsafe input handling | Special characters like ' or < cause an error page or break the layout | High (security) |
| 12 | Request flood | Every keystroke sends a request, slowing the app and the server | Low–Medium |
Find the bug
The home goods shop below has a search page with six bugs. Explore it like a real tester:
- Type slowly, then type quickly, and watch the network log.
- Search for words with and without accents.
- Turn filters on, combine them, then press Clear all.
- Try every sort option and check the prices.
- Search for something that doesn’t exist.
- Compare the results count with what you can actually see.
🐞 Bug hunt: Nook & Co. shop search
This demo has 6 hidden bugs. Explore it like a tester, then check your findings.
Nook & Co.
Home goods & more18 results
- Stoneware Coffee Mug4.6Kitchen$12.50
- Café Espresso Beans 1 kg4.8Kitchen$24.99
- Cafe Bistro Chair4.1Home$129.00
- Travel Mug with Lid4.3OutdoorOut of stock$19.00
- Linen Table Lamp3.9Home$64.00
- Camping Lantern4.5Outdoor$39.00
- Wireless Earbuds4.2Tech$89.00
- Crème Brûlée Torch4.0Kitchen$32.00
- Wool Throw Blanket4.7Home$45.00
- Two-Person Tent4.4Outdoor$249.00
- USB-C Charging Cable3.6Tech$9.99
- Ceramic Mug Set (4)4.9Kitchen$100.00
- Scented Candle4.1HomeOut of stock$8.99
- Bluetooth Speaker4.6Tech$110.00
- Insulated Water Bottle4.4Outdoor$18.00
- Silicone Spatula3.8Kitchen$5.49
- Desk Lamp with USB Port4.0Tech$15.00
- Pour-Over Coffee Maker4.3Kitchen$7.50
Network log
- Type in the search box to see API requests…
- 1
Hint: Type "lamp" as fast as you can and watch the network log.
- 2
Hint: Search for "cafe", then for "café".
- 3
Hint: Turn on "4★ & up" and count the products.
- 4
Hint: Select Tech, then press Clear all.
- 5
Hint: Sort by "Price: low to high" and read the prices top to bottom.
- 6
Hint: Search for something the shop doesn't sell, like "piano".
Test scenarios
Group your ideas so you don’t forget whole areas. A test scenarioTest scenarioA high-level idea of what to test, such as 'User resets a forgotten password'.Open in glossary → is what to check; you’ll turn the important ones into test cases next.
Functional
- Search by a full product name, a partial word (“lam” finds “Lamp”) and a word from the middle of a name.
- Search is triggered by typing (after the debounce), by the Search/Enter key and by the search button.
- Each filter on its own narrows the list correctly.
- Two values in one group (OR) make the list bigger; filters from different groups (AND) make it smaller.
- Search and filters work together: changing one keeps the other.
- Each sort option orders the list correctly, and the results count doesn’t change when sorting.
- Ties are stable: products with the same price keep the same order after reload and across pages.
- Results count is correct after every search, filter and sort change.
- Pagination or infinite scroll: no duplicates, no gaps, the last page ends cleanly.
- Autocomplete suggestions match the query and tapping one runs the search.
- Recent searches are saved, shown in the right order (newest first), and can be removed one by one or all at once.
- Web: URL updates; Back, Forward, refresh and a shared link restore the same state.
Negative and edge cases
This is where negative testingNegative testingTesting with invalid or unexpected input to check the software handles it gracefully.Open in glossary → and edge casesEdge caseAn unusual situation at the extreme of what the software should handle.Open in glossary → shine. Try each of these queries:
| Query | What to check |
|---|---|
| (empty) | Pressing Search does nothing, or shows all products or recent searches. Never an error |
" " (only spaces) | Treated like an empty query. Not “No results for ’ ’” |
" mug " | Leading/trailing spaces are ignored; finds the same as mug |
MUG, Mug, mUg | Same results as mug (case-insensitive) |
cafe vs café | Same results (accents, called diacritics, are ignored) |
mugs vs mug | Plurals ideally find the same products |
mgu, headphnes | Typos: “Did you mean…?” or fuzzy matches, at least a friendly empty state |
%, &, _, #, + | No error; the character is searched literally (% and _ are wildcards in some databases) |
' or " | No error page. A crash here can hint at SQL injectionSQL injectionAn attack where text typed into a field is run as a database command.Open in glossary → |
<b>hi</b> | Shown as plain text, never rendered as bold HTML (if it renders, that’s a sign of Cross-site scripting (XSS)Cross-site scripting (XSS)An attack where text a user enters is run as code in other people's browsers.Open in glossary → risk) |
| 300+ characters | Field limits input or handles it; layout doesn’t break; no server error |
Emoji ☕ and non-Latin text кофе | No crash; sensible results or empty state |
| A price range where min > max | Prevented or swapped, with a clear message |
| Filters that match nothing | Empty state that suggests removing filters |
UI and usability
- A loading indicator appears while waiting and always disappears afterwards.
- The empty state explains what happened and what to do next (“Check the spelling or clear filters”).
- The search box has a clear (×) button that empties the field and resets the results (more in Search bar).
- On mobile, the keyboard shows a Search key (not “Return”), and pressing it hides the keyboard.
- Highlighting marks the right part of the name, including when case or accents differ.
- The filter badge count matches the number of active filters.
- Long product names and long queries are truncated nicely, not overlapping prices or buttons.
- The placeholderPlaceholderHint text shown inside an empty input field that disappears when the user starts typing.Open in glossary → text explains what you can search (“Search products”).
Performance
- Results appear within the agreed time (for example, under 1 second on a normal connection).
- Typing fast doesn’t send a request for every keystroke (check the network tab in DevToolsDevToolsDeveloper tools built into browsers for inspecting pages, network traffic and errors.Open in glossary →).
- Old requests are canceled or ignored, so results never flicker between queries.
- Scrolling a long list (hundreds of items, infinite scroll) stays smooth.
- On a slow or offline connection, the app shows a loading state and then an error message, not a frozen screen.
Accessibility
- The search field has a label that screen readersScreen readerSoftware that reads the screen aloud for blind and low-vision users, like VoiceOver or TalkBack.Open in glossary → announce (“Search products, search field”).
- After results load, a screen reader announces the count (“12 results”).
Dev note
For example with anaria-liveregion on the web. - Filter chips announce their state: “Kitchen, toggle button, selected”.
Dev note
aria-pressedon the web. - Everything works with a keyboard: Tab to the field, type, Enter to search, arrow keys in autocomplete, Esc closes suggestions.
- Highlighting doesn’t rely on color alone (bold text helps), and text keeps 4.5:1 contrast.
- Chips and the clear button are big enough to tap: 44×44 pt on iOS, 48×48 dp on Android.
Example test cases
TC-SRCH-001Search by partial product namepositivehigh
Preconditions
- Catalog contains "Linen Table Lamp" and "Desk Lamp with USB Port"
Steps
- Open the search page
- Type "lamp"
- Wait 1 second
Test data
Query: lamp
Expected result
Exactly the two lamp products are shown, "lamp" is highlighted in each name, and the count says "2 results for 'lamp'".
TC-SRCH-002Search ignores case, spaces and accentsedgehigh
Steps
- Search for "cafe"
- Note the results
- Search for " CAFÉ "
Expected result
Both searches return the same products, including "Café Espresso Beans" and "Cafe Bistro Chair".
TC-SRCH-003Fast typing shows results for the final query onlyedgehigh
Preconditions
- Network throttled to "Slow 4G" in DevTools
Steps
- Type "lamp" as fast as possible
- Wait 3 seconds without typing
Expected result
Only lamp products are shown. At most one or two requests appear in the network tab, and the list never switches to results for "l" or "la".
TC-SRCH-004No results shows a helpful empty statenegativemedium
Steps
- Search for "piano"
Expected result
The loading indicator disappears and the page shows "No results for 'piano'" with a tip to check spelling or remove filters.
TC-SRCH-005Filters in different groups combine with ANDpositivehigh
Steps
- Tap "Kitchen"
- Note the count
- Tap "4★ & up"
Expected result
The list shows only Kitchen products rated 4.0 or higher, and the count shrinks to match the number of visible products.
TC-SRCH-006Clear all removes every filter from the resultspositivehigh
Steps
- Tap "Tech" and "In stock"
- Tap "Clear all"
Expected result
All chips are unselected, the filter badge disappears and all products are shown with the full count.
TC-SRCH-007Price sort is numericpositivehigh
Steps
- Select sort "Price: low to high"
- Read prices from top to bottom
- Select "Price: high to low"
Expected result
Low to high starts with $5.49 and ends with $249.00, each price ≥ the one above. High to low is the exact reverse. The count does not change.
TC-SRCH-008Back button restores search state (web)positivemedium
Steps
- Search "mug", tap "Kitchen", sort by "Top rated"
- Open any product
- Press the browser Back button
Expected result
The URL, query, chip, sort and results are the same as before opening the product, and the scroll position is kept.
TC-SRCH-009Special characters are handled safelynegativehigh
Steps
- Search for each: ' " % _ <b>x</b>
Expected result
No error page or broken layout. The query is shown as plain text in the empty state or results.
Tip: click a test case to expand it.
Mobile vs web
- Keyboard: check that the keyboard shows a Search key and that it runs the search and hides the keyboard. Check the clear (×) button and the Cancel button on iOS search bars.
- Filters in a bottom sheet: filters often open in a sheet with an Apply button. Test closing the sheet without applying: changes should be discarded.
- Infinite scroll is more common than numbered pages. Scroll to the end, then rotate the device and check nothing is duplicated or lost.
- State: open a product, go back, send the app to the background and return. Query, filters, sort and scroll position should survive.
- Voice input and paste: dictating or pasting a query should trigger a search just like typing.
- Bad networks: switch to airplane mode mid-search. Expect a clear error and a Retry option.
- Recent searches are often stored on the device, so check they are cleared on log out.
- URL state: every change should update the URL. Test Back, Forward, refresh and opening a copied link in a private window.
- Network tab: open DevToolsDevToolsDeveloper tools built into browsers for inspecting pages, network traffic and errors.Open in glossary →, filter by “search”, type quickly and count the requests. Throttle to “Slow 4G” to expose race conditions.
- Pagination: check page numbers, “Next” on the last page, and changing a filter while on page 3 (it should usually return to page 1).
- Keyboard: Tab, Enter, arrow keys in autocomplete, Esc to close suggestions, visible focus on chips.
- Responsive layout: filters in a sidebar on desktop often become a “Filters” button with a drawer on small screens. Test both. See responsive designResponsive designA website layout that adapts to different screen sizes, from phones to large monitors.Open in glossary →.
- Browser autofill: the browser’s own suggestions shouldn’t cover the site’s autocomplete list.
- Cross-browser: test accent-insensitive search and sorting in Chrome, Safari and Firefox, because text handling can differ.
Checklist
Search, filters and sorting checklist
0 of 18 checked
Check your understanding
Quick quiz
0/5 answered · 0 correct
1.You type "mug" quickly. The box says "mug", but the list shows products containing "m". What is the most likely cause?
2.You select the "Kitchen" and "Home" category chips. What should usually happen to the number of results?
3.Sorted by "Price: low to high", the list shows $100, $110, $12.50, $129, $15. What is the bug?
4.Which query is the best check for accent handling?
5.Why should search filters and sort be stored in the URL on a website?
Key takeaways
- Search flows from query → debounce → request → results, with loading, empty and error states along the way.
- The nastiest search bug is the race condition: type fast on a slow network and check you see results for the final query.
- Test queries with case, spaces, accents, plurals, typos, special characters and extreme lengths.
- Filters: OR within a group, AND between groups. Check the badge, Clear all, and that search and filters keep each other.
- Sorting changes the order, never the set. Check numeric price sorting and stable ties.
- After every action, check that the results count matches the list.
- On the web, state belongs in the URL; on mobile, it must survive Back, rotation and backgrounding.
Finished this page?Nice work, this page is complete!
Mark it as done to track your progress. It's saved in this browser, no account needed.
Its review cards are now in Bites ⚡