WZWren / night-sentry

0 stars 0 forks source link

Supabase Authentication Testing with Jest #8

Closed WZWren closed 1 year ago

WZWren commented 1 year ago

Supabase Auth is integrated with the app using listeners provided by Supabase, so it is rather hard to directly mock functions for Supabase Auth as we are treating its functions like a black box. It is not feasible to have the app be tested by making real calls to the DB for every test, so the plan is to use the Nock library to intercept POST requests to the Auth service.

WZWren commented 1 year ago

On closer inspection, it seems Nock does not properly intercept POST requests made by Supabase. This is possibly due to Supabase using the fetch method supplied starting from Node 18+, which Nock is unable to intercept due to no support for the Undici library. We therefore move the plan to MSW, which does provide support for the fetch method.

WZWren commented 1 year ago

MSW does not natively capture the requests sent out by Supabase run in the Jest environment on Node 18.16.0. As the native fetch should have been used, we also tried using Undici's own mock methods. However, Undici's mocking only works on fetch supplied with its library, and testing with it has proven this fact.

To confirm this interaction, inspection was done on the open-sourced Supabase Auth methods. There, we see that Supabase uses a resolveFetch method to find the relevant fetch:

... if (customFetch) { _fetch = customFetch } else if (typeof fetch === 'undefined') { _fetch = crossFetch as unknown as Fetch } else { _fetch = fetch } return (...args) => _fetch(...args) }

From this, we conclude that Supabase Auth is defining its fetch as fetch of cross-fetch or native fetch of Node 18. However, MSW still does not detect the fetch trigger of Supabase, which was odd. Using jest.spyOn on the global scoped fetch does not help us in detecting calls to the fetch either.

Final Fix

As customFetch directly bypasses the ambiguity of the fetch issue, and it is known that cross-fetch should work with MSW, mocking the supabase Client object was deemed to be more favorable as a fix to this issue. We call createClient with an additional fetch: crossFetch field - given that supabase uses crossFetch as their chosen polyfill when the client does not have a fetch method, this is a safe library to use as our main fetcher. jest.replaceProperty was called on our lib/supabase object to "mock" the object and replace it with a more favorable fetch method. Running the MSW server on this test works as expected.

Remarks to consider

The MSW library should have Node 18+ fetch support. However, testing it like so does not seem to let us intercept the API call. Even though no further testing will be done on this for this period, a thread was found on MSW where it lists the support under msw@next.