diff --git a/packages/fxa-settings/src/pages/Signin/SigninRecoveryCode/container.test.tsx b/packages/fxa-settings/src/pages/Signin/SigninRecoveryCode/container.test.tsx index 15892403354..a0bbf6af172 100644 --- a/packages/fxa-settings/src/pages/Signin/SigninRecoveryCode/container.test.tsx +++ b/packages/fxa-settings/src/pages/Signin/SigninRecoveryCode/container.test.tsx @@ -10,7 +10,11 @@ import { LocationProvider } from '@reach/router'; import { renderWithLocalizationProvider } from 'fxa-react/lib/test-utils/localizationProvider'; import SigninRecoveryCodeContainer from './container'; import { createMockWebIntegration } from '../../../lib/integrations/mocks'; -import { Integration, useAuthClient, useSensitiveDataClient } from '../../../models'; +import { + Integration, + useAuthClient, + useSensitiveDataClient, +} from '../../../models'; import { mockSensitiveDataClient as createMockSensitiveDataClient } from '../../../models/mocks'; import { MOCK_STORED_ACCOUNT, @@ -24,6 +28,16 @@ import { mockSigninLocationState } from '../mocks'; import { waitFor } from '@testing-library/react'; import { AuthUiErrors } from '../../../lib/auth-errors/auth-errors'; import { SensitiveData } from '../../../lib/sensitive-data-client'; +import { + useFinishOAuthFlowHandler, + useOAuthKeysCheck, +} from '../../../lib/oauth/hooks'; + +jest.mock('../../../lib/oauth/hooks', () => ({ + __esModule: true, + useFinishOAuthFlowHandler: jest.fn(), + useOAuthKeysCheck: jest.fn(), +})); let integration: Integration; function mockWebIntegration() { @@ -122,6 +136,13 @@ function applyDefaultMocks() { mockWebIntegration(); resetMockSensitiveDataClient(); resetMockAuthClient(); + (useFinishOAuthFlowHandler as jest.Mock).mockImplementation(() => ({ + finishOAuthFlowHandler: jest.fn(), + oAuthDataError: null, + })); + (useOAuthKeysCheck as jest.Mock).mockImplementation(() => ({ + oAuthKeysCheckError: null, + })); } function render() { @@ -170,6 +191,36 @@ describe('SigninRecoveryCode container', () => { }); }); + describe('useOAuthKeysCheck', () => { + it('passes isPasswordlessFlow to skip the keys check', () => { + mockReachRouter('signin_recovery_code', { + signinState: { ...mockSigninLocationState, isPasswordlessFlow: true }, + }); + render(); + expect(useOAuthKeysCheck).toHaveBeenCalledWith( + integration, + MOCK_KEY_FETCH_TOKEN, + MOCK_UNWRAP_BKEY, + true + ); + }); + + it('renders the recovery code component when keys check is skipped for passwordless flow', () => { + (useOAuthKeysCheck as jest.Mock).mockImplementationOnce( + (_integration: any, _kft: any, _ubk: any, skipKeysCheck: boolean) => ({ + oAuthKeysCheckError: skipKeysCheck + ? null + : { errno: 1, message: 'TRY_AGAIN' }, + }) + ); + mockReachRouter('signin_recovery_code', { + signinState: { ...mockSigninLocationState, isPasswordlessFlow: true }, + }); + render(); + expect(currentSigninRecoveryCodeProps).toBeDefined(); + }); + }); + describe('submitRecoveryCode', () => { it('successful', async () => { mockAuthClient.consumeRecoveryCode.mockResolvedValue({ remaining: 3 }); diff --git a/packages/fxa-settings/src/pages/Signin/SigninRecoveryCode/container.tsx b/packages/fxa-settings/src/pages/Signin/SigninRecoveryCode/container.tsx index cb2ac8d64e3..d98fda852e6 100644 --- a/packages/fxa-settings/src/pages/Signin/SigninRecoveryCode/container.tsx +++ b/packages/fxa-settings/src/pages/Signin/SigninRecoveryCode/container.tsx @@ -58,7 +58,7 @@ export const SigninRecoveryCodeContainer = ({ integration, keyFetchToken, unwrapBKey, - signinState?.isSignInWithThirdPartyAuth + signinState?.isSignInWithThirdPartyAuth || signinState?.isPasswordlessFlow ); const submitRecoveryCode: SubmitRecoveryCode = useCallback( diff --git a/packages/fxa-settings/src/pages/Signin/SigninRecoveryPhone/container.test.tsx b/packages/fxa-settings/src/pages/Signin/SigninRecoveryPhone/container.test.tsx index d87809d9b6f..46f963f78da 100644 --- a/packages/fxa-settings/src/pages/Signin/SigninRecoveryPhone/container.test.tsx +++ b/packages/fxa-settings/src/pages/Signin/SigninRecoveryPhone/container.test.tsx @@ -248,4 +248,32 @@ describe('SigninRecoveryPhoneContainer', () => { ); }); }); + + describe('useOAuthKeysCheck', () => { + it('passes isPasswordlessFlow to skip the keys check', () => { + mockReachRouter('/signin_recovery_phone', { + signinState: { ...mockSigninLocationState, isPasswordlessFlow: true }, + lastFourPhoneDigits: '1234', + }); + renderSigninRecoveryPhoneContainer(); + const lastArg = (useOAuthKeysCheck as jest.Mock).mock.calls[0]?.[3]; + expect(lastArg).toBe(true); + }); + + it('renders the recovery phone component when keys check is skipped for passwordless flow', () => { + (useOAuthKeysCheck as jest.Mock).mockImplementationOnce( + (_integration: any, _kft: any, _ubk: any, skipKeysCheck: boolean) => ({ + oAuthKeysCheckError: skipKeysCheck + ? null + : { errno: 1, message: 'TRY_AGAIN' }, + }) + ); + mockReachRouter('/signin_recovery_phone', { + signinState: { ...mockSigninLocationState, isPasswordlessFlow: true }, + lastFourPhoneDigits: '1234', + }); + renderSigninRecoveryPhoneContainer(); + expect(currentPageProps).toBeDefined(); + }); + }); }); diff --git a/packages/fxa-settings/src/pages/Signin/SigninRecoveryPhone/container.tsx b/packages/fxa-settings/src/pages/Signin/SigninRecoveryPhone/container.tsx index 7cefbe8ae98..65d813a4982 100644 --- a/packages/fxa-settings/src/pages/Signin/SigninRecoveryPhone/container.tsx +++ b/packages/fxa-settings/src/pages/Signin/SigninRecoveryPhone/container.tsx @@ -70,7 +70,7 @@ const SigninRecoveryPhoneContainer = ({ integration, keyFetchToken, unwrapBKey, - signinState?.isSignInWithThirdPartyAuth + signinState?.isSignInWithThirdPartyAuth || signinState?.isPasswordlessFlow ); const webRedirectCheck = useWebRedirect(integration.data.redirectTo);