Skip to content

Commit b0e61a7

Browse files
authored
Merge pull request #17700 from mozilla/FXA-10459
feat(settings): Enable collapsing/expanding reset password warning
2 parents 8dd1802 + e57626e commit b0e61a7

File tree

19 files changed

+292
-252
lines changed

19 files changed

+292
-252
lines changed

packages/functional-tests/pages/resetPassword.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export class ResetPasswordPage extends BaseLayout {
8383
}
8484

8585
get reenterPasswordTextbox() {
86-
return this.page.getByRole('textbox', { name: 'Re-enter password' });
86+
return this.page.getByRole('textbox', { name: 'Confirm password' });
8787
}
8888

8989
get resetPasswordButton() {
@@ -115,14 +115,12 @@ export class ResetPasswordPage extends BaseLayout {
115115
}
116116

117117
get dataLossWarning() {
118-
return this.page.getByText(
119-
'Resetting your password may delete your encrypted browser data.'
120-
);
118+
return this.page.getByText('Your browser data may not be recovered');
121119
}
122120

123121
get resetPasswordWithRecoveryKey() {
124122
return this.page.getByRole('link', {
125-
name: 'Reset your password with your recovery key.',
123+
name: 'Reset your password and keep your data',
126124
});
127125
}
128126

packages/fxa-settings/src/components/FormPasswordWithInlineCriteria/en.ftl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ form-password-with-inline-criteria-signup-submit-button = Create account
99
form-password-with-inline-criteria-reset-new-password =
1010
.label = New password
1111
form-password-with-inline-criteria-confirm-password =
12-
.label = Re-enter password
13-
form-password-with-inline-criteria-reset-submit-button-2 = Create new password
12+
.label = Confirm password
13+
form-password-with-inline-criteria-reset-submit-button = Create new password
1414
1515
form-password-with-inline-criteria-match-error = Passwords do not match
1616
form-password-with-inline-criteria-sr-too-short-message = Password must contain at least 8 characters.

packages/fxa-settings/src/components/FormPasswordWithInlineCriteria/index.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ describe('FormPasswordWithInlineCriteria component', () => {
2727
await waitFor(() => {
2828
screen.getByLabelText('New password');
2929
});
30-
screen.getByLabelText('Re-enter password');
30+
screen.getByLabelText('Confirm password');
3131
screen.getByRole('button', { name: 'Create new password' });
3232
});
3333

packages/fxa-settings/src/components/FormPasswordWithInlineCriteria/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ const getTemplateValues = (passwordFormType: PasswordFormType) => {
5454
templateValues.passwordLabel = 'New password';
5555
templateValues.confirmPasswordFtlId =
5656
'form-password-with-inline-criteria-confirm-password';
57-
templateValues.confirmPasswordLabel = 'Re-enter password';
57+
templateValues.confirmPasswordLabel = 'Confirm password';
5858
templateValues.buttonFtlId =
59-
'form-password-with-inline-criteria-reset-submit-button-2';
59+
'form-password-with-inline-criteria-reset-submit-button';
6060
templateValues.buttonText = 'Create new password';
6161
break;
6262
}

packages/fxa-settings/src/components/PasswordStrengthInline/index.tsx

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -34,80 +34,54 @@ export const PasswordStrengthInline = ({
3434
}: PasswordStrengthInlineProps) => {
3535
return (
3636
<div
37-
className="leading-5 text-sm"
37+
className="text-sm mb-2"
3838
id="password-strength-inline"
3939
aria-live="polite"
4040
>
4141
<p className="mb-2 text-left">
4242
Pick a strong password you haven’t used on other sites. Ensure it meets
4343
the security requirements:
4444
</p>
45-
<ul className="mt-2 mb-2">
46-
<li data-testid="password-min-char-req" className="flex ">
45+
<ul className="mt-2 mb-2 text-grey-400">
46+
<li data-testid="password-min-char-req" className="flex -mb-1">
4747
<span className="w-7 h-7 text-center">
4848
{isPasswordEmpty && '•'}
4949
{!isPasswordEmpty && <ValidationIcon hasError={isTooShort} />}
5050
</span>
5151
<FtlMsg id="password-strength-inline-min-length">
52-
<span
53-
className={`ps-2 ${
54-
!isPasswordEmpty && isTooShort ? 'text-red-700' : ''
55-
}`}
56-
>
57-
At least 8 characters
58-
</span>
52+
<span className="ps-2">At least 8 characters</span>
5953
</FtlMsg>
6054
</li>
61-
<li data-testid="password-not-email-req" className="flex ">
55+
<li data-testid="password-not-email-req" className="flex -mb-1">
6256
<span className="w-7 h-7 text-center">
6357
{isPasswordEmpty && '•'}
6458
{!isPasswordEmpty && (
6559
<ValidationIcon hasError={!isTooShort && isSameAsEmail} />
6660
)}
6761
</span>
6862
<FtlMsg id="password-strength-inline-not-email">
69-
<span
70-
className={`ps-2 ${
71-
!isPasswordEmpty && !isTooShort && isSameAsEmail
72-
? 'text-red-700'
73-
: ''
74-
}`}
75-
>
76-
Not your email address
77-
</span>
63+
<span className="ps-2">Not your email address</span>
7864
</FtlMsg>
7965
</li>
80-
<li data-testid="password-not-common-req" className="flex ">
66+
<li data-testid="password-not-common-req" className="flex -mb-1">
8167
<span className="w-7 h-7 text-center">
8268
{isPasswordEmpty && '•'}
8369
{!isPasswordEmpty && <ValidationIcon hasError={isCommon} />}
8470
</span>
8571
<FtlMsg id="password-strength-inline-not-common">
86-
<span
87-
className={`ps-2 ${
88-
!isPasswordEmpty && isCommon ? 'text-red-700' : ''
89-
}`}
90-
>
91-
Not a commonly used password
92-
</span>
72+
<span className="ps-2">Not a commonly used password</span>
9373
</FtlMsg>
9474
</li>
9575
{isUnconfirmed !== undefined && (
96-
<li data-testid="passwords-match" className="flex ">
76+
<li data-testid="passwords-match" className="flex">
9777
<span className="w-7 h-7 text-center">
9878
{(isPasswordEmpty || isConfirmedPasswordEmpty) && '•'}
9979
{!(isPasswordEmpty || isConfirmedPasswordEmpty) && (
10080
<ValidationIcon hasError={isUnconfirmed} />
10181
)}
10282
</span>
10383
<FtlMsg id="password-strength-inline-confirmed-must-match">
104-
<span
105-
className={`ps-2 ${
106-
!isPasswordEmpty && !isConfirmedPasswordEmpty && isUnconfirmed
107-
? 'text-red-700'
108-
: ''
109-
}`}
110-
>
84+
<span className="ps-2">
11185
Confirmation matches the new password
11286
</span>
11387
</FtlMsg>
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## ResetPasswordWarning component
2+
## Warning shown to sync users that reset their password without using an account recovery key
3+
4+
password-reset-warning-icon = Warning
5+
password-reset-chevron-expanded = Collapse warning
6+
password-reset-chevron-collapsed = Expand warning
7+
8+
password-reset-data-may-not-be-recovered = Your browser data may not be recovered
9+
password-reset-previously-signed-in-device = Have a device where you previously signed in?
10+
password-reset-data-may-be-saved-locally = Your browser data may be locally saved on that device. Sign in there with your new password to restore and sync.
11+
password-reset-no-old-device = Have a new device but don’t have your old one?
12+
password-reset-encrypted-data-cannot-be-recovered = We’re sorry, but your encrypted browser data on Firefox servers can’t be recovered. However, you can still access your local data on any device where you have previously signed in.
13+
password-reset-learn-about-restoring-account-data = Learn more about restoring account data

packages/fxa-settings/src/components/WarningMessage/index.stories.tsx renamed to packages/fxa-settings/src/components/ResetPasswordWarning/indes.stories.tsx

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,19 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
import React from 'react';
6-
import WarningMessage from '.';
7-
import AppLayout from '../AppLayout';
86
import { Meta } from '@storybook/react';
9-
import {
10-
MOCK_WARNING_MESSAGE_FTL_ID,
11-
MOCK_WARNING_MESSAGE,
12-
MOCK_WARNING_TYPE,
13-
} from './mocks';
147
import { withLocalization } from 'fxa-react/lib/storybooks';
8+
import ResetPasswordWarning from '.';
9+
import AppLayout from '../AppLayout';
1510

1611
export default {
17-
title: 'Components/WarningMessage',
18-
component: WarningMessage,
12+
title: 'Components/ResetPasswordWarning',
13+
component: ResetPasswordWarning,
1914
decorators: [withLocalization],
2015
} as Meta;
2116

2217
export const Default = () => (
2318
<AppLayout>
24-
<WarningMessage
25-
warningMessageFtlId={MOCK_WARNING_MESSAGE_FTL_ID}
26-
warningType={MOCK_WARNING_TYPE}
27-
>
28-
{MOCK_WARNING_MESSAGE}
29-
</WarningMessage>
19+
<ResetPasswordWarning />
3020
</AppLayout>
3121
);
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
import { renderWithLocalizationProvider } from 'fxa-react/lib/test-utils/localizationProvider';
6+
import { screen, waitFor } from '@testing-library/react';
7+
import ResetPasswordWarning from '.';
8+
import userEvent from '@testing-library/user-event';
9+
10+
describe('ResetPasswordWarning component', () => {
11+
it('renders as expected', async () => {
12+
renderWithLocalizationProvider(<ResetPasswordWarning />);
13+
14+
expect(
15+
screen.getByRole('img', {
16+
name: 'Warning',
17+
})
18+
).toBeVisible();
19+
20+
expect(
21+
screen.getByText('Your browser data may not be recovered')
22+
).toBeVisible();
23+
24+
expect(screen.getByRole('img', { name: 'Collapse warning' })).toBeVisible();
25+
26+
expect(
27+
screen.getByText('Have a device where you previously signed in?')
28+
).toBeVisible();
29+
30+
expect(
31+
screen.getByText(
32+
'Your browser data may be locally saved on that device. Sign in there with your new password to restore and sync.'
33+
)
34+
).toBeVisible();
35+
36+
expect(
37+
screen.getByText('Have a new device but don’t have your old one?')
38+
).toBeVisible();
39+
40+
expect(
41+
screen.getByText(
42+
'We’re sorry, but your encrypted browser data on Firefox servers can’t be recovered. However, you can still access your local data on any device where you have previously signed in.'
43+
)
44+
).toBeVisible();
45+
46+
expect(
47+
screen.getByRole('link', {
48+
name: 'Learn more about restoring account data',
49+
})
50+
).toBeVisible();
51+
52+
expect(screen.getByRole('link')).toHaveAttribute(
53+
'href',
54+
'https://support.mozilla.org/kb/how-reset-your-password-without-account-recovery-keys-access-data'
55+
);
56+
});
57+
58+
it('renders as expected with mobile width', async () => {
59+
global.innerWidth = 375; // Set mobile width
60+
global.dispatchEvent(new Event('resize'));
61+
62+
renderWithLocalizationProvider(<ResetPasswordWarning />);
63+
64+
expect(
65+
screen.getByRole('img', {
66+
name: 'Warning',
67+
})
68+
).toBeVisible();
69+
70+
expect(
71+
screen.getByText('Your browser data may not be recovered')
72+
).toBeVisible();
73+
74+
expect(screen.getByRole('img', { name: 'Expand warning' })).toBeVisible();
75+
76+
expect(
77+
screen.queryByText('Have a device where you previously signed in?')
78+
).not.toBeVisible();
79+
});
80+
81+
it('handles click/toggle as expected', async () => {
82+
const user = userEvent.setup();
83+
global.innerWidth = 375; // Set mobile width
84+
global.dispatchEvent(new Event('resize'));
85+
86+
renderWithLocalizationProvider(<ResetPasswordWarning />);
87+
88+
user.click(screen.getByRole('img', { name: 'Expand warning' }));
89+
90+
await waitFor(() => {
91+
expect(screen.getByRole('group')).toHaveAttribute('open');
92+
expect(
93+
screen.getByRole('img', { name: 'Collapse warning' })
94+
).toBeVisible();
95+
expect(
96+
screen.queryByRole('img', { name: 'Expand warning' })
97+
).not.toBeInTheDocument();
98+
});
99+
100+
user.click(screen.getByRole('img', { name: 'Collapse warning' }));
101+
102+
await waitFor(() => {
103+
expect(screen.getByRole('group')).not.toHaveAttribute('open');
104+
expect(screen.getByRole('img', { name: 'Expand warning' })).toBeVisible();
105+
expect(
106+
screen.queryByRole('img', { name: 'Collapse warning' })
107+
).not.toBeInTheDocument();
108+
});
109+
});
110+
});

0 commit comments

Comments
 (0)