зеркало из https://github.com/mozilla/fxa.git
Merge pull request #17614 from mozilla/fxa-10080
feat(recovery): Add functionality of `do it later` in inline recovery key
This commit is contained in:
Коммит
bc582e8d8a
|
@ -84,6 +84,7 @@ const FRONTEND_ROUTES = [
|
|||
'verify_secondary_email',
|
||||
'would_you_like_to_sync',
|
||||
'web_channel_example',
|
||||
'inline_recovery_key_setup',
|
||||
];
|
||||
|
||||
// The array is converted into a RegExp
|
||||
|
|
|
@ -86,6 +86,7 @@ const getReactRouteGroups = (showReactApp, reactRoute) => {
|
|||
'inline_recovery_setup',
|
||||
'signin_push_code',
|
||||
'signin_push_code_confirm',
|
||||
'inline_recovery_key_setup',
|
||||
]),
|
||||
fullProdRollout: true,
|
||||
},
|
||||
|
|
|
@ -77,6 +77,7 @@ import PrimaryEmailVerified from '../../pages/Signup/PrimaryEmailVerified';
|
|||
import SignupConfirmed from '../../pages/Signup/SignupConfirmed';
|
||||
import WebChannelExample from '../../pages/WebChannelExample';
|
||||
import SignoutSync from '../Settings/SignoutSync';
|
||||
import InlineRecoveryKeySetupContainer from '../../pages/InlineRecoveryKeySetup/container';
|
||||
|
||||
const Settings = lazy(() => import('../Settings'));
|
||||
|
||||
|
@ -410,6 +411,10 @@ const AuthAndAccountSetupRoutes = ({
|
|||
path="/signin_unblock/*"
|
||||
{...{ integration, flowQueryParams }}
|
||||
/>
|
||||
<InlineRecoveryKeySetupContainer
|
||||
path="/inline_recovery_key_setup/*"
|
||||
{...{ integration, serviceName }}
|
||||
/>
|
||||
|
||||
{/* Signup */}
|
||||
<CannotCreateAccount path="/cannot_create_account/*" />
|
||||
|
|
|
@ -12,7 +12,7 @@ export const InlineRecoveryKeySetupCreate = ({
|
|||
doLaterHandler,
|
||||
}: {
|
||||
createRecoveryKeyHandler: () => Promise<void>;
|
||||
doLaterHandler: () => Promise<void>;
|
||||
doLaterHandler: () => void;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
|
@ -58,7 +58,11 @@ export const InlineRecoveryKeySetupCreate = ({
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<button className="flex justify-center items-center link-blue text-sm mx-auto">
|
||||
<button
|
||||
className="flex justify-center items-center link-blue text-sm mx-auto"
|
||||
onClick={doLaterHandler}
|
||||
data-glean-id="inline_recovery_key_setup_create_do_it_later"
|
||||
>
|
||||
<FtlMsg id="inline-recovery-key-setup-later-button">Do it later</FtlMsg>
|
||||
</button>
|
||||
</>
|
||||
|
|
|
@ -18,6 +18,10 @@ jest.mock('@reach/router', () => ({
|
|||
}));
|
||||
|
||||
describe('NotificationPromoBanner component', () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
it('renders as expected', () => {
|
||||
const notificationProps = {
|
||||
headerImage: keyImage,
|
||||
|
|
|
@ -3,6 +3,7 @@ import { Link, RouteComponentProps, useLocation } from '@reach/router';
|
|||
import { ReactComponent as IconClose } from '@fxa/shared/assets/images/close.svg';
|
||||
import { FtlMsg } from 'fxa-react/lib/utils';
|
||||
import GleanMetrics from '../../lib/glean';
|
||||
import { Constants } from '../../lib/constants';
|
||||
|
||||
type NotificationPromoBannerProps = {
|
||||
headerImage: string;
|
||||
|
@ -15,6 +16,11 @@ type NotificationPromoBannerProps = {
|
|||
isVisible: boolean;
|
||||
};
|
||||
|
||||
const PromoKeys: { [key: string]: string } = {
|
||||
'account-recovery-dismissed':
|
||||
Constants.DISABLE_PROMO_ACCOUNT_RECOVERY_KEY_BANNER,
|
||||
};
|
||||
|
||||
const NotificationPromoBanner = ({
|
||||
headerImage,
|
||||
ctaText,
|
||||
|
@ -34,7 +40,7 @@ const NotificationPromoBanner = ({
|
|||
// This value is used to animate the banner out of view when the user dismisses it.
|
||||
const [isClosing, setIsClosing] = useState(false);
|
||||
|
||||
const notificationBannerClosedLocalStorageKey = `__fxa_storage.fxa_disable_notification_banner.${dismissKey}`;
|
||||
const notificationBannerClosedLocalStorageKey = PromoKeys[dismissKey];
|
||||
|
||||
const [bannerClosed] = useState<string | null>(
|
||||
localStorage.getItem(notificationBannerClosedLocalStorageKey)
|
||||
|
|
|
@ -189,4 +189,10 @@ export const Constants = {
|
|||
|
||||
ENV_DEVELOPMENT: 'development',
|
||||
ENV_PRODUCTION: 'production',
|
||||
|
||||
DISABLE_PROMO_ACCOUNT_RECOVERY_KEY_BANNER:
|
||||
'__fxa_storage.fxa_disable_notification_banner.account-recovery-dismissed',
|
||||
|
||||
DISABLE_PROMO_ACCOUNT_RECOVERY_KEY_DO_IT_LATER:
|
||||
'__fxa_storage.disable_promo.account-recovery-do-it-later',
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ export const InlineRecoveryKeySetupContainer = ({
|
|||
}: {
|
||||
integration: Integration;
|
||||
} & RouteComponentProps) => {
|
||||
const [currentStep, setCurrentStep] = useState<number>(1);
|
||||
const [currentStep] = useState<number>(1);
|
||||
const createRecoveryKeyHandler = useCallback(async () => {
|
||||
// TODO in FXA-10079
|
||||
}, []);
|
||||
|
|
|
@ -2,11 +2,22 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import { screen } from '@testing-library/react';
|
||||
import { act, fireEvent, screen } from '@testing-library/react';
|
||||
import { renderWithLocalizationProvider } from 'fxa-react/lib/test-utils/localizationProvider';
|
||||
import { Subject } from './mocks';
|
||||
import { Constants } from '../../lib/constants';
|
||||
import * as ReactUtils from '../../../../fxa-react/lib/utils';
|
||||
|
||||
function mockReactUtilsModule() {
|
||||
jest.spyOn(ReactUtils, 'hardNavigate').mockImplementation(() => {});
|
||||
}
|
||||
|
||||
describe('InlineRecoveryKeySetup', () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
mockReactUtilsModule();
|
||||
});
|
||||
|
||||
it('renders as expected, step 1', () => {
|
||||
renderWithLocalizationProvider(<Subject currentStep={1} />);
|
||||
|
||||
|
@ -43,4 +54,34 @@ describe('InlineRecoveryKeySetup', () => {
|
|||
renderWithLocalizationProvider(<Subject currentStep={3} />);
|
||||
screen.getByText('TODO');
|
||||
});
|
||||
|
||||
it('redirects to `connect_another_device` if promo has been dismissed before', async () => {
|
||||
localStorage.setItem(
|
||||
Constants.DISABLE_PROMO_ACCOUNT_RECOVERY_KEY_DO_IT_LATER,
|
||||
'true'
|
||||
);
|
||||
renderWithLocalizationProvider(<Subject />);
|
||||
expect(ReactUtils.hardNavigate).toHaveBeenCalledWith(
|
||||
'/connect_another_device',
|
||||
{},
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('clicks `do it later` navigates to `connect_another_device`', async () => {
|
||||
renderWithLocalizationProvider(<Subject />);
|
||||
await act(async () => {
|
||||
fireEvent.click(await screen.findByText('Do it later'));
|
||||
});
|
||||
expect(ReactUtils.hardNavigate).toHaveBeenCalledWith(
|
||||
'/connect_another_device',
|
||||
{},
|
||||
true
|
||||
);
|
||||
expect(
|
||||
localStorage.getItem(
|
||||
Constants.DISABLE_PROMO_ACCOUNT_RECOVERY_KEY_DO_IT_LATER
|
||||
)
|
||||
).toBe('true');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,8 +11,9 @@ import {
|
|||
CircleCheckOutlineImage,
|
||||
RecoveryKeyImage,
|
||||
} from '../../components/images';
|
||||
import { FtlMsg } from 'fxa-react/lib/utils';
|
||||
import { FtlMsg, hardNavigate } from 'fxa-react/lib/utils';
|
||||
import Banner, { BannerType } from '../../components/Banner';
|
||||
import { Constants } from '../../lib/constants';
|
||||
|
||||
export const InlineRecoveryKeySetup = ({
|
||||
createRecoveryKeyHandler,
|
||||
|
@ -21,6 +22,29 @@ export const InlineRecoveryKeySetup = ({
|
|||
createRecoveryKeyHandler: () => Promise<void>;
|
||||
currentStep: number;
|
||||
} & RouteComponentProps) => {
|
||||
const doLaterHandler = () => {
|
||||
localStorage.setItem(
|
||||
Constants.DISABLE_PROMO_ACCOUNT_RECOVERY_KEY_DO_IT_LATER,
|
||||
'true'
|
||||
);
|
||||
// We do a hard navigate because this page is still in the content server, this
|
||||
// also keeps all query params so that correct metrics are emitted.
|
||||
hardNavigate('/connect_another_device', {}, true);
|
||||
};
|
||||
|
||||
// We don't show this promo if the user has dismissed it or dismissed it from
|
||||
// settings
|
||||
if (
|
||||
localStorage.getItem(
|
||||
Constants.DISABLE_PROMO_ACCOUNT_RECOVERY_KEY_DO_IT_LATER
|
||||
) === 'true'
|
||||
) {
|
||||
doLaterHandler();
|
||||
|
||||
// Prevents a flash of the promo banner before redirecting
|
||||
return <></>;
|
||||
}
|
||||
|
||||
// nice to have with FXA-10079:
|
||||
// if user refreshes on step 1 and we no longer have PW from previous step,
|
||||
// just take them to CAD with success messaging.
|
||||
|
@ -78,9 +102,7 @@ export const InlineRecoveryKeySetup = ({
|
|||
default:
|
||||
return (
|
||||
<InlineRecoveryKeySetupCreate
|
||||
{...{ createRecoveryKeyHandler }}
|
||||
// TODO with FXA-10079
|
||||
doLaterHandler={() => Promise.resolve()}
|
||||
{...{ createRecoveryKeyHandler, doLaterHandler }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче