I'm following this guide to create an auth composition library: https://mattlaw.dev/blog/vuejs-the-composition-api-and-firebase-authentication/
At a high level, you define a file /src/components/auth/index.ts and that file has refs and "use" functions defined and directly exported, like:
export const user = ref(null);
export function useSignup() {
const email = ref("");
const password = ref("");
async function signup() {
if (email.value == "" || password.value == "") return;
const creds = await auth.createUserWithEmailAndPassword(
email.value,
password.value
);
if (!creds.user) throw Error("Signup failed");
user.value = creds.user;
}
return {
email,
password,
signup,
};
}
I want to replace the "auth.createUserWithEmailAndPassword" with a fake injected auth service so I can purely test the useSignup function, but I don't want to have to initiate a full component to wrap this as part of my test. Is there a way to get a vue app context, "provide" a DI property, and then test this from jest so I'm purely testing the useSignup code?
One way to test useSignup()
without any component context is to import the auth
module in useSignup()
:
import { ref } from "vue";
import auth from "@/auth"; // 👈
export const user = ref(null);
export function useSignup() {
const email = ref("");
const password = ref("");
async function signup() {
if (email.value == "" || password.value == "") return;
const creds = await auth.createUserWithEmailAndPassword(
email.value,
password.value
);
if (!creds.user) throw Error("Signup failed");
user.value = creds.user;
return creds.user
}
return {
email,
password,
signup,
};
}
Then your test could mock that module:
Use jest.mock('@/auth')
at the top of the test file.
In your test, require
the module (which has been mocked above), and use mockReturnValue()
to set the mock return value.
Setup the credentials ref
values, and call signup()
.
Verify the mock createUserWithEmailAndPassword()
was called.
import { useSignup } from "@/useSignup";
jest.mock("@/auth"); 1️⃣
describe("useSignup", () => {
it("signs in", async () => {
2️⃣
const { createUserWithEmailAndPassword } = require("@/auth").default;
const myEmail = "john@gmail.com";
createUserWithEmailAndPassword.mockReturnValue({
user: myEmail
});
3️⃣
const { email, password, signup } = useSignup();
email.value = myEmail;
password.value = "myPassword";
await signup();
4️⃣
expect(createUserWithEmailAndPassword).toHaveBeenCalledWith(email.value, password.value);
})
})