Skip to content

Commit

Permalink
Merge pull request #116 from HassanBahati/ft-add-useSendSignInLinkToE…
Browse files Browse the repository at this point in the history
…mailMutation
  • Loading branch information
Ehesp authored Oct 10, 2024
2 parents 7ebcfd9 + 064bcf1 commit 6309453
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 2 deletions.
3 changes: 1 addition & 2 deletions packages/react/src/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// useGetRedirectResultQuery
// useRevokeAccessTokenMutation
// useSendPasswordResetEmailMutation
// useSendSignInLinkToEmailMutation
export { useSendSignInLinkToEmailMutation } from "./useSendSignInLinkToEmailMutation";
export { useSignInAnonymouslyMutation } from "./useSignInAnonymouslyMutation";
// useSignInWithCredentialMutation
// useSignInWithCustomTokenMutation
Expand Down Expand Up @@ -46,4 +46,3 @@ export { useSignInAnonymouslyMutation } from "./useSignInAnonymouslyMutation";
// useUpdatePasswordMutation
// useUpdateProfileMutation
// useVerifyBeforeUpdateEmailMutation

119 changes: 119 additions & 0 deletions packages/react/src/auth/useSendSignInLinkToEmailMutation.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React from "react";
import { describe, expect, test, beforeEach } from "vitest";
import { renderHook, act, waitFor } from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useSendSignInLinkToEmailMutation } from "./useSendSignInLinkToEmailMutation";
import { wipeAuth, auth } from "~/testing-utils";

const queryClient = new QueryClient({
defaultOptions: {
queries: { retry: false },
mutations: { retry: false },
},
});

const wrapper = ({ children }: { children: React.ReactNode }) => (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);

describe("useSendSignInLinkToEmailMutation", () => {
const email = "[email protected]";
const actionCodeSettings = {
url: `https://invertase.io/?email=${email}`,
iOS: {
bundleId: "com.example.ios",
},
android: {
packageName: "com.example.android",
installApp: true,
minimumVersion: "12",
},
handleCodeInApp: true,
};

beforeEach(async () => {
queryClient.clear();
await wipeAuth();
});

test("resets mutation state correctly", async () => {
const { result } = renderHook(
() => useSendSignInLinkToEmailMutation(auth),
{ wrapper }
);

act(() => {
result.current.mutate({ email, actionCodeSettings });
});

await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
});

act(() => {
result.current.reset();
});

await waitFor(() => {
expect(result.current.isIdle).toBe(true);
expect(result.current.data).toBeUndefined();
expect(result.current.error).toBeNull();
});
});

test("successfully sends sign-in link to email", async () => {
const { result } = renderHook(
() => useSendSignInLinkToEmailMutation(auth),
{ wrapper }
);

act(() => {
result.current.mutate({ email, actionCodeSettings });
});

await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
});

expect(result.current.isSuccess).toBe(true);
expect(result.current.error).toBeNull();
});

test("allows multiple sequential send attempts", async () => {
const { result } = renderHook(
() => useSendSignInLinkToEmailMutation(auth),
{ wrapper }
);

// First attempt
act(() => {
result.current.mutate({ email, actionCodeSettings });
});

await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
});

// Reset state
act(() => {
result.current.reset();
});

await waitFor(() => {
expect(result.current.isIdle).toBe(true);
expect(result.current.data).toBeUndefined();
expect(result.current.error).toBeNull();
});

// Second attempt
act(() => {
result.current.mutate({ email, actionCodeSettings });
});

await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
});

expect(result.current.error).toBeNull();
});
});
29 changes: 29 additions & 0 deletions packages/react/src/auth/useSendSignInLinkToEmailMutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useMutation, type UseMutationOptions } from "@tanstack/react-query";
import {
type ActionCodeSettings,
type Auth,
AuthError,
sendSignInLinkToEmail,
} from "firebase/auth";

type SendSignInLinkParams = {
email: string;
actionCodeSettings: ActionCodeSettings;
};

type AuthUseMutationOptions<
TData = unknown,
TError = Error,
TVariables = void
> = Omit<UseMutationOptions<TData, TError, TVariables>, "mutationFn">;

export function useSendSignInLinkToEmailMutation(
auth: Auth,
options?: AuthUseMutationOptions<void, AuthError, SendSignInLinkParams>
) {
return useMutation<void, AuthError, SendSignInLinkParams>({
...options,
mutationFn: ({ email, actionCodeSettings }) =>
sendSignInLinkToEmail(auth, email, actionCodeSettings),
});
}
1 change: 1 addition & 0 deletions vitest/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { expect } from "vitest";
const firebaseTestingOptions = {
projectId: "test-project",
apiKey: "test-api-key",
authDomain: "test-auth-domain",
};

let app: FirebaseApp | undefined;
Expand Down

0 comments on commit 6309453

Please sign in to comment.