зеркало из https://github.com/mozilla/fxa.git
storybook(fxa-settings): recreate ResetPasswordWithRecoveryKeyVerified
Because: * We're recreating the remaining content-server views in React and moving them into Storybook before they go live This commit: * Recreates reset_password_with_recovery_key_verified in React with metrics, tests, and l10n Closes #https://mozilla-hub.atlassian.net/browse/FXA-6345
This commit is contained in:
Родитель
37f5f7d4ea
Коммит
eb5bd7d6be
|
@ -130,15 +130,29 @@ const EVENTS = {
|
|||
},
|
||||
|
||||
// Reset password confirmation
|
||||
'screen.settings.reset-password-confirmed': {
|
||||
group: GROUPS.settings,
|
||||
'screen.reset-password-confirmed': {
|
||||
group: GROUPS.login,
|
||||
event: 'reset_password_confirmed_view',
|
||||
},
|
||||
'flow.settings.reset-password-confirmed.continue': {
|
||||
group: GROUPS.settings,
|
||||
'flow.reset-password-confirmed.continue': {
|
||||
group: GROUPS.login,
|
||||
event: 'reset_password_confirmed_continue',
|
||||
},
|
||||
|
||||
// Reset password with recovery key verified
|
||||
'screen.reset-password-with-recovery-key-verified': {
|
||||
group: GROUPS.login,
|
||||
event: 'reset_password_with_recovery_key_verified_view',
|
||||
},
|
||||
'flow.reset-password-with-recovery-key-verified.generate-new-key': {
|
||||
group: GROUPS.login,
|
||||
event: 'reset_password_with_recovery_key_verified_generate_new_key',
|
||||
},
|
||||
'flow.reset-password-with-recovery-key-verified.continue-to-account': {
|
||||
group: GROUPS.login,
|
||||
event: 'reset_password_with_recovery_key_verified_continue_to_account',
|
||||
},
|
||||
|
||||
// Save account recovery key
|
||||
'screen.save-recovery-key': {
|
||||
group: GROUPS.activity,
|
||||
|
|
|
@ -2040,6 +2040,32 @@ registerSuite('amplitude', {
|
|||
assert.equal(arg.event_properties.email_type, 'login');
|
||||
},
|
||||
|
||||
'screen.reset-password-with-recovery-key-verified': () => {
|
||||
createAmplitudeEvent('screen.reset-password-with-recovery-key-verified');
|
||||
assert.equal(
|
||||
logger.info.args[0][1].event_type,
|
||||
'fxa_login - reset_password_with_recovery_key_verified_view'
|
||||
);
|
||||
},
|
||||
'flow.reset-password-with-recovery-key-verified.generate-new-key': () => {
|
||||
createAmplitudeEvent(
|
||||
'flow.reset-password-with-recovery-key-verified.generate-new-key'
|
||||
);
|
||||
assert.equal(
|
||||
logger.info.args[0][1].event_type,
|
||||
'fxa_login - reset_password_with_recovery_key_verified_generate_new_key'
|
||||
);
|
||||
},
|
||||
'flow.reset-password-with-recovery-key-verified.continue-to-account':
|
||||
() => {
|
||||
createAmplitudeEvent(
|
||||
'flow.reset-password-with-recovery-key-verified.continue-to-account'
|
||||
);
|
||||
assert.equal(
|
||||
logger.info.args[0][1].event_type,
|
||||
'fxa_login - reset_password_with_recovery_key_verified_continue_to_account'
|
||||
);
|
||||
},
|
||||
'verify-email.verification.clicked': () => {
|
||||
amplitude(
|
||||
{
|
||||
|
|
|
@ -14,8 +14,7 @@ jest.mock('../../lib/metrics', () => ({
|
|||
|
||||
describe('Ready', () => {
|
||||
const customServiceName = 'Example Service';
|
||||
const viewName = 'example.my-page';
|
||||
const actionName = 'my_page';
|
||||
const viewName = 'example-view';
|
||||
|
||||
it('renders as expected with default values', () => {
|
||||
render(<Ready viewName={viewName} />);
|
||||
|
@ -27,7 +26,8 @@ describe('Ready', () => {
|
|||
'You’re now ready to use Account Settings'
|
||||
);
|
||||
const passwordResetContinueButton = screen.queryByText('Continue');
|
||||
|
||||
// Calling `getByText` will fail if the first two elements aren't in the document,
|
||||
// but we test anyway to make the intention of the test explicit
|
||||
expect(passwordResetContinueButton).not.toBeInTheDocument();
|
||||
expect(passwordResetConfirmation).toBeInTheDocument();
|
||||
expect(serviceAvailabilityConfirmation).toBeInTheDocument();
|
||||
|
@ -44,7 +44,8 @@ describe('Ready', () => {
|
|||
`You’re now ready to use ${customServiceName}`
|
||||
);
|
||||
const passwordResetContinueButton = screen.queryByText('Continue');
|
||||
|
||||
// Calling `getByText` will fail if these elements aren't in the document,
|
||||
// but we test anyway to make the intention of the test explicit
|
||||
expect(passwordResetContinueButton).not.toBeInTheDocument();
|
||||
expect(passwordResetConfirmation).toBeInTheDocument();
|
||||
expect(serviceAvailabilityConfirmation).toBeInTheDocument();
|
||||
|
@ -68,7 +69,8 @@ describe('Ready', () => {
|
|||
`You’re now ready to use ${customServiceName}`
|
||||
);
|
||||
const passwordResetContinueButton = screen.getByText('Continue');
|
||||
|
||||
// Calling `getByText` would fail if these elements weren't in the document,
|
||||
// but we test anyway to make the intention of the test explicit
|
||||
expect(passwordResetContinueButton).toBeInTheDocument();
|
||||
expect(passwordResetConfirmation).toBeInTheDocument();
|
||||
expect(serviceAvailabilityConfirmation).toBeInTheDocument();
|
||||
|
@ -85,7 +87,6 @@ describe('Ready', () => {
|
|||
render(
|
||||
<Ready
|
||||
viewName={viewName}
|
||||
baseActionName={actionName}
|
||||
serviceName={customServiceName}
|
||||
continueHandler={() => {
|
||||
console.log('beepboop');
|
||||
|
@ -93,8 +94,8 @@ describe('Ready', () => {
|
|||
/>
|
||||
);
|
||||
const passwordResetContinueButton = screen.getByText('Continue');
|
||||
const clickViewName = `${viewName}.continue`;
|
||||
const fullActionName = `${actionName}_continue`;
|
||||
const clickViewName = `${viewName}`;
|
||||
const fullActionName = `${viewName}.continue`;
|
||||
fireEvent.click(passwordResetContinueButton);
|
||||
expect(logViewEvent).toHaveBeenCalledWith(clickViewName, fullActionName, {
|
||||
entrypoint_variation: 'react',
|
||||
|
|
|
@ -11,13 +11,11 @@ import { logViewEvent, usePageViewEvent } from '../../lib/metrics';
|
|||
type ReadyProps = {
|
||||
serviceName?: string;
|
||||
continueHandler?: Function;
|
||||
baseActionName?: string;
|
||||
viewName: string;
|
||||
};
|
||||
|
||||
const Ready = ({
|
||||
serviceName = 'Account Settings',
|
||||
baseActionName,
|
||||
continueHandler,
|
||||
viewName,
|
||||
}: ReadyProps & RouteComponentProps) => {
|
||||
|
@ -29,7 +27,7 @@ const Ready = ({
|
|||
<>
|
||||
<div className="mb-4">
|
||||
<Localized id="ready-confirmation">
|
||||
<h1 className="text-xl mb-2">Your password has been reset</h1>
|
||||
<h1 className="card-header">Your password has been reset</h1>
|
||||
</Localized>
|
||||
</div>
|
||||
<div className="flex justify-center mx-auto">
|
||||
|
@ -48,9 +46,8 @@ const Ready = ({
|
|||
type="submit"
|
||||
className="cta-primary cta-base-p font-bold mx-2 flex-1"
|
||||
onClick={(e) => {
|
||||
const logViewName = `${viewName}.continue`;
|
||||
const logActionName = `${baseActionName}_continue`;
|
||||
logViewEvent(logViewName, logActionName, {
|
||||
const eventName = `${viewName}.continue`;
|
||||
logViewEvent(viewName, eventName, {
|
||||
entrypoint_variation: 'react',
|
||||
});
|
||||
continueHandler(e);
|
||||
|
|
|
@ -15,7 +15,8 @@ jest.mock('../../lib/metrics', () => ({
|
|||
describe('ResetPasswordConfirmed', () => {
|
||||
it('renders Ready component as expected', () => {
|
||||
render(<ResetPasswordConfirmed />);
|
||||
|
||||
// Calling `getByText` will fail if these elements aren't in the document,
|
||||
// but we test anyway to make the intention of the test explicit
|
||||
const passwordResetConfirmation = screen.getByText(
|
||||
'Your password has been reset'
|
||||
);
|
||||
|
@ -23,23 +24,19 @@ describe('ResetPasswordConfirmed', () => {
|
|||
'You’re now ready to use Account Settings'
|
||||
);
|
||||
const passwordResetContinueButton = screen.queryByText('Continue');
|
||||
|
||||
expect(passwordResetContinueButton).not.toBeInTheDocument();
|
||||
expect(passwordResetConfirmation).toBeInTheDocument();
|
||||
expect(serviceAvailabilityConfirmation).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('emits the expected metrics on render', async () => {
|
||||
it('emits the expected metrics on render', () => {
|
||||
render(<ResetPasswordConfirmed />);
|
||||
expect(usePageViewEvent).toHaveBeenCalledWith(
|
||||
'settings.reset-password-confirmed',
|
||||
{
|
||||
entrypoint_variation: 'react',
|
||||
}
|
||||
);
|
||||
expect(usePageViewEvent).toHaveBeenCalledWith('reset-password-confirmed', {
|
||||
entrypoint_variation: 'react',
|
||||
});
|
||||
});
|
||||
|
||||
it('emits the expected metrics when a user clicks `Continue`', async () => {
|
||||
it('emits the expected metrics when a user clicks `Continue`', () => {
|
||||
render(
|
||||
<ResetPasswordConfirmed
|
||||
continueHandler={() => {
|
||||
|
@ -51,8 +48,8 @@ describe('ResetPasswordConfirmed', () => {
|
|||
|
||||
fireEvent.click(passwordResetContinueButton);
|
||||
expect(logViewEvent).toHaveBeenCalledWith(
|
||||
'settings.reset-password-confirmed.continue',
|
||||
'reset_password_confirmed_continue',
|
||||
'reset-password-confirmed',
|
||||
'reset-password-confirmed.continue',
|
||||
{
|
||||
entrypoint_variation: 'react',
|
||||
}
|
||||
|
|
|
@ -16,17 +16,9 @@ const ResetPasswordConfirmed = ({
|
|||
serviceName,
|
||||
}: ResetPasswordConfirmedProps & RouteComponentProps) => {
|
||||
// This is pretty ridiculously barebones, but the content in here gets expanded on other, similar views.
|
||||
const viewName = 'settings.reset-password-confirmed';
|
||||
const baseActionName = 'reset_password_confirmed';
|
||||
const viewName = 'reset-password-confirmed';
|
||||
|
||||
return (
|
||||
<Ready
|
||||
continueHandler={continueHandler}
|
||||
viewName={viewName}
|
||||
baseActionName={baseActionName}
|
||||
serviceName={serviceName}
|
||||
/>
|
||||
);
|
||||
return <Ready {...{ continueHandler, viewName, serviceName }} />;
|
||||
};
|
||||
|
||||
export default ResetPasswordConfirmed;
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
reset-password-with-recovery-key-verified-generate-new-key = Generate a new account recovery key
|
||||
reset-password-with-recovery-key-verified-continue-to-account = Continue to my account
|
|
@ -0,0 +1,22 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 React from 'react';
|
||||
import ResetPasswordWithRecoveryKeyVerified from '.';
|
||||
import AppLayout from '../../components/AppLayout';
|
||||
import { LocationProvider } from '@reach/router';
|
||||
import { Meta } from '@storybook/react';
|
||||
|
||||
export default {
|
||||
title: 'pages/ResetPasswordWithRecoveryKeyVerified',
|
||||
component: ResetPasswordWithRecoveryKeyVerified,
|
||||
} as Meta;
|
||||
|
||||
export const Default = () => (
|
||||
<LocationProvider>
|
||||
<AppLayout>
|
||||
<ResetPasswordWithRecoveryKeyVerified />
|
||||
</AppLayout>
|
||||
</LocationProvider>
|
||||
);
|
|
@ -0,0 +1,64 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 React from 'react';
|
||||
import { fireEvent, screen } from '@testing-library/react';
|
||||
import { renderWithRouter } from '../../models/mocks';
|
||||
import { getFtlBundle, testAllL10n } from 'fxa-react/lib/test-utils';
|
||||
import { FluentBundle } from '@fluent/bundle';
|
||||
import ResetPasswordWithRecoveryKeyVerified from '.';
|
||||
import { logViewEvent } from '../../lib/metrics';
|
||||
|
||||
jest.mock('../../lib/metrics', () => ({
|
||||
logViewEvent: jest.fn(),
|
||||
usePageViewEvent: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('ResetPasswordWithRecoveryKeyVerified', () => {
|
||||
let bundle: FluentBundle;
|
||||
beforeAll(async () => {
|
||||
bundle = await getFtlBundle('settings');
|
||||
});
|
||||
it('renders default content as expected', () => {
|
||||
renderWithRouter(<ResetPasswordWithRecoveryKeyVerified />);
|
||||
testAllL10n(screen, bundle);
|
||||
|
||||
const newAccountRecoveryKeyButton = screen.getByText(
|
||||
'Generate a new account recovery key'
|
||||
);
|
||||
const continueToAccountLink = screen.getByText('Continue to my account');
|
||||
// Calling `getByText` will fail if these elements aren't in the document,
|
||||
// but we test anyway to make the intention of the test explicit
|
||||
expect(newAccountRecoveryKeyButton).toBeInTheDocument();
|
||||
expect(continueToAccountLink).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('emits the expected metrics when a user generates new recovery keys', async () => {
|
||||
renderWithRouter(<ResetPasswordWithRecoveryKeyVerified />);
|
||||
const newAccountRecoveryKeyButton = screen.getByText(
|
||||
'Generate a new account recovery key'
|
||||
);
|
||||
fireEvent.click(newAccountRecoveryKeyButton);
|
||||
expect(logViewEvent).toHaveBeenCalledWith(
|
||||
'reset-password-with-recovery-key-verified',
|
||||
'reset-password-with-recovery-key-verified.generate-new-key',
|
||||
{
|
||||
entrypoint_variation: 'react',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('emits the expected metrics when a user continues to their account', async () => {
|
||||
renderWithRouter(<ResetPasswordWithRecoveryKeyVerified />);
|
||||
const continueToAccountLink = screen.getByText('Continue to my account');
|
||||
fireEvent.click(continueToAccountLink);
|
||||
expect(logViewEvent).toHaveBeenCalledWith(
|
||||
'reset-password-with-recovery-key-verified',
|
||||
'reset-password-with-recovery-key-verified.continue-to-account',
|
||||
{
|
||||
entrypoint_variation: 'react',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,58 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 React from 'react';
|
||||
import { RouteComponentProps, useNavigate } from '@reach/router';
|
||||
import { FtlMsg } from 'fxa-react/lib/utils';
|
||||
import { logViewEvent } from '../../lib/metrics';
|
||||
import Ready from '../../components/Ready';
|
||||
|
||||
type ResetPasswordWithRecoveryKeyVerifiedProps = {
|
||||
serviceName?: string;
|
||||
};
|
||||
|
||||
const ResetPasswordWithRecoveryKeyVerified = ({
|
||||
serviceName,
|
||||
}: ResetPasswordWithRecoveryKeyVerifiedProps & RouteComponentProps) => {
|
||||
const navigate = useNavigate();
|
||||
const viewName = 'reset-password-with-recovery-key-verified';
|
||||
|
||||
return (
|
||||
<>
|
||||
<Ready {...{ viewName, serviceName }} />
|
||||
<div className="flex justify-center mx-auto m-6">
|
||||
<button
|
||||
className="cta-primary cta-xl"
|
||||
onClick={() => {
|
||||
const eventName = `${viewName}.generate-new-key`;
|
||||
logViewEvent(viewName, eventName, {
|
||||
entrypoint_variation: 'react',
|
||||
});
|
||||
navigate('/settings/account_recovery');
|
||||
}}
|
||||
>
|
||||
<FtlMsg id="reset-password-with-recovery-key-verified-generate-new-key">
|
||||
Generate a new account recovery key
|
||||
</FtlMsg>
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
className="link-blue text-sm"
|
||||
onClick={() => {
|
||||
const eventName = `${viewName}.continue-to-account`;
|
||||
logViewEvent(viewName, eventName, {
|
||||
entrypoint_variation: 'react',
|
||||
});
|
||||
navigate('/settings');
|
||||
}}
|
||||
>
|
||||
<FtlMsg id="reset-password-with-recovery-key-verified-continue-to-account">
|
||||
Continue to my account
|
||||
</FtlMsg>
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResetPasswordWithRecoveryKeyVerified;
|
Загрузка…
Ссылка в новой задаче