From da4187510fa4ec221d9c625933bbf61925629059 Mon Sep 17 00:00:00 2001 From: naveen-s-chand_atko Date: Thu, 7 May 2026 12:40:33 +0530 Subject: [PATCH 1/7] feat(react): create use user service hook and types --- .../__tests__/use-user-mfa-service.test.tsx | 177 ++++++++++++++++++ .../hooks/my-account/use-user-mfa-service.ts | 116 ++++++++++++ .../src/types/my-account/mfa/mfa-types.ts | 21 +++ 3 files changed, 314 insertions(+) create mode 100644 packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx create mode 100644 packages/react/src/hooks/my-account/use-user-mfa-service.ts diff --git a/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx b/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx new file mode 100644 index 000000000..6159c6de4 --- /dev/null +++ b/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx @@ -0,0 +1,177 @@ +import { mfaQueryKeys } from '@auth0/universal-components-core'; +import { renderHook, waitFor } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach } from 'vitest'; + +import { useUserMFAService } from '@/hooks/my-account/use-user-mfa-service'; +import * as useCoreClientModule from '@/hooks/shared/use-core-client'; +import * as useErrorHandlerModule from '@/hooks/shared/use-error-handler'; +import * as useTranslatorModule from '@/hooks/shared/use-translator'; +import { mockCore, setupAllCommonMocks, createQueryClientWrapper } from '@/tests/utils'; +import { createMockAvailableFactors } from '@/tests/utils/__mocks__/my-account/mfa/mfa.mocks'; + +const { initMockCoreClient } = mockCore(); +let mockCoreClient: ReturnType; + +describe('useUserMFAService', () => { + let mockHandleError: ReturnType; + + beforeEach(() => { + vi.clearAllMocks(); + mockCoreClient = initMockCoreClient(); + + ({ mockHandleError } = setupAllCommonMocks({ + useTranslatorModule, + coreClient: mockCoreClient, + useCoreClientModule, + useErrorHandlerModule, + })); + }); + + const renderService = (onlyActive = false) => { + const { wrapper } = createQueryClientWrapper(); + return renderHook(() => useUserMFAService(onlyActive), { wrapper }); + }; + + it('returns loading state initially', () => { + const { result } = renderService(); + expect(result.current.factorsQuery.isLoading).toBe(true); + }); + + it('fetches and maps factors on success', async () => { + const { result } = renderService(); + await waitFor(() => expect(result.current.factorsQuery.isSuccess).toBe(true)); + expect(result.current.factorsQuery.data).toBeDefined(); + const apiClient = mockCoreClient.getMyAccountApiClient(); + expect(apiClient.factors.list).toHaveBeenCalledTimes(1); + expect(apiClient.authenticationMethods.list).toHaveBeenCalledTimes(1); + }); + + it('calls handleError once when factorsQuery fails', async () => { + const apiError = new Error('network error'); + mockCoreClient.getMyAccountApiClient().factors.list = vi.fn().mockRejectedValue(apiError); + + const { result } = renderService(); + await waitFor(() => expect(result.current.factorsQuery.isError).toBe(true)); + + expect(mockHandleError).toHaveBeenCalledTimes(1); + expect(mockHandleError).toHaveBeenCalledWith( + apiError, + expect.objectContaining({ fallbackMessage: expect.any(String) }), + ); + }); + + it('resets the error guard after recovery so a subsequent error fires handleError again', async () => { + const apiClient = mockCoreClient.getMyAccountApiClient(); + const listFn = vi + .fn() + .mockRejectedValueOnce(new Error('first failure')) + .mockResolvedValueOnce(createMockAvailableFactors()) + .mockRejectedValueOnce(new Error('second failure')); + apiClient.factors.list = listFn; + + const { result } = renderService(); + + // first error fires handleError + await waitFor(() => expect(result.current.factorsQuery.isError).toBe(true)); + expect(mockHandleError).toHaveBeenCalledTimes(1); + + // recovery clears the ref + await result.current.factorsQuery.refetch(); + await waitFor(() => expect(result.current.factorsQuery.isSuccess).toBe(true)); + + // second error should fire handleError again + await result.current.factorsQuery.refetch(); + await waitFor(() => expect(result.current.factorsQuery.isError).toBe(true)); + expect(mockHandleError).toHaveBeenCalledTimes(2); + }); + + it('does not fetch when coreClient is null', () => { + vi.spyOn(useCoreClientModule, 'useCoreClient').mockReturnValue({ coreClient: null }); + + const { wrapper } = createQueryClientWrapper(); + const { result } = renderHook(() => useUserMFAService(false), { wrapper }); + + expect(result.current.factorsQuery.fetchStatus).toBe('idle'); + }); + + it('calls authenticationMethods.create with mapped params on enroll', async () => { + const apiClient = mockCoreClient.getMyAccountApiClient(); + vi.mocked(apiClient.authenticationMethods.create).mockResolvedValue({ + id: 'new_id', + auth_session: 'sess', + } as never); + + const { result } = renderService(); + await waitFor(() => expect(result.current.factorsQuery.isSuccess).toBe(true)); + + await result.current.enrollMutation.mutateAsync({ factorType: 'totp', options: {} }); + + expect(apiClient.authenticationMethods.create).toHaveBeenCalled(); + }); + + it('calls authenticationMethods.delete and invalidates query on success', async () => { + const apiClient = mockCoreClient.getMyAccountApiClient(); + + const { result, rerender } = renderService(); + await waitFor(() => expect(result.current.factorsQuery.isSuccess).toBe(true)); + + const initialCallCount = vi.mocked(apiClient.factors.list).mock.calls.length; + await result.current.deleteMutation.mutateAsync('auth-id-123'); + + expect(apiClient.authenticationMethods.delete).toHaveBeenCalledWith('auth-id-123'); + rerender(); + await waitFor(() => { + expect(vi.mocked(apiClient.factors.list).mock.calls.length).toBeGreaterThan(initialCallCount); + }); + }); + + it('calls handleError on delete failure', async () => { + const deleteError = new Error('delete failed'); + mockCoreClient.getMyAccountApiClient().authenticationMethods.delete = vi + .fn() + .mockRejectedValue(deleteError); + + const { result } = renderService(); + await waitFor(() => expect(result.current.factorsQuery.isSuccess).toBe(true)); + + await expect(result.current.deleteMutation.mutateAsync('auth-id-123')).rejects.toThrow(); + + expect(mockHandleError).toHaveBeenCalledWith( + deleteError, + expect.objectContaining({ fallbackMessage: expect.any(String) }), + ); + }); + + it('calls authenticationMethods.verify with correct params on confirm', async () => { + const apiClient = mockCoreClient.getMyAccountApiClient(); + + const { result } = renderService(); + await waitFor(() => expect(result.current.factorsQuery.isSuccess).toBe(true)); + + await result.current.confirmEnrollmentMutation.mutateAsync({ + factorType: 'totp', + authSession: 'sess-abc', + authenticationMethodId: 'method-123', + options: { userOtpCode: '123456' }, + }); + + expect(apiClient.authenticationMethods.verify).toHaveBeenCalledWith( + 'method-123', + expect.anything(), + ); + }); + + it('registers query under the onlyActive=true key when onlyActive is true', async () => { + const { wrapper, queryClient } = createQueryClientWrapper(); + const { result } = renderHook(() => useUserMFAService(true), { wrapper }); + + await waitFor(() => expect(result.current.factorsQuery.isSuccess).toBe(true)); + + const cachedKeys = queryClient + .getQueryCache() + .getAll() + .map((q) => q.queryKey); + expect(cachedKeys).toContainEqual(mfaQueryKeys.factors(true)); + expect(cachedKeys).not.toContainEqual(mfaQueryKeys.factors(false)); + }); +}); diff --git a/packages/react/src/hooks/my-account/use-user-mfa-service.ts b/packages/react/src/hooks/my-account/use-user-mfa-service.ts new file mode 100644 index 000000000..dddc7934e --- /dev/null +++ b/packages/react/src/hooks/my-account/use-user-mfa-service.ts @@ -0,0 +1,116 @@ +/** + * MFA service hook with TanStack Query. + * @module use-user-mfa-service + * @internal + */ + +import { + MFAMappers, + mfaQueryKeys, + type Authenticator, + type MFAType, + type EnrollOptions, + type ConfirmEnrollmentOptions, +} from '@auth0/universal-components-core'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { useEffect, useRef } from 'react'; + +import { useCoreClient } from '@/hooks/shared/use-core-client'; +import { useErrorHandler } from '@/hooks/shared/use-error-handler'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { UseUserMFAServiceReturn, UserMFAMgmtProps } from '@/types/my-account/mfa/mfa-types'; + +/** + * Internal service hook for MFA operations backed by TanStack Query. + * Provides queries and mutations; use `useUserMFA` for the public API. + * @param onlyActive - Whether to return only active factors. + * @param customMessages - Optional custom i18n messages for MFA translations. + * @returns MFA query and mutation handlers for factor listing and enrollment lifecycle operations. + * @internal + */ +export function useUserMFAService( + onlyActive: boolean, + customMessages: UserMFAMgmtProps['customMessages'] = {}, +): UseUserMFAServiceReturn { + const { coreClient } = useCoreClient(); + const { t } = useTranslator('mfa', customMessages); + const queryClient = useQueryClient(); + const handleError = useErrorHandler(); + const hasFiredFactorsError = useRef(false); + + const factorsQuery = useQuery>({ + queryKey: mfaQueryKeys.factors(onlyActive), + queryFn: async () => { + const client = coreClient!.getMyAccountApiClient(); + const [availableFactors, enrolledFactors] = await Promise.all([ + client.factors.list(), + client.authenticationMethods.list(), + ]); + return MFAMappers.fromAPI(availableFactors, enrolledFactors, onlyActive) as Record< + MFAType, + Authenticator[] + >; + }, + enabled: !!coreClient, + }); + + useEffect(() => { + if (!factorsQuery.isError) { + hasFiredFactorsError.current = false; + return; + } + if (hasFiredFactorsError.current) return; + hasFiredFactorsError.current = true; + handleError(factorsQuery.error, { fallbackMessage: t('errors.factors_loading_error') }); + }, [factorsQuery.isError, factorsQuery.error, handleError, t]); + + const enrollMutation = useMutation({ + mutationFn: ({ + factorType, + options = {}, + }: { + factorType: MFAType; + options?: EnrollOptions; + }) => { + const client = coreClient!.getMyAccountApiClient(); + const params = MFAMappers.buildEnrollParams(factorType, options); + return client.authenticationMethods.create(params); + }, + }); + + const deleteMutation = useMutation({ + mutationFn: (authenticatorId: string) => + coreClient!.getMyAccountApiClient().authenticationMethods.delete(authenticatorId), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: mfaQueryKeys.factors(onlyActive) }); + }, + onError: (error) => { + handleError(error, { fallbackMessage: t('errors.delete_factor') }); + }, + }); + + const confirmEnrollmentMutation = useMutation({ + mutationFn: ({ + factorType, + authSession, + authenticationMethodId, + options, + }: { + factorType: MFAType; + authSession: string; + authenticationMethodId: string; + options: ConfirmEnrollmentOptions; + }) => { + const client = coreClient!.getMyAccountApiClient(); + const params = MFAMappers.buildConfirmEnrollmentParams(factorType, authSession, options); + return client.authenticationMethods.verify(authenticationMethodId, params); + }, + }); + + return { + factorsQuery, + enrollMutation, + deleteMutation, + confirmEnrollmentMutation, + }; +} diff --git a/packages/react/src/types/my-account/mfa/mfa-types.ts b/packages/react/src/types/my-account/mfa/mfa-types.ts index c37010401..7c62ad592 100644 --- a/packages/react/src/types/my-account/mfa/mfa-types.ts +++ b/packages/react/src/types/my-account/mfa/mfa-types.ts @@ -12,9 +12,30 @@ import type { MFAMessages, SharedComponentProps, } from '@auth0/universal-components-core'; +import type { UseMutationResult, UseQueryResult } from '@tanstack/react-query'; import type { ENROLL, CONFIRM } from '@/lib/constants/my-account/mfa/mfa-constants'; +export interface UseUserMFAServiceReturn { + factorsQuery: UseQueryResult>; + enrollMutation: UseMutationResult< + CreateAuthenticationMethodResponseContent, + Error, + { factorType: MFAType; options?: EnrollOptions } + >; + deleteMutation: UseMutationResult; + confirmEnrollmentMutation: UseMutationResult< + unknown, + Error, + { + factorType: MFAType; + authSession: string; + authenticationMethodId: string; + options: ConfirmEnrollmentOptions; + } + >; +} + /** Configuration for an individual MFA factor type. */ export interface FactorConfigOptions { visible?: boolean; From 6ef5ef0d6f7e6dafcb2cbc42525f6e00b5df7863 Mon Sep 17 00:00:00 2001 From: naveen-s-chand_atko Date: Thu, 7 May 2026 18:44:18 +0530 Subject: [PATCH 2/7] fix(react): update service hook --- .../__tests__/use-user-mfa-service.test.tsx | 66 +------------------ .../hooks/my-account/use-user-mfa-service.ts | 27 +------- 2 files changed, 5 insertions(+), 88 deletions(-) diff --git a/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx b/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx index 6159c6de4..5e68fa2f3 100644 --- a/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx +++ b/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx @@ -7,24 +7,20 @@ import * as useCoreClientModule from '@/hooks/shared/use-core-client'; import * as useErrorHandlerModule from '@/hooks/shared/use-error-handler'; import * as useTranslatorModule from '@/hooks/shared/use-translator'; import { mockCore, setupAllCommonMocks, createQueryClientWrapper } from '@/tests/utils'; -import { createMockAvailableFactors } from '@/tests/utils/__mocks__/my-account/mfa/mfa.mocks'; const { initMockCoreClient } = mockCore(); let mockCoreClient: ReturnType; describe('useUserMFAService', () => { - let mockHandleError: ReturnType; - beforeEach(() => { vi.clearAllMocks(); mockCoreClient = initMockCoreClient(); - - ({ mockHandleError } = setupAllCommonMocks({ - useTranslatorModule, + setupAllCommonMocks({ coreClient: mockCoreClient, useCoreClientModule, + useTranslatorModule, useErrorHandlerModule, - })); + }); }); const renderService = (onlyActive = false) => { @@ -46,45 +42,6 @@ describe('useUserMFAService', () => { expect(apiClient.authenticationMethods.list).toHaveBeenCalledTimes(1); }); - it('calls handleError once when factorsQuery fails', async () => { - const apiError = new Error('network error'); - mockCoreClient.getMyAccountApiClient().factors.list = vi.fn().mockRejectedValue(apiError); - - const { result } = renderService(); - await waitFor(() => expect(result.current.factorsQuery.isError).toBe(true)); - - expect(mockHandleError).toHaveBeenCalledTimes(1); - expect(mockHandleError).toHaveBeenCalledWith( - apiError, - expect.objectContaining({ fallbackMessage: expect.any(String) }), - ); - }); - - it('resets the error guard after recovery so a subsequent error fires handleError again', async () => { - const apiClient = mockCoreClient.getMyAccountApiClient(); - const listFn = vi - .fn() - .mockRejectedValueOnce(new Error('first failure')) - .mockResolvedValueOnce(createMockAvailableFactors()) - .mockRejectedValueOnce(new Error('second failure')); - apiClient.factors.list = listFn; - - const { result } = renderService(); - - // first error fires handleError - await waitFor(() => expect(result.current.factorsQuery.isError).toBe(true)); - expect(mockHandleError).toHaveBeenCalledTimes(1); - - // recovery clears the ref - await result.current.factorsQuery.refetch(); - await waitFor(() => expect(result.current.factorsQuery.isSuccess).toBe(true)); - - // second error should fire handleError again - await result.current.factorsQuery.refetch(); - await waitFor(() => expect(result.current.factorsQuery.isError).toBe(true)); - expect(mockHandleError).toHaveBeenCalledTimes(2); - }); - it('does not fetch when coreClient is null', () => { vi.spyOn(useCoreClientModule, 'useCoreClient').mockReturnValue({ coreClient: null }); @@ -125,23 +82,6 @@ describe('useUserMFAService', () => { }); }); - it('calls handleError on delete failure', async () => { - const deleteError = new Error('delete failed'); - mockCoreClient.getMyAccountApiClient().authenticationMethods.delete = vi - .fn() - .mockRejectedValue(deleteError); - - const { result } = renderService(); - await waitFor(() => expect(result.current.factorsQuery.isSuccess).toBe(true)); - - await expect(result.current.deleteMutation.mutateAsync('auth-id-123')).rejects.toThrow(); - - expect(mockHandleError).toHaveBeenCalledWith( - deleteError, - expect.objectContaining({ fallbackMessage: expect.any(String) }), - ); - }); - it('calls authenticationMethods.verify with correct params on confirm', async () => { const apiClient = mockCoreClient.getMyAccountApiClient(); diff --git a/packages/react/src/hooks/my-account/use-user-mfa-service.ts b/packages/react/src/hooks/my-account/use-user-mfa-service.ts index dddc7934e..c165dc440 100644 --- a/packages/react/src/hooks/my-account/use-user-mfa-service.ts +++ b/packages/react/src/hooks/my-account/use-user-mfa-service.ts @@ -13,30 +13,20 @@ import { type ConfirmEnrollmentOptions, } from '@auth0/universal-components-core'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; -import { useEffect, useRef } from 'react'; import { useCoreClient } from '@/hooks/shared/use-core-client'; -import { useErrorHandler } from '@/hooks/shared/use-error-handler'; -import { useTranslator } from '@/hooks/shared/use-translator'; -import type { UseUserMFAServiceReturn, UserMFAMgmtProps } from '@/types/my-account/mfa/mfa-types'; +import type { UseUserMFAServiceReturn } from '@/types/my-account/mfa/mfa-types'; /** * Internal service hook for MFA operations backed by TanStack Query. * Provides queries and mutations; use `useUserMFA` for the public API. * @param onlyActive - Whether to return only active factors. - * @param customMessages - Optional custom i18n messages for MFA translations. * @returns MFA query and mutation handlers for factor listing and enrollment lifecycle operations. * @internal */ -export function useUserMFAService( - onlyActive: boolean, - customMessages: UserMFAMgmtProps['customMessages'] = {}, -): UseUserMFAServiceReturn { +export function useUserMFAService(onlyActive: boolean): UseUserMFAServiceReturn { const { coreClient } = useCoreClient(); - const { t } = useTranslator('mfa', customMessages); const queryClient = useQueryClient(); - const handleError = useErrorHandler(); - const hasFiredFactorsError = useRef(false); const factorsQuery = useQuery>({ queryKey: mfaQueryKeys.factors(onlyActive), @@ -54,16 +44,6 @@ export function useUserMFAService( enabled: !!coreClient, }); - useEffect(() => { - if (!factorsQuery.isError) { - hasFiredFactorsError.current = false; - return; - } - if (hasFiredFactorsError.current) return; - hasFiredFactorsError.current = true; - handleError(factorsQuery.error, { fallbackMessage: t('errors.factors_loading_error') }); - }, [factorsQuery.isError, factorsQuery.error, handleError, t]); - const enrollMutation = useMutation({ mutationFn: ({ factorType, @@ -84,9 +64,6 @@ export function useUserMFAService( onSuccess: () => { queryClient.invalidateQueries({ queryKey: mfaQueryKeys.factors(onlyActive) }); }, - onError: (error) => { - handleError(error, { fallbackMessage: t('errors.delete_factor') }); - }, }); const confirmEnrollmentMutation = useMutation({ From 38bca81be7c52222d9735ae6e5af85c8dba503f6 Mon Sep 17 00:00:00 2001 From: naveen-s-chand_atko Date: Fri, 8 May 2026 15:14:14 +0530 Subject: [PATCH 3/7] fix(react): update test cases --- .../__tests__/use-user-mfa-service.test.tsx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx b/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx index 5e68fa2f3..797eaeefd 100644 --- a/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx +++ b/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx @@ -4,9 +4,7 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'; import { useUserMFAService } from '@/hooks/my-account/use-user-mfa-service'; import * as useCoreClientModule from '@/hooks/shared/use-core-client'; -import * as useErrorHandlerModule from '@/hooks/shared/use-error-handler'; -import * as useTranslatorModule from '@/hooks/shared/use-translator'; -import { mockCore, setupAllCommonMocks, createQueryClientWrapper } from '@/tests/utils'; +import { mockCore, setupMockUseCoreClient, createQueryClientWrapper } from '@/tests/utils'; const { initMockCoreClient } = mockCore(); let mockCoreClient: ReturnType; @@ -15,12 +13,7 @@ describe('useUserMFAService', () => { beforeEach(() => { vi.clearAllMocks(); mockCoreClient = initMockCoreClient(); - setupAllCommonMocks({ - coreClient: mockCoreClient, - useCoreClientModule, - useTranslatorModule, - useErrorHandlerModule, - }); + setupMockUseCoreClient(mockCoreClient, useCoreClientModule); }); const renderService = (onlyActive = false) => { @@ -69,14 +62,13 @@ describe('useUserMFAService', () => { it('calls authenticationMethods.delete and invalidates query on success', async () => { const apiClient = mockCoreClient.getMyAccountApiClient(); - const { result, rerender } = renderService(); + const { result } = renderService(); await waitFor(() => expect(result.current.factorsQuery.isSuccess).toBe(true)); const initialCallCount = vi.mocked(apiClient.factors.list).mock.calls.length; await result.current.deleteMutation.mutateAsync('auth-id-123'); expect(apiClient.authenticationMethods.delete).toHaveBeenCalledWith('auth-id-123'); - rerender(); await waitFor(() => { expect(vi.mocked(apiClient.factors.list).mock.calls.length).toBeGreaterThan(initialCallCount); }); From 1f3768b30b112afa954dc4a1de91ae3b2082991c Mon Sep 17 00:00:00 2001 From: naveen-s-chand_atko Date: Fri, 8 May 2026 15:24:28 +0530 Subject: [PATCH 4/7] fix(react): update type for verify method --- packages/core/src/index.ts | 1 + packages/react/src/types/my-account/mfa/mfa-types.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index b1d8407e8..0ec74b97f 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -31,6 +31,7 @@ export { ConfirmEnrollmentOptions, CreateAuthenticationMethodRequestContent, CreateAuthenticationMethodResponseContent, + VerifyAuthenticationMethodResponseContent, } from './services/my-account/mfa/mfa-types'; export { diff --git a/packages/react/src/types/my-account/mfa/mfa-types.ts b/packages/react/src/types/my-account/mfa/mfa-types.ts index 7c62ad592..79aee21b1 100644 --- a/packages/react/src/types/my-account/mfa/mfa-types.ts +++ b/packages/react/src/types/my-account/mfa/mfa-types.ts @@ -5,6 +5,7 @@ import type { CreateAuthenticationMethodResponseContent, + VerifyAuthenticationMethodResponseContent, Authenticator, MFAType, EnrollOptions, @@ -25,7 +26,7 @@ export interface UseUserMFAServiceReturn { >; deleteMutation: UseMutationResult; confirmEnrollmentMutation: UseMutationResult< - unknown, + VerifyAuthenticationMethodResponseContent, Error, { factorType: MFAType; From 77be81ba45e621f5a16371b5bff15dc0e41ffead Mon Sep 17 00:00:00 2001 From: naveen-s-chand_atko Date: Fri, 8 May 2026 15:32:24 +0530 Subject: [PATCH 5/7] fix(react): rename confirm mutation to verify --- .../hooks/my-account/__tests__/use-user-mfa-service.test.tsx | 2 +- packages/react/src/hooks/my-account/use-user-mfa-service.ts | 4 ++-- packages/react/src/types/my-account/mfa/mfa-types.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx b/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx index 797eaeefd..568a20a4a 100644 --- a/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx +++ b/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx @@ -80,7 +80,7 @@ describe('useUserMFAService', () => { const { result } = renderService(); await waitFor(() => expect(result.current.factorsQuery.isSuccess).toBe(true)); - await result.current.confirmEnrollmentMutation.mutateAsync({ + await result.current.verifyMutation.mutateAsync({ factorType: 'totp', authSession: 'sess-abc', authenticationMethodId: 'method-123', diff --git a/packages/react/src/hooks/my-account/use-user-mfa-service.ts b/packages/react/src/hooks/my-account/use-user-mfa-service.ts index c165dc440..ae0ed36f5 100644 --- a/packages/react/src/hooks/my-account/use-user-mfa-service.ts +++ b/packages/react/src/hooks/my-account/use-user-mfa-service.ts @@ -66,7 +66,7 @@ export function useUserMFAService(onlyActive: boolean): UseUserMFAServiceReturn }, }); - const confirmEnrollmentMutation = useMutation({ + const verifyMutation = useMutation({ mutationFn: ({ factorType, authSession, @@ -88,6 +88,6 @@ export function useUserMFAService(onlyActive: boolean): UseUserMFAServiceReturn factorsQuery, enrollMutation, deleteMutation, - confirmEnrollmentMutation, + verifyMutation, }; } diff --git a/packages/react/src/types/my-account/mfa/mfa-types.ts b/packages/react/src/types/my-account/mfa/mfa-types.ts index 79aee21b1..fadf8c4d9 100644 --- a/packages/react/src/types/my-account/mfa/mfa-types.ts +++ b/packages/react/src/types/my-account/mfa/mfa-types.ts @@ -25,7 +25,7 @@ export interface UseUserMFAServiceReturn { { factorType: MFAType; options?: EnrollOptions } >; deleteMutation: UseMutationResult; - confirmEnrollmentMutation: UseMutationResult< + verifyMutation: UseMutationResult< VerifyAuthenticationMethodResponseContent, Error, { From 9579cca539f7181e8fbae1c7ee0e20229660a479 Mon Sep 17 00:00:00 2001 From: naveen-s-chand_atko Date: Fri, 8 May 2026 17:21:32 +0530 Subject: [PATCH 6/7] fix(react): create shared service folder --- .../my-account/{ => shared/services}/use-user-mfa-service.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/react/src/hooks/my-account/{ => shared/services}/use-user-mfa-service.ts (100%) diff --git a/packages/react/src/hooks/my-account/use-user-mfa-service.ts b/packages/react/src/hooks/my-account/shared/services/use-user-mfa-service.ts similarity index 100% rename from packages/react/src/hooks/my-account/use-user-mfa-service.ts rename to packages/react/src/hooks/my-account/shared/services/use-user-mfa-service.ts From 8808f44d178e45eb0b9d2edfe7f157908979c712 Mon Sep 17 00:00:00 2001 From: naveen-s-chand_atko Date: Fri, 8 May 2026 17:32:30 +0530 Subject: [PATCH 7/7] fix(react): test case update --- .../hooks/my-account/__tests__/use-user-mfa-service.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx b/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx index 568a20a4a..7c839834e 100644 --- a/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx +++ b/packages/react/src/hooks/my-account/__tests__/use-user-mfa-service.test.tsx @@ -2,7 +2,7 @@ import { mfaQueryKeys } from '@auth0/universal-components-core'; import { renderHook, waitFor } from '@testing-library/react'; import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { useUserMFAService } from '@/hooks/my-account/use-user-mfa-service'; +import { useUserMFAService } from '@/hooks/my-account/shared/services/use-user-mfa-service'; import * as useCoreClientModule from '@/hooks/shared/use-core-client'; import { mockCore, setupMockUseCoreClient, createQueryClientWrapper } from '@/tests/utils';