зеркало из https://github.com/mozilla/fxa.git
storybook:(fxa-settings) add signin-confirmed to storybook
Because: * We're moving the remaining FxA content-server backbone views into React, starting with adding them to storybook. This commit: * Adds in the signin-confirmed/signin-verified views, and modifies the Ready component to accept different values for the header based on which view is being displayed Closes #https://mozilla-hub.atlassian.net/browse/FXA-6417
This commit is contained in:
Родитель
3161a7daf7
Коммит
b24688dcbc
|
@ -1 +1 @@
|
|||
<svg height="2in" width="3in" viewBox="0 0 216 144" xmlns="http://www.w3.org/2000/svg"><style>@keyframes beat{0%,60%,90%,to{transform:scale(1)}25%{transform:scale(.8)}80%{transform:scale(.9)}}.heart{animation:beat 1.5s infinite}</style><radialGradient id="a" cx="85.91" cy="159.8" gradientUnits="userSpaceOnUse" r="102.61"><stop offset=".26" stop-color="#cdcdd4" stop-opacity="0"/><stop offset=".4" stop-color="#cdcdd4" stop-opacity=".02"/><stop offset=".55" stop-color="#cdcdd4" stop-opacity=".08"/><stop offset=".69" stop-color="#cdcdd4" stop-opacity=".18"/><stop offset=".72" stop-color="#cdcdd4" stop-opacity=".2"/></radialGradient><radialGradient id="b" cx="72.32" cy="144.71" gradientUnits="userSpaceOnUse" r="150.75"><stop offset=".27" stop-color="#cdcdd4" stop-opacity="0"/><stop offset=".46" stop-color="#cdcdd4" stop-opacity=".02"/><stop offset=".66" stop-color="#cdcdd4" stop-opacity=".08"/><stop offset=".86" stop-color="#cdcdd4" stop-opacity=".18"/><stop offset=".9" stop-color="#cdcdd4" stop-opacity=".2"/></radialGradient><radialGradient id="c" cx="129.21" cy="117.26" gradientTransform="matrix(1 0 0 .7 0 35.37)" gradientUnits="userSpaceOnUse" r="112.67"><stop offset=".4" stop-color="#cdcdd4" stop-opacity="0"/><stop offset=".58" stop-color="#cdcdd4" stop-opacity=".02"/><stop offset=".77" stop-color="#cdcdd4" stop-opacity=".08"/><stop offset=".96" stop-color="#cdcdd4" stop-opacity=".18"/><stop offset="1" stop-color="#cdcdd4" stop-opacity=".2"/></radialGradient><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="67.44" x2="126.91" y1="85.38" y2="25.9"><stop offset="0" stop-color="#c689ff"/><stop offset="1" stop-color="#d74cf0"/></linearGradient><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="37.24" x2="138.18" y1="121.61" y2="20.67"><stop offset=".22" stop-color="#b833e1"/><stop offset=".91" stop-color="#ff4f5e"/></linearGradient><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="80.06" x2="199.29" y1="149.59" y2="30.36"><stop offset=".28" stop-color="#7542e5"/><stop offset=".42" stop-color="#824deb"/><stop offset=".79" stop-color="#a067fa"/><stop offset="1" stop-color="#ab71ff"/></linearGradient><path d="M71.24 101.17a9.5 9.5 0 01-9.47 9.5H23.69a7.27 7.27 0 010-14.53 7.17 7.17 0 011.75.22 7.3 7.3 0 01-.2-1.69 7.49 7.49 0 017.5-7.49A7.41 7.41 0 0137 88.49a12.61 12.61 0 0124.8 3.17 9.5 9.5 0 019.44 9.51z" fill="url(#a)"/><path d="M190.14 46.66a10.72 10.72 0 00-2.61.32 11.15 11.15 0 00.29-2.53 11.31 11.31 0 00-17.69-9.32 19 19 0 00-37.37 4.78 14.27 14.27 0 100 28.53h57.39a10.89 10.89 0 100-21.78z" fill="url(#b)"/><path d="M24.87 72.66A22.54 22.54 0 0147.32 50l120.77-.48a22.53 22.53 0 11.18 45.06l-120.77.53a22.54 22.54 0 01-22.63-22.45z" fill="url(#c)"/><path d="M83.89 81.48h29.85v8.65H83.89z" fill="#ff848b"/><path d="M61.36 31.98h71.63v47.31H61.36z" fill="url(#d)"/><path d="M140.78 84.07h-1.95V30.31a3.86 3.86 0 00-3.83-3.86H59.46a3.86 3.86 0 00-3.86 3.87v53.75h-2A1.92 1.92 0 0051.72 86v3.9a1.92 1.92 0 001.93 1.93h87.13a1.93 1.93 0 001.93-1.93V86a1.93 1.93 0 00-1.93-1.93zM105 87.94H89.47v-3.87H105z" fill="url(#e)"/><path class="heart" d="M107.33 47.59a6.26 6.26 0 00-8.85 0l-1.27 1.26L96 47.59a6.26 6.26 0 00-8.85 0 6.26 6.26 0 000 8.85l9 9a1.49 1.49 0 001.07.45 1.51 1.51 0 001.08-.45l9-9a6.26 6.26 0 00.03-8.85z" fill="#f9f9fa" style="transform-origin:45% 38%"/><rect fill="url(#f)" height="62.76" rx="5.4" width="41.61" x="122.66" y="54.8"/><path d="M139.53 107.32h7.75v3.87h-7.75z" fill="#ab71ff"/><path class="heart" d="M153.51 73.93a6.26 6.26 0 00-8.85 0l-1.26 1.26-1.26-1.26a6.26 6.26 0 10-8.85 8.85l9 9a1.53 1.53 0 001.08.45 1.51 1.51 0 001.08-.45l9-9a6.26 6.26 0 00.06-8.85z" fill="#f9f9fa" style="transform-origin:66% 56%"/></svg>
|
||||
<svg height="2in" width="3in" viewBox="0 0 216 144" xmlns="http://www.w3.org/2000/svg"><style>@keyframes beat{0%,60%,90%,to{transform:scale(1)}25%{transform:scale(.8)}80%{transform:scale(.9)}}.heart{animation:beat 1.5s infinite}</style><radialGradient id="a" cx="85.91" cy="159.8" gradientUnits="userSpaceOnUse" r="102.61"><stop offset=".26" stop-color="#cdcdd4" stop-opacity="0"/><stop offset=".4" stop-color="#cdcdd4" stop-opacity=".02"/><stop offset=".55" stop-color="#cdcdd4" stop-opacity=".08"/><stop offset=".69" stop-color="#cdcdd4" stop-opacity=".18"/><stop offset=".72" stop-color="#cdcdd4" stop-opacity=".2"/></radialGradient><radialGradient id="b" cx="72.32" cy="144.71" gradientUnits="userSpaceOnUse" r="150.75"><stop offset=".27" stop-color="#cdcdd4" stop-opacity="0"/><stop offset=".46" stop-color="#cdcdd4" stop-opacity=".02"/><stop offset=".66" stop-color="#cdcdd4" stop-opacity=".08"/><stop offset=".86" stop-color="#cdcdd4" stop-opacity=".18"/><stop offset=".9" stop-color="#cdcdd4" stop-opacity=".2"/></radialGradient><radialGradient id="c" cx="129.21" cy="117.26" gradientTransform="matrix(1 0 0 .7 0 35.37)" gradientUnits="userSpaceOnUse" r="112.67"><stop offset=".4" stop-color="#cdcdd4" stop-opacity="0"/><stop offset=".58" stop-color="#cdcdd4" stop-opacity=".02"/><stop offset=".77" stop-color="#cdcdd4" stop-opacity=".08"/><stop offset=".96" stop-color="#cdcdd4" stop-opacity=".18"/><stop offset="1" stop-color="#cdcdd4" stop-opacity=".2"/></radialGradient><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="67.44" x2="126.91" y1="85.38" y2="25.9"><stop offset="0" stop-color="#c689ff"/><stop offset="1" stop-color="#d74cf0"/></linearGradient><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="37.24" x2="138.18" y1="121.61" y2="20.67"><stop offset=".22" stop-color="#b833e1"/><stop offset=".91" stop-color="#ff4f5e"/></linearGradient><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="80.06" x2="199.29" y1="149.59" y2="30.36"><stop offset=".28" stop-color="#7542e5"/><stop offset=".42" stop-color="#824deb"/><stop offset=".79" stop-color="#a067fa"/><stop offset="1" stop-color="#ab71ff"/></linearGradient><path d="M71.24 101.17a9.5 9.5 0 01-9.47 9.5H23.69a7.27 7.27 0 010-14.53 7.17 7.17 0 011.75.22 7.3 7.3 0 01-.2-1.69 7.49 7.49 0 017.5-7.49A7.41 7.41 0 0137 88.49a12.61 12.61 0 0124.8 3.17 9.5 9.5 0 019.44 9.51z" fill="url(#a)"/><path d="M190.14 46.66a10.72 10.72 0 00-2.61.32 11.15 11.15 0 00.29-2.53 11.31 11.31 0 00-17.69-9.32 19 19 0 00-37.37 4.78 14.27 14.27 0 100 28.53h57.39a10.89 10.89 0 100-21.78z" fill="url(#b)"/><path d="M24.87 72.66A22.54 22.54 0 0147.32 50l120.77-.48a22.53 22.53 0 11.18 45.06l-120.77.53a22.54 22.54 0 01-22.63-22.45z" fill="url(#c)"/><path d="M83.89 81.48h29.85v8.65H83.89z" fill="#ff848b"/><path d="M61.36 31.98h71.63v47.31H61.36z" fill="url(#d)"/><path d="M140.78 84.07h-1.95V30.31a3.86 3.86 0 00-3.83-3.86H59.46a3.86 3.86 0 00-3.86 3.87v53.75h-2A1.92 1.92 0 0051.72 86v3.9a1.92 1.92 0 001.93 1.93h87.13a1.93 1.93 0 001.93-1.93V86a1.93 1.93 0 00-1.93-1.93zM105 87.94H89.47v-3.87H105z" fill="url(#e)"/><path class="heart" d="M107.33 47.59a6.26 6.26 0 00-8.85 0l-1.27 1.26L96 47.59a6.26 6.26 0 00-8.85 0 6.26 6.26 0 000 8.85l9 9a1.49 1.49 0 001.07.45 1.51 1.51 0 001.08-.45l9-9a6.26 6.26 0 00.03-8.85z" fill="#f9f9fa" style="transform-origin:45% 38%"/><rect fill="url(#f)" height="62.76" rx="5.4" width="41.61" x="122.66" y="54.8"/><path d="M139.53 107.32h7.75v3.87h-7.75z" fill="#ab71ff"/><path class="heart" d="M153.51 73.93a6.26 6.26 0 00-8.85 0l-1.26 1.26-1.26-1.26a6.26 6.26 0 10-8.85 8.85l9 9a1.53 1.53 0 001.08.45 1.51 1.51 0 001.08-.45l9-9a6.26 6.26 0 00.06-8.85z" fill="#f9f9fa" style="transform-origin:66% 56%"/></svg>
|
||||
|
|
До Ширина: | Высота: | Размер: 3.6 KiB После Ширина: | Высота: | Размер: 3.6 KiB |
|
@ -1,8 +1,11 @@
|
|||
## Ready component
|
||||
|
||||
ready-confirmation = Your password has been reset
|
||||
reset-password-complete-header = Your password has been reset
|
||||
# This is a string that tells the user they can use whatever service prompted them to reset their password
|
||||
# Variables:
|
||||
# $serviceName (String) - the service which caused the user to reset their password
|
||||
# { $serviceName } represents a product name (e.g., Mozilla VPN) that will be passed in as a variable
|
||||
ready-use-service = You’re now ready to use { $serviceName }
|
||||
ready-account-ready = Your account is ready!
|
||||
ready-continue = Continue
|
||||
sign-in-complete-header = Sign-in confirmed
|
||||
pulsing-hearts-description = A pink laptop and a purple mobile device each with a pulsing heart
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/* 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 Ready from '.';
|
||||
import { ViewNameType } from '.';
|
||||
import AppLayout from '../../components/AppLayout';
|
||||
import { Meta } from '@storybook/react';
|
||||
|
||||
export default {
|
||||
title: 'components/Ready',
|
||||
component: Ready,
|
||||
} as Meta;
|
||||
|
||||
type ReadyWithLayoutPropsType = {
|
||||
continueHandler?: Function;
|
||||
isSignedIn?: boolean;
|
||||
serviceName?: string;
|
||||
viewName: ViewNameType;
|
||||
};
|
||||
|
||||
const ReadyWithLayout = ({
|
||||
continueHandler,
|
||||
isSignedIn,
|
||||
serviceName,
|
||||
viewName,
|
||||
}: ReadyWithLayoutPropsType) => {
|
||||
return (
|
||||
<AppLayout>
|
||||
<Ready {...{ continueHandler, isSignedIn, serviceName, viewName }} />
|
||||
</AppLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export const SigninConfirmedOrSigninVerified = () => (
|
||||
<ReadyWithLayout viewName="signin-confirmed" />
|
||||
);
|
||||
|
||||
export const ResetPasswordConfirmForLoggedOutUser = () => (
|
||||
<ReadyWithLayout isSignedIn={false} viewName="reset-password-confirmed" />
|
||||
);
|
||||
|
||||
export const ResetPasswordConfirmedWithRelyingParty = () => (
|
||||
<ReadyWithLayout
|
||||
serviceName="Example Service"
|
||||
viewName="reset-password-confirmed"
|
||||
/>
|
||||
);
|
||||
|
||||
export const WithRelyingPartyNoContinueAction = () => (
|
||||
<ReadyWithLayout serviceName="Example Service" viewName="signin-confirmed" />
|
||||
);
|
||||
|
||||
export const WithRelyingPartyAndContinueAction = () => (
|
||||
<ReadyWithLayout
|
||||
serviceName={'Example Service'}
|
||||
viewName="reset-password-confirmed"
|
||||
continueHandler={() => {
|
||||
console.log('Arbitrary action');
|
||||
}}
|
||||
/>
|
||||
);
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
import React from 'react';
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { getFtlBundle, testL10n } from 'fxa-react/lib/test-utils';
|
||||
import { FluentBundle } from '@fluent/bundle';
|
||||
import Ready from '.';
|
||||
import { logViewEvent, usePageViewEvent } from '../../lib/metrics';
|
||||
|
||||
|
@ -14,10 +16,18 @@ jest.mock('../../lib/metrics', () => ({
|
|||
|
||||
describe('Ready', () => {
|
||||
const customServiceName = 'Example Service';
|
||||
const viewName = 'example-view';
|
||||
const viewName = 'reset-password-confirmed';
|
||||
let bundle: FluentBundle;
|
||||
beforeAll(async () => {
|
||||
bundle = await getFtlBundle('settings');
|
||||
});
|
||||
|
||||
it('renders as expected with default values', () => {
|
||||
render(<Ready viewName={viewName} />);
|
||||
render(<Ready {...{ viewName }} />);
|
||||
const ftlMsgMock = screen.getAllByTestId('ftlmsg-mock')[1];
|
||||
testL10n(ftlMsgMock, bundle, {
|
||||
serviceName: 'Account Settings',
|
||||
});
|
||||
|
||||
const passwordResetConfirmation = screen.getByText(
|
||||
'Your password has been reset'
|
||||
|
@ -33,9 +43,8 @@ describe('Ready', () => {
|
|||
expect(serviceAvailabilityConfirmation).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// it renders as expected with a custom service name.
|
||||
it('renders as expected when given a service name', () => {
|
||||
render(<Ready viewName={viewName} serviceName={customServiceName} />);
|
||||
render(<Ready {...{ viewName }} serviceName={customServiceName} />);
|
||||
|
||||
const passwordResetConfirmation = screen.getByText(
|
||||
'Your password has been reset'
|
||||
|
@ -51,10 +60,25 @@ describe('Ready', () => {
|
|||
expect(serviceAvailabilityConfirmation).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders as expected when page is viewed by a logged out user', () => {
|
||||
render(<Ready isSignedIn={false} {...{ viewName }} />);
|
||||
|
||||
const passwordResetConfirmation = screen.getByText(
|
||||
'Your password has been reset'
|
||||
);
|
||||
const serviceAvailabilityConfirmation = screen.getByText(
|
||||
'Your account is ready!'
|
||||
);
|
||||
expect(passwordResetConfirmation).toBeInTheDocument();
|
||||
expect(serviceAvailabilityConfirmation).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders as expected when given a service name and relier continue action', () => {
|
||||
render(
|
||||
<Ready
|
||||
viewName={viewName}
|
||||
{...{
|
||||
viewName,
|
||||
}}
|
||||
serviceName={customServiceName}
|
||||
continueHandler={() => {
|
||||
console.log('beepboop');
|
||||
|
@ -76,21 +100,21 @@ describe('Ready', () => {
|
|||
expect(serviceAvailabilityConfirmation).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('emits a metrics event on render', async () => {
|
||||
it('emits a metrics event on render', () => {
|
||||
render(<Ready viewName={viewName} />);
|
||||
expect(usePageViewEvent).toHaveBeenCalledWith(viewName, {
|
||||
entrypoint_variation: 'react',
|
||||
});
|
||||
});
|
||||
|
||||
it('emits a metrics event when a user clicks `Continue`', async () => {
|
||||
it('emits a metrics event when a user clicks `Continue`', () => {
|
||||
render(
|
||||
<Ready
|
||||
viewName={viewName}
|
||||
serviceName={customServiceName}
|
||||
continueHandler={() => {
|
||||
console.log('beepboop');
|
||||
}}
|
||||
serviceName={customServiceName}
|
||||
{...{ viewName }}
|
||||
/>
|
||||
);
|
||||
const passwordResetContinueButton = screen.getByText('Continue');
|
||||
|
|
|
@ -4,58 +4,107 @@
|
|||
|
||||
import React from 'react';
|
||||
import { RouteComponentProps } from '@reach/router';
|
||||
import { Localized } from '@fluent/react';
|
||||
import { FtlMsg } from 'fxa-react/lib/utils';
|
||||
import { ReactComponent as PulseHearts } from './account-verified.svg';
|
||||
import { logViewEvent, usePageViewEvent } from '../../lib/metrics';
|
||||
import { useFtlMsgResolver } from '../../models/hooks';
|
||||
|
||||
// We'll actually be getting the isSignedIn value from a context when this is wired up.
|
||||
type ReadyProps = {
|
||||
serviceName?: string;
|
||||
continueHandler?: Function;
|
||||
viewName: string;
|
||||
isSignedIn?: boolean;
|
||||
serviceName?: string;
|
||||
viewName: ViewNameType;
|
||||
};
|
||||
|
||||
export type ViewNameType =
|
||||
| 'signin-confirmed'
|
||||
| 'signin-verified'
|
||||
| 'reset-password-confirmed'
|
||||
| 'reset-password-verified'
|
||||
| 'reset-password-with-recovery-key-verified';
|
||||
|
||||
const getTemplateValues = (viewName: ViewNameType) => {
|
||||
let templateValues = {
|
||||
headerText: '',
|
||||
headerId: '',
|
||||
};
|
||||
switch (viewName) {
|
||||
case 'signin-confirmed':
|
||||
case 'signin-verified':
|
||||
templateValues.headerId = 'sign-in-complete-header';
|
||||
templateValues.headerText = 'Sign-in confirmed';
|
||||
break;
|
||||
case 'reset-password-confirmed':
|
||||
case 'reset-password-with-recovery-key-verified':
|
||||
templateValues.headerId = 'reset-password-complete-header';
|
||||
templateValues.headerText = 'Your password has been reset';
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid view name submitted to Ready component');
|
||||
}
|
||||
return templateValues;
|
||||
};
|
||||
|
||||
const Ready = ({
|
||||
serviceName = 'Account Settings',
|
||||
continueHandler,
|
||||
isSignedIn = true,
|
||||
serviceName = 'Account Settings',
|
||||
viewName,
|
||||
}: ReadyProps & RouteComponentProps) => {
|
||||
usePageViewEvent(viewName, {
|
||||
entrypoint_variation: 'react',
|
||||
});
|
||||
const templateValues = getTemplateValues(viewName);
|
||||
const ftlMsgResolver = useFtlMsgResolver();
|
||||
const pulsingHeartsAltText = ftlMsgResolver.getMsg(
|
||||
'pulsing-hearts-description',
|
||||
'A pink laptop and a purple mobile device each with a pulsing heart'
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-4">
|
||||
<Localized id="ready-confirmation">
|
||||
<h1 className="card-header">Your password has been reset</h1>
|
||||
</Localized>
|
||||
<h1 className="card-header">
|
||||
<FtlMsg id={templateValues.headerId}>
|
||||
{templateValues.headerText}
|
||||
</FtlMsg>
|
||||
</h1>
|
||||
</div>
|
||||
<div className="flex justify-center mx-auto">
|
||||
<PulseHearts />
|
||||
<PulseHearts
|
||||
className="w-3/5"
|
||||
role="img"
|
||||
aria-label={pulsingHeartsAltText}
|
||||
/>
|
||||
</div>
|
||||
<section>
|
||||
<div className="error"></div>
|
||||
<Localized id="ready-use-service">
|
||||
<p className="my-4 text-sm">{`You’re now ready to use ${serviceName}`}</p>
|
||||
</Localized>
|
||||
{isSignedIn ? (
|
||||
<FtlMsg id="ready-use-service" vars={{ serviceName }}>
|
||||
<p className="my-4 text-sm">{`You’re now ready to use ${serviceName}`}</p>
|
||||
</FtlMsg>
|
||||
) : (
|
||||
<FtlMsg id="ready-account-ready">
|
||||
<p className="my-4 text-sm">Your account is ready!</p>
|
||||
</FtlMsg>
|
||||
)}
|
||||
</section>
|
||||
{continueHandler && (
|
||||
<div className="flex justify-center mx-auto mt-6 max-w-64">
|
||||
<Localized id="ready-continue">
|
||||
<button
|
||||
type="submit"
|
||||
className="cta-primary cta-base-p font-bold mx-2 flex-1"
|
||||
onClick={(e) => {
|
||||
const eventName = `${viewName}.continue`;
|
||||
logViewEvent(viewName, eventName, {
|
||||
entrypoint_variation: 'react',
|
||||
});
|
||||
continueHandler(e);
|
||||
}}
|
||||
>
|
||||
Continue
|
||||
</button>
|
||||
</Localized>
|
||||
<button
|
||||
type="submit"
|
||||
className="cta-primary cta-base-p font-bold mx-2 flex-1"
|
||||
onClick={(e) => {
|
||||
const eventName = `${viewName}.continue`;
|
||||
logViewEvent(viewName, eventName, {
|
||||
entrypoint_variation: 'react',
|
||||
});
|
||||
continueHandler(e);
|
||||
}}
|
||||
>
|
||||
<FtlMsg id="ready-continue">Continue</FtlMsg>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
|
|
@ -15,16 +15,12 @@ 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'
|
||||
);
|
||||
const serviceAvailabilityConfirmation = screen.getByText(
|
||||
'You’re now ready to use Account Settings'
|
||||
);
|
||||
const passwordResetContinueButton = screen.queryByText('Continue');
|
||||
expect(passwordResetContinueButton).not.toBeInTheDocument();
|
||||
expect(passwordResetConfirmation).toBeInTheDocument();
|
||||
expect(serviceAvailabilityConfirmation).toBeInTheDocument();
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
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 { getFtlBundle, testL10n } from 'fxa-react/lib/test-utils';
|
||||
import { FluentBundle } from '@fluent/bundle';
|
||||
import ResetPasswordWithRecoveryKeyVerified from '.';
|
||||
import { logViewEvent } from '../../lib/metrics';
|
||||
|
@ -22,7 +22,10 @@ describe('ResetPasswordWithRecoveryKeyVerified', () => {
|
|||
});
|
||||
it('renders default content as expected', () => {
|
||||
renderWithRouter(<ResetPasswordWithRecoveryKeyVerified />);
|
||||
testAllL10n(screen, bundle);
|
||||
const ftlMsgMock = screen.getAllByTestId('ftlmsg-mock')[1];
|
||||
testL10n(ftlMsgMock, bundle, {
|
||||
serviceName: 'Account Settings',
|
||||
});
|
||||
|
||||
const newAccountRecoveryKeyButton = screen.getByText(
|
||||
'Generate a new account recovery key'
|
||||
|
|
|
@ -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 SigninConfirmed from '.';
|
||||
import AppLayout from '../../components/AppLayout';
|
||||
import { LocationProvider } from '@reach/router';
|
||||
import { Meta } from '@storybook/react';
|
||||
|
||||
export default {
|
||||
title: 'pages/SigninConfirmed',
|
||||
component: SigninConfirmed,
|
||||
} as Meta;
|
||||
|
||||
export const Default = () => (
|
||||
<LocationProvider>
|
||||
<AppLayout>
|
||||
<SigninConfirmed />
|
||||
</AppLayout>
|
||||
</LocationProvider>
|
||||
);
|
|
@ -0,0 +1,67 @@
|
|||
/* 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, render, screen } from '@testing-library/react';
|
||||
import { getFtlBundle, testL10n } from 'fxa-react/lib/test-utils';
|
||||
import { FluentBundle } from '@fluent/bundle';
|
||||
import SigninConfirmed from '.';
|
||||
import { logViewEvent, usePageViewEvent } from '../../lib/metrics';
|
||||
|
||||
jest.mock('../../lib/metrics', () => ({
|
||||
logViewEvent: jest.fn(),
|
||||
usePageViewEvent: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('SigninConfirmed', () => {
|
||||
let bundle: FluentBundle;
|
||||
beforeAll(async () => {
|
||||
bundle = await getFtlBundle('settings');
|
||||
});
|
||||
it('renders Ready component as expected', () => {
|
||||
render(<SigninConfirmed />);
|
||||
const ftlMsgMock = screen.getAllByTestId('ftlmsg-mock')[1];
|
||||
testL10n(ftlMsgMock, bundle, {
|
||||
serviceName: 'Account Settings',
|
||||
});
|
||||
|
||||
const signinConfirmation = screen.getByText('Sign-in confirmed');
|
||||
const serviceAvailabilityConfirmation = screen.getByText(
|
||||
'You’re now ready to use Account Settings'
|
||||
);
|
||||
const signinContinueButton = 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(signinContinueButton).not.toBeInTheDocument();
|
||||
expect(signinConfirmation).toBeInTheDocument();
|
||||
expect(serviceAvailabilityConfirmation).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('emits the expected metrics on render', () => {
|
||||
render(<SigninConfirmed />);
|
||||
expect(usePageViewEvent).toHaveBeenCalledWith('signin-confirmed', {
|
||||
entrypoint_variation: 'react',
|
||||
});
|
||||
});
|
||||
|
||||
it('emits the expected metrics when a user clicks `Continue`', () => {
|
||||
render(
|
||||
<SigninConfirmed
|
||||
continueHandler={() => {
|
||||
console.log('beepboop');
|
||||
}}
|
||||
/>
|
||||
);
|
||||
const passwordResetContinueButton = screen.getByText('Continue');
|
||||
|
||||
fireEvent.click(passwordResetContinueButton);
|
||||
expect(logViewEvent).toHaveBeenCalledWith(
|
||||
'signin-confirmed',
|
||||
'signin-confirmed.continue',
|
||||
{
|
||||
entrypoint_variation: 'react',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
/* 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 } from '@reach/router';
|
||||
import Ready from '../../components/Ready';
|
||||
|
||||
type SigninConfirmedProps = {
|
||||
continueHandler?: Function;
|
||||
serviceName?: string;
|
||||
};
|
||||
|
||||
const SigninConfirmed = ({
|
||||
continueHandler,
|
||||
serviceName,
|
||||
}: SigninConfirmedProps & RouteComponentProps) => {
|
||||
const viewName = 'signin-confirmed';
|
||||
|
||||
return <Ready {...{ continueHandler, viewName, serviceName }} />;
|
||||
};
|
||||
|
||||
export default SigninConfirmed;
|
Загрузка…
Ссылка в новой задаче