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:
Vijay Budhram 2024-09-18 10:28:34 -04:00 коммит произвёл GitHub
Родитель 33814cb2c4 a15e9d7cd0
Коммит bc582e8d8a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
10 изменённых файлов: 99 добавлений и 9 удалений

Просмотреть файл

@ -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 }}
/>
);
}