Founder & Lead Engineer, RAITHub
On a property portal, the bugs buyers meet first are in search and filters: a price range that excludes a listing priced exactly at the boundary, a map that drops results at its edge, filters that combine wrongly, facet counts that lie, and a sort order that reshuffles between pages. Test the boundaries, the combinations and the counts, because the happy-path search everyone demos rarely breaks.
If you would rather have it tested for you, see how RAITHub would test this below. This is a reusable test plan for any property portal's search, whoever built it, and it pairs with the broader pre-launch QA checklist.
Why are search and filters where portals break?
Because every filter is a boundary, and boundaries are where off-by-one bugs live. A buyer sets "up to 500,000" and a home at exactly 500,000 should appear; half the time it doesn't. They draw a box on the map and a listing on the line vanishes. They pick "3+ beds" and "garage", and the two conditions are combined with OR instead of AND, flooding the page. None of these throw an error, so they pass a green build and only a human or a boundary test catches them. Listing correctness upstream is its own topic (listing moderation for property portals); this post is about whether search returns the right set.
How do you test price and numeric range filters?
Test the edges, not the middle. For every range filter, seed a listing exactly on each boundary and assert it is included (for an inclusive range) or excluded, consistently. Test an inverted range (min above max), an empty range, and very large numbers.
// tests/search/price-range.spec.ts
import { test, expect } from '@playwright/test'
import { seedListing, search } from './helpers'
test('a listing priced exactly at the max is included', async ({ request }) => {
await seedListing({ ref: 'edge', price: 500000 })
const results = await search(request, { priceMax: 500000 })
expect(results.map((r) => r.ref)).toContain('edge') // boundary included
})
test('min above max returns nothing, not everything', async ({ request }) => {
const results = await search(request, { priceMin: 900000, priceMax: 100000 })
expect(results).toEqual([]) // inverted range is empty, not unfiltered
})
How do you test map-bounds and radius search?
Geographic search has its own edges: a listing exactly on the boundary of the map viewport, a listing right at a radius limit, properties near the 180th meridian or the poles, and the difference between "within this box" and "within this circle". Seed listings at known coordinates and assert which the search returns.
| Case | What to assert |
|---|---|
| On the viewport edge | Included or excluded, but consistently; not flickering as you pan |
| Exactly at the radius | Defined behaviour (inclusive), tested at the limit |
| Just outside the box | Excluded; it must not leak in |
| Pan and zoom | Results update to match the new bounds; none stale |
| No results in view | A clear empty state, not a spinner or old results |
How do you test combined filters and facet counts?
Buyers stack filters, and the combination is where logic goes wrong. Assert that two filters combine with AND (3+ beds AND garage), that a facet count equals the number of results that facet would actually return, and that applying the facet then yields exactly that many. A facet that says "Garage (12)" and then shows 7 results is a trust-killer.
// tests/search/facets.spec.ts
import { test, expect } from '@playwright/test'
import { search, facetCount } from './helpers'
test('a facet count matches the results it yields', async ({ request }) => {
const claimed = await facetCount(request, { feature: 'garage' })
const results = await search(request, { feature: 'garage' })
expect(results.length).toBe(claimed) // the count cannot lie
})
How do you test pagination and sort together?
Sort and pagination interact badly when the sort is not stable. If two listings share a sort value (same price, say) and the tie is broken randomly, the same listing can appear on page 1 and page 2, or vanish between them. Assert a stable sort (a deterministic tiebreaker, such as id), that no listing is duplicated or missing across pages, and that the total count matches the sum of the pages. Changing a filter should reset to page 1, not strand the user on an empty page 9.
What other edges lose listings?
- Special characters and other languages in a free-text search, including Arabic or accented place names, must not break the query or drop results (RTL correctness is a known portal risk).
- Stale results after a listing changes state: a sold or withdrawn listing should leave the results promptly.
- Saved searches: a saved filter set returns the same results when re-run, and alerts fire for genuinely new matches only.
- Performance: search stays fast as listings grow; a slow filter is a conversion bug, not just a speed one.
Buy, build or hire this testing?
| Option | What you get | Choose this when |
|---|---|---|
| Manual spot-checks | A quick look before release | A tiny catalogue and few filters |
| A test library you write | Boundary and facet tests you maintain | You have the skill and time to cover the edges and keep them green |
| A pre-launch QA audit | A tester works the search edges and hands you a ranked bug report | You are about to launch and want the search bugs found first |
| A monthly QA plan | Search and filter suites gated in CI, retested every release | Listings and filters keep changing and search must stay correct |
How RAITHub would test this
- Scope: boundary tests for every range filter, map-bounds and radius cases, combined-filter logic, facet-count correctness, stable sort and pagination, saved searches, and a performance check as the catalogue grows.
- Timeline: a fixed-scope pre-launch audit is a one-off checkpoint; ongoing coverage runs as a monthly QA plan, with the first weeks on the risky journeys.
- What you receive: a ranked bug report with reproduction steps, and automated search and filter tests in your repository, gated in CI and owned by you.
- Ways to buy it: a one-off pre-launch QA or a monthly QA plan; the same engineers can fix what they find under a separate quote.
- Next step: a free 15-minute technical audit, then a fixed written quote.
See the QA as a Service page, the AI app testing service if an AI tool built your portal, or book the free 15-minute audit. For a portal build from scratch, see the SaaS development service and how to build a portal like Property Finder or Bayut. The wider real-estate context is on the real-estate industry page.
Documentation checked on 10 October 2026.
Frequently asked questions
What are the most common search bugs on a property portal?
Range filters that exclude the boundary value, map searches that drop listings at the edge, combined filters joined with OR instead of AND, facet counts that don't match the results, and unstable sorts that duplicate or lose listings between pages. None of them throw errors, so they slip past a green build.
How do you test a price range filter?
Test the edges. Seed a listing priced exactly at the minimum and one at the maximum and assert they are included or excluded consistently, then test an inverted range (min above max), an empty range and very large numbers. The middle of the range almost never breaks; the boundaries do.
How do you test map-bounds search?
Seed listings at known coordinates, including ones exactly on the viewport edge and at a radius limit, and assert which the search returns. Check that panning and zooming update the results, that nothing just outside leaks in, and that an empty view shows a clear empty state.
Why do facet counts need their own tests?
Because a count that says "Garage (12)" and then returns 7 results destroys trust. A test asserts that the facet's stated count equals the number of results applying it actually yields, so the numbers the buyer relies on cannot lie.
Can RAITHub test a portal it did not build?
Yes. RAITHub tests the running portal, so who built it matters less than the stack. A pre-launch QA audit hands you a ranked bug report, and a monthly QA plan adds search and filter tests to your repository, gated in CI and retested every release.
Related posts
Ready to discuss your project?
Book a free 15-minute technical audit with our engineering team.