functions-js icon indicating copy to clipboard operation
functions-js copied to clipboard

Negative tests for edge functions with Deno

Open ghost opened this issue 2 years ago • 4 comments
trafficstars

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:

  1. Create edge function
  2. Create negative test for edge function
  3. 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

ghost avatar Aug 24 '23 13:08 ghost

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));
      }
    }
  }
});}

LaskeJu avatar Nov 20 '23 21:11 LaskeJu

Also running into this when running tests with supabase-js, it seems to only happen on tests that are testing for an error response

carlosdp avatar Feb 05 '24 16:02 carlosdp

Any news on this?

chrissy0 avatar Mar 07 '24 13:03 chrissy0

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.

hammerlscs avatar Mar 07 '24 13:03 hammerlscs