I want to mock supabase.auth.signUp
of @supabase/supabase-js
. I am not directly calling supabase.auth.signUp
, but in a wrapper I created. If I don't use jest.fn()
, but a default JS function, it is correctly resolving the object I want. However this does not give me the flexibility of resolving with different values in different tests...
import { createClient } from "@supabase/supabase-js";
export const supabase = createClient(
process.env.REACT_APP_SUPABASE_URL as string,
process.env.REACT_APP_SUPABASE_ANON_KEY as string
);
// This default function does work...
// export const supabase = {
// auth: {
// signUp: () =>
// Promise.resolve({ data: { user: null, session: null }, error: null }),
// },
// };
// This jest.fn() does not work and returns undefined?
export const supabase = {
auth: {
signUp: jest
.fn()
.mockResolvedValue({ data: { user: null, session: null }, error: null }),
// mockImplementation does the same
// .mockImplementation(() =>
// Promise.resolve({ data: { user: null, session: null }, error: null })
// ),
},
};
import Auth from "../interfaces/Auth";
import Credentials from "../interfaces/Credentials";
import Error from "../interfaces/Error";
import { supabase } from "./supabase";
export default async function signUp(
credentials: Credentials
): Promise<{ auth: Auth; error: Error | null }> {
const { data, error } = await supabase.auth.signUp({
email: credentials.email,
password: credentials.password,
});
...
}
import Credentials from "../interfaces/Credentials";
import signUp from "./signUp";
jest.mock("./supabase");
// This call does return the correct value?
console.log(supabase.auth.signUp({email: "test@example.com", password: "password"}))
test("successful sign up", async () => {
const credentials: Credentials = {
email: "test@example.com",
password: "password",
};
const { auth, error } = await signUp(credentials);
console.log({auth, error})
expect(auth.user).toBeDefined();
expect(auth.session).toBeNull();
});
FAIL src/supabase/signUp.test.ts
● successful sign up
TypeError: Cannot destructure property 'data' of '(intermediate value)' as it is undefined.
8 | params: Credentials
9 | ): Promise<{ auth: Auth; error: Error | null }> {
> 10 | const { data, error } = await supabase.auth.signUp({
| ^
11 | email: params.email,
12 | password: params.password,
13 | });
at signUp (src/supabase/signUp.ts:10:11)
at Object.<anonymous> (src/supabase/signUp.test.ts:12:27)
How can I make supabase.auth.signUp
resolve with a mocked value inside src/supabase/signUp.ts
while I am executing src/supabase/signUp.test.ts
?
Thanks in advance.
U can use jest.spyOn to spy on the signUp function, I already tried this but in a global scope, make sure to use it in a beforeEach, or in the actual test itself. beforeAll and global scope does not work
import { supabase } from "./supabase";
beforeEach(() => {
jest
.spyOn(supabase.auth, "signUp")
.mockResolvedValueOnce({ data: { user: null, session: null }, error: null });
});
test("successful sign up", async () => {
jest.spyOn(supabase.auth, "signUp").mockResolvedValueOnce({ data: { user: null, session: null }, error: null });
...
});