Andy
Andy3w ago

withSearchIndex does not return results when running tests, but does in production.

Assume you have the following query:
await db.query("tasks").withSearchIndex("search_name", (q) => q.search("name", taskName)).paginate(paginationOpts)
await db.query("tasks").withSearchIndex("search_name", (q) => q.search("name", taskName)).paginate(paginationOpts)
When running the code from the frontend, it functions as expected, returning results for exact and partial string matches; however, it returns no results when attempting to execute with convex-test via the following test:
test("returns a task", async () => {
const response = await asUser.query(api.tasks.listTasks, {
paginationOpts: { numItems: 10, cursor: null },
name: "Foo"
})
expect(response).toMatchObject({
continueCursor: "_end_cursor",
isDone: true,
page: [] // Search doesn't return tasks, just an empty array.
})
})
test("returns a task", async () => {
const response = await asUser.query(api.tasks.listTasks, {
paginationOpts: { numItems: 10, cursor: null },
name: "Foo"
})
expect(response).toMatchObject({
continueCursor: "_end_cursor",
isDone: true,
page: [] // Search doesn't return tasks, just an empty array.
})
})
Replacing the withSearchIndex method with withIndex returns results.
9 Replies
Convex Bot
Convex Bot3w ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
Convex Bot
Convex Bot3w ago
<@35h6nwr87agxv93r3r7a5v5a9fxnw28>: what version are you on? there was a change to support case-insensitive search in tests, in case that explains it?
Andy
AndyOP3w ago
"convex-test": "0.0.38", "convex": "1.25.4", "convex-helpers": "0.1.101", "vitest": "3.2.4" Even searching the exact string doesn't yield a result, so the case-insensitive change wouldn't apply.
ian
ian3w ago
I know this is a bit ridiculous, but could you add an insert with that string right above the query, just to sanity check the db didn't get wiped of that value between tests? or test that the withIndex results do include the record with the string? There's a bunch of tests that seem to match this syntax almost exactly, so it makes me wonder what the difference is https://github.com/get-convex/convex-test/blob/main/convex/textSearch.test.ts#L43-L64
GitHub
convex-test/convex/textSearch.test.ts at main · get-convex/convex-...
Testing harness for pure-JS Convex tests. Contribute to get-convex/convex-test development by creating an account on GitHub.
Michal Srb
Michal Srb3w ago
Also note that search doesn't behave exactly the same: https://docs.convex.dev/testing/convex-test#limitations
convex-test | Convex Developer Hub
Mock Convex backend for fast automated testing of functions
Andy
AndyOP2w ago
Thanks to your replies, I was able to reproduce the issue (2 cases).
1. convex-test does not return results when performing queries with spaces. The tests in textSearch.test.ts that @ian provided all have single word queries, which pass without issue (hello works while hello convex does not). 2. convex-test does not return results when filtering on undefined. Assume you have a deletionTime field that is only populated when a record is deleted – performing something like .eq("deletionTime", undefined) yields no results.
ian
ian2w ago
great call, thanks for digging in! When you say "filtering on undefined" you mean in the context of a withIndex right?
Andy
AndyOP2w ago
That's right, specifically when using the eq method, so for instance, the index: .searchIndex("name", { searchField: "name", filterFields: ["deletionTime"] }) Might be queried like so: .withSearchIndex("name", (q) => q.search("name", name).eq("deletionTime", undefined)) Expected result: Only undefined records are returned when using convex-test and in production. Actual result: No records are returned when using convex-test, but works in production. While on the subject of handling falsy values in search indexes, it may be worth noting that there's a similar behavior on the main query search, so q.search("name", "") returns no results. My expectation from using search engines in the past like elastic is that this would return all values (e.g. the search field is empty on the frontend and you want all results). This is pretty easy to circumvent but it gets somewhat wordy:
const result = name
? await db
.query("some_table")
.withSearchIndex("name", (q) => q.search("name", name).eq("deletionTime", undefined))
.paginate(paginationOpts)
: await db
.query("some_table")
.withIndex("by_name", (q) => q.eq("deletionTime", undefined))
.paginate(paginationOpts)
const result = name
? await db
.query("some_table")
.withSearchIndex("name", (q) => q.search("name", name).eq("deletionTime", undefined))
.paginate(paginationOpts)
: await db
.query("some_table")
.withIndex("by_name", (q) => q.eq("deletionTime", undefined))
.paginate(paginationOpts)
I wouldn't include this as part of this ticket as it has nothing to do with convex-test (behavior is the same in prod), but just putting it out there in case it's helpful in any way.
ian
ian2w ago
GitHub
Update text search to split queries on whitespace and verify withIn...
Update text search to split queries on whitespace and verify withIndex undefined handling Summary This PR modifies the text search implementation in convex-test to split search queries on whitespac...

Did you find this page helpful?