functions-js
functions-js copied to clipboard
Negative tests for edge functions with Deno
Bug report
- [x] I confirm this is a bug with Supabase, not with my own application.
- [x] I confirm I have searched the Docs, GitHub Discussions, and Discord.
Describe the bug
I am trying to write some negative tests for my edge functions, for example:
const testSomeFunction = async () => {
const { data, error } = await supabaseUser.functions.invoke('some-function', {
body: {
userId: 'invalid-id'
}
})
assertEquals(error.message, 'Edge Function returned a non-2xx status code')
assertEquals(data, null)
}
But when running deno test, the test fails with:
error: Leaking resources:
- A fetch response body (rid 18) was created during the test, but not consumed during the test. Consume or close the response body `ReadableStream`, e.g `await resp.text()` or `await resp.body.cancel()`.
But I cannot access the response to consume/close/cancel/... it.
To Reproduce
Steps to reproduce the behavior, please provide code snippets or a repository:
- Create edge function
- Create negative test for edge function
- Run
deno test
Expected behavior
I expect the test to pass, without any leaking resources.
System information
- OS: Windows 11
- Version of supabase-js: 2.26.0
- Version of Node.js: 18.15.0
- Version of Deno: 1.36.2
Ugly workaround to make my tests pass ...
Deno.test("Test something", async () => {
try {
await testSomething();
} catch (error) {
console.error(error);
} finally {
const resources = Deno.resources();
for (const rid in resources) {
if (resources[rid] === "fetchResponse") {
Deno.close(parseInt(rid));
}
}
}
});}
Also running into this when running tests with supabase-js, it seems to only happen on tests that are testing for an error response
Any news on this?
This worked for us:
const { data, error } = await supabaseUser.functions.invoke('some-function', {
body: {
userId: 'invalid-id'
}
})
assertEquals(data, null)
await assertError(error, 'expected error message')
And:
export async function assertError(
error: FunctionsHttpError | FunctionsRelayError | FunctionsFetchError,
expectedErrorMessage: string,
) {
assertEquals(error.name, 'FunctionsHttpError')
const { message: actualErrorMessage }: { message: string } = await error.context.json()
assertEquals(
actualErrorMessage,
expectedErrorMessage,
)
}
Because we always return a message with an error response:
const responseData = { message, data }
return new Response(JSON.stringify(responseData), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: httpStatusCode,
})
Which we can assert in the edge function test.