mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
Create Password onboarding unit test, test-ids, and snapshot (#18257)
* Create Password onboarding unit test, test-ids, and snapshot * Add button inline snapshot check for import wallet text * Don't adjust inlineSnapshot formatting * Get text content --------- Co-authored-by: Brad Decker <bhdecker84@gmail.com>
This commit is contained in:
parent
b91043cf72
commit
8d29fc907d
@ -0,0 +1,172 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Onboarding Create Password Render should match snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="create-password__wrapper"
|
||||
data-testid="create-password"
|
||||
>
|
||||
<div
|
||||
class="box box--margin-bottom-4 box--flex-direction-row"
|
||||
>
|
||||
<ul
|
||||
class="progressbar"
|
||||
>
|
||||
<li
|
||||
class="active"
|
||||
>
|
||||
Create password
|
||||
</li>
|
||||
<li
|
||||
class=""
|
||||
>
|
||||
Secure wallet
|
||||
</li>
|
||||
<li
|
||||
class=""
|
||||
>
|
||||
Confirm secret recovery phrase
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<h2
|
||||
class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography typography--h2 typography--weight-bold typography--style-normal typography--color-text-default"
|
||||
>
|
||||
Create password
|
||||
</h2>
|
||||
<h4
|
||||
class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography typography--h4 typography--weight-normal typography--style-normal typography--align-center typography--color-text-default"
|
||||
>
|
||||
This password will unlock your MetaMask wallet only on this device. MetaMask can not recover this password.
|
||||
</h4>
|
||||
<div
|
||||
class="box box--margin-top-3 box--flex-direction-row box--justify-content-center box--display-flex"
|
||||
>
|
||||
<form
|
||||
class="create-password__form"
|
||||
>
|
||||
<div
|
||||
class="form-field"
|
||||
>
|
||||
<label
|
||||
class="box box--flex-direction-row"
|
||||
>
|
||||
<div
|
||||
class="form-field__heading"
|
||||
>
|
||||
<div
|
||||
class="box form-field__heading-title box--display-flex box--flex-direction-row box--align-items-baseline"
|
||||
>
|
||||
<h6
|
||||
class="box box--margin-top-1 box--margin-bottom-1 box--display-inline-block box--flex-direction-row typography typography--h6 typography--weight-bold typography--style-normal typography--color-text-default"
|
||||
>
|
||||
New password (8 characters min)
|
||||
</h6>
|
||||
|
||||
|
||||
</div>
|
||||
<div
|
||||
class="box form-field__heading-detail box--margin-right-2 box--flex-direction-row box--text-align-end"
|
||||
>
|
||||
<h6
|
||||
class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography typography--h7 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
<a
|
||||
class="create-password__form--password-button"
|
||||
data-testid="show-password"
|
||||
href=""
|
||||
>
|
||||
Show
|
||||
</a>
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
class="form-field__input"
|
||||
data-testid="create-password-new"
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
|
||||
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="form-field"
|
||||
>
|
||||
<label
|
||||
class="box box--flex-direction-row"
|
||||
>
|
||||
<div
|
||||
class="form-field__heading"
|
||||
>
|
||||
<div
|
||||
class="box form-field__heading-title box--display-flex box--flex-direction-row box--align-items-baseline"
|
||||
>
|
||||
<h6
|
||||
class="box box--margin-top-1 box--margin-bottom-1 box--display-inline-block box--flex-direction-row typography typography--h6 typography--weight-bold typography--style-normal typography--color-text-default"
|
||||
>
|
||||
Confirm password
|
||||
</h6>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
class="form-field__input"
|
||||
data-testid="create-password-confirm"
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-bottom-4 box--flex-direction-row box--justify-content-space-between box--align-items-center box--display-flex"
|
||||
>
|
||||
<label
|
||||
class="create-password__form__terms-label"
|
||||
>
|
||||
<input
|
||||
class="check-box far fa-square"
|
||||
data-testid="create-password-terms"
|
||||
readonly=""
|
||||
type="checkbox"
|
||||
/>
|
||||
<h5
|
||||
class="box box--margin-top-1 box--margin-bottom-1 box--margin-left-3 box--flex-direction-row typography typography--h5 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
<span>
|
||||
|
||||
I understand that MetaMask cannot recover this password for me.
|
||||
<a
|
||||
href="https://metamask.zendesk.com/hc/en-us/articles/4404722782107"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<span
|
||||
class="create-password__link-text"
|
||||
>
|
||||
Learn more
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
||||
</span>
|
||||
</h5>
|
||||
</label>
|
||||
</div>
|
||||
<button
|
||||
class="button btn--rounded btn-primary btn--large create-password__form--submit-button"
|
||||
data-testid="create-password-wallet"
|
||||
disabled=""
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Create a new wallet
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -85,6 +85,7 @@ export default function CreatePassword({
|
||||
if (isTooShort) {
|
||||
return {
|
||||
className: 'create-password__weak',
|
||||
dataTestId: 'short-password-error',
|
||||
text: t('passwordNotLongEnough'),
|
||||
description: '',
|
||||
};
|
||||
@ -92,6 +93,7 @@ export default function CreatePassword({
|
||||
if (score >= 4) {
|
||||
return {
|
||||
className: 'create-password__strong',
|
||||
dataTestId: 'strong-password',
|
||||
text: t('strong'),
|
||||
description: '',
|
||||
};
|
||||
@ -99,12 +101,14 @@ export default function CreatePassword({
|
||||
if (score === 3) {
|
||||
return {
|
||||
className: 'create-password__average',
|
||||
dataTestId: 'average-password',
|
||||
text: t('average'),
|
||||
description: t('passwordStrengthDescription'),
|
||||
};
|
||||
}
|
||||
return {
|
||||
className: 'create-password__weak',
|
||||
dataTestId: 'weak-password',
|
||||
text: t('weak'),
|
||||
description: t('passwordStrengthDescription'),
|
||||
};
|
||||
@ -116,7 +120,11 @@ export default function CreatePassword({
|
||||
const { score } = zxcvbn(passwordInput);
|
||||
const passwordStrengthLabel = getPasswordStrengthLabel(isTooShort, score);
|
||||
const passwordStrengthComponent = t('passwordStrength', [
|
||||
<span key={score} className={passwordStrengthLabel.className}>
|
||||
<span
|
||||
key={score}
|
||||
data-testid={passwordStrengthLabel.dataTestId}
|
||||
className={passwordStrengthLabel.className}
|
||||
>
|
||||
{passwordStrengthLabel.text}
|
||||
</span>,
|
||||
]);
|
||||
@ -206,6 +214,7 @@ export default function CreatePassword({
|
||||
<Typography variant={TypographyVariant.H7}>
|
||||
<a
|
||||
href=""
|
||||
data-testid="show-password"
|
||||
className="create-password__form--password-button"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
395
ui/pages/onboarding-flow/create-password/create-password.test.js
Normal file
395
ui/pages/onboarding-flow/create-password/create-password.test.js
Normal file
@ -0,0 +1,395 @@
|
||||
import React from 'react';
|
||||
import { fireEvent, waitFor } from '@testing-library/react';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import initializedMockState from '../../../../test/data/mock-send-state.json';
|
||||
import {
|
||||
ONBOARDING_SECURE_YOUR_WALLET_ROUTE,
|
||||
ONBOARDING_COMPLETION_ROUTE,
|
||||
} from '../../../helpers/constants/routes';
|
||||
import { FIRST_TIME_FLOW_TYPES } from '../../../helpers/constants/onboarding';
|
||||
import CreatePassword from './create-password';
|
||||
|
||||
const mockHistoryPush = jest.fn();
|
||||
const mockHistoryReplace = jest.fn();
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useHistory: () => ({
|
||||
push: mockHistoryPush,
|
||||
replace: mockHistoryReplace,
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('Onboarding Create Password', () => {
|
||||
const mockState = {
|
||||
metamask: {
|
||||
identities: {},
|
||||
selectedAddress: '',
|
||||
},
|
||||
};
|
||||
|
||||
const mockCreateNewAccount = jest.fn().mockResolvedValue();
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('Initialized State Conditionals with keyrings and firstTimeFlowType', () => {
|
||||
it('should route to secure your wallet when keyring is present but not imported first time flow type', () => {
|
||||
const mockStore = configureMockStore()(initializedMockState);
|
||||
|
||||
renderWithProvider(<CreatePassword />, mockStore);
|
||||
expect(mockHistoryReplace).toHaveBeenCalledWith(
|
||||
ONBOARDING_SECURE_YOUR_WALLET_ROUTE,
|
||||
);
|
||||
});
|
||||
|
||||
it('should route to completion when keyring is present and imported first time flow type', () => {
|
||||
const importFirstTimeFlowState = {
|
||||
...initializedMockState,
|
||||
metamask: {
|
||||
...initializedMockState.metamask,
|
||||
firstTimeFlowType: 'import',
|
||||
},
|
||||
};
|
||||
const mockStore = configureMockStore()(importFirstTimeFlowState);
|
||||
|
||||
renderWithProvider(<CreatePassword />, mockStore);
|
||||
expect(mockHistoryReplace).toHaveBeenCalledWith(
|
||||
ONBOARDING_COMPLETION_ROUTE,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Render', () => {
|
||||
it('should match snapshot', () => {
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
const { container } = renderWithProvider(<CreatePassword />, mockStore);
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Password Validation Checks', () => {
|
||||
it('should show password as text when click Show under password', () => {
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
const { queryByTestId } = renderWithProvider(
|
||||
<CreatePassword />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const createPassword = queryByTestId('create-password-new');
|
||||
const event = {
|
||||
target: {
|
||||
value: '1234567',
|
||||
},
|
||||
};
|
||||
|
||||
fireEvent.change(createPassword, event);
|
||||
|
||||
expect(createPassword).toHaveAttribute('type', 'password');
|
||||
|
||||
const showPassword = queryByTestId('show-password');
|
||||
|
||||
fireEvent.click(showPassword);
|
||||
|
||||
expect(createPassword).toHaveAttribute('type', 'text');
|
||||
});
|
||||
it('should disable create new account button and show short password error with password length of 7', () => {
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
const { queryByTestId } = renderWithProvider(
|
||||
<CreatePassword createNewAccount={mockCreateNewAccount} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const createPassword = queryByTestId('create-password-new');
|
||||
const event = {
|
||||
target: {
|
||||
value: '1234567',
|
||||
},
|
||||
};
|
||||
|
||||
fireEvent.change(createPassword, event);
|
||||
|
||||
const shortPasswordError = queryByTestId('short-password-error');
|
||||
expect(shortPasswordError).toBeInTheDocument();
|
||||
|
||||
const createNewWalletButton = queryByTestId('create-password-wallet');
|
||||
|
||||
expect(createNewWalletButton).toBeDisabled();
|
||||
|
||||
fireEvent.click(createNewWalletButton);
|
||||
expect(mockCreateNewAccount).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should show weak password strength', () => {
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
const { queryByTestId } = renderWithProvider(
|
||||
<CreatePassword createNewAccount={mockCreateNewAccount} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const createNewWalletButton = queryByTestId('create-password-wallet');
|
||||
|
||||
const createPassword = queryByTestId('create-password-new');
|
||||
const event = {
|
||||
target: {
|
||||
value: '12345678',
|
||||
},
|
||||
};
|
||||
|
||||
fireEvent.change(createPassword, event);
|
||||
|
||||
const weakPasswordError = queryByTestId('weak-password');
|
||||
expect(weakPasswordError).toBeInTheDocument();
|
||||
|
||||
expect(createNewWalletButton).toBeDisabled();
|
||||
|
||||
fireEvent.click(createNewWalletButton);
|
||||
|
||||
expect(mockCreateNewAccount).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should show average password strength', () => {
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
const { queryByTestId } = renderWithProvider(
|
||||
<CreatePassword createNewAccount={mockCreateNewAccount} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const createNewWalletButton = queryByTestId('create-password-wallet');
|
||||
|
||||
const createPassword = queryByTestId('create-password-new');
|
||||
const event = {
|
||||
target: {
|
||||
value: 'ZsE(!6679',
|
||||
},
|
||||
};
|
||||
|
||||
fireEvent.change(createPassword, event);
|
||||
|
||||
const weakPasswordError = queryByTestId('average-password');
|
||||
expect(weakPasswordError).toBeInTheDocument();
|
||||
|
||||
expect(createNewWalletButton).toBeDisabled();
|
||||
|
||||
fireEvent.click(createNewWalletButton);
|
||||
|
||||
expect(mockCreateNewAccount).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should show strong password strength', () => {
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
const { queryByTestId } = renderWithProvider(
|
||||
<CreatePassword createNewAccount={mockCreateNewAccount} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const createPassword = queryByTestId('create-password-new');
|
||||
const event = {
|
||||
target: {
|
||||
value: 'E}URkDoV|/*,pxI',
|
||||
},
|
||||
};
|
||||
|
||||
fireEvent.change(createPassword, event);
|
||||
|
||||
const weakPasswordError = queryByTestId('strong-password');
|
||||
expect(weakPasswordError).toBeInTheDocument();
|
||||
|
||||
const createNewWalletButton = queryByTestId('create-password-wallet');
|
||||
|
||||
expect(createNewWalletButton).toBeDisabled();
|
||||
|
||||
fireEvent.click(createNewWalletButton);
|
||||
|
||||
expect(mockCreateNewAccount).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should show mismatch password error', () => {
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
const { queryByTestId, queryByText } = renderWithProvider(
|
||||
<CreatePassword createNewAccount={mockCreateNewAccount} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const createPassword = queryByTestId('create-password-new');
|
||||
const confirmPassword = queryByTestId('create-password-confirm');
|
||||
|
||||
const createPasswordEvent = {
|
||||
target: {
|
||||
value: '123456789',
|
||||
},
|
||||
};
|
||||
const confirmPasswordEvent = {
|
||||
target: {
|
||||
value: '12345678',
|
||||
},
|
||||
};
|
||||
|
||||
fireEvent.change(createPassword, createPasswordEvent);
|
||||
fireEvent.change(confirmPassword, confirmPasswordEvent);
|
||||
|
||||
const passwordMismatchError = queryByText("Passwords don't match");
|
||||
|
||||
expect(passwordMismatchError).toBeInTheDocument();
|
||||
|
||||
const createNewWalletButton = queryByTestId('create-password-wallet');
|
||||
|
||||
expect(createNewWalletButton).toBeDisabled();
|
||||
|
||||
fireEvent.click(createNewWalletButton);
|
||||
|
||||
expect(mockCreateNewAccount).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not create new wallet without terms checked', () => {
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
const { queryByTestId } = renderWithProvider(
|
||||
<CreatePassword createNewAccount={mockCreateNewAccount} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const createPassword = queryByTestId('create-password-new');
|
||||
const confirmPassword = queryByTestId('create-password-confirm');
|
||||
|
||||
const createPasswordEvent = {
|
||||
target: {
|
||||
value: '12345678',
|
||||
},
|
||||
};
|
||||
const confirmPasswordEvent = {
|
||||
target: {
|
||||
value: '12345678',
|
||||
},
|
||||
};
|
||||
|
||||
fireEvent.change(createPassword, createPasswordEvent);
|
||||
fireEvent.change(confirmPassword, confirmPasswordEvent);
|
||||
|
||||
const terms = queryByTestId('create-password-terms');
|
||||
|
||||
expect(terms).not.toBeChecked();
|
||||
|
||||
const createNewWalletButton = queryByTestId('create-password-wallet');
|
||||
|
||||
expect(createNewWalletButton).toBeDisabled();
|
||||
|
||||
fireEvent.click(createNewWalletButton);
|
||||
|
||||
expect(mockCreateNewAccount).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Create New Account', () => {
|
||||
it('should create new account with correct passwords and terms checked', async () => {
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
const { queryByTestId } = renderWithProvider(
|
||||
<CreatePassword createNewAccount={mockCreateNewAccount} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const createPassword = queryByTestId('create-password-new');
|
||||
const confirmPassword = queryByTestId('create-password-confirm');
|
||||
|
||||
const password = '12345678';
|
||||
|
||||
const createPasswordEvent = {
|
||||
target: {
|
||||
value: password,
|
||||
},
|
||||
};
|
||||
const confirmPasswordEvent = {
|
||||
target: {
|
||||
value: password,
|
||||
},
|
||||
};
|
||||
|
||||
fireEvent.change(createPassword, createPasswordEvent);
|
||||
fireEvent.change(confirmPassword, confirmPasswordEvent);
|
||||
|
||||
const terms = queryByTestId('create-password-terms');
|
||||
fireEvent.click(terms);
|
||||
|
||||
const createNewWalletButton = queryByTestId('create-password-wallet');
|
||||
|
||||
expect(createNewWalletButton).not.toBeDisabled();
|
||||
|
||||
fireEvent.click(createNewWalletButton);
|
||||
|
||||
expect(mockCreateNewAccount).toHaveBeenCalledWith(password);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockHistoryPush).toHaveBeenCalledWith(
|
||||
ONBOARDING_SECURE_YOUR_WALLET_ROUTE,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Import Wallet', () => {
|
||||
const importMockState = {
|
||||
...mockState,
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
firstTimeFlowType: FIRST_TIME_FLOW_TYPES.IMPORT,
|
||||
},
|
||||
};
|
||||
|
||||
it('should import wallet', async () => {
|
||||
const mockStore = configureMockStore()(importMockState);
|
||||
|
||||
const props = {
|
||||
importWithRecoveryPhrase: jest.fn().mockResolvedValue(),
|
||||
secretRecoveryPhrase: 'SRP',
|
||||
};
|
||||
|
||||
const { queryByTestId } = renderWithProvider(
|
||||
<CreatePassword {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const createPassword = queryByTestId('create-password-new');
|
||||
const confirmPassword = queryByTestId('create-password-confirm');
|
||||
|
||||
const password = '12345678';
|
||||
|
||||
const createPasswordEvent = {
|
||||
target: {
|
||||
value: password,
|
||||
},
|
||||
};
|
||||
const confirmPasswordEvent = {
|
||||
target: {
|
||||
value: password,
|
||||
},
|
||||
};
|
||||
|
||||
fireEvent.change(createPassword, createPasswordEvent);
|
||||
fireEvent.change(confirmPassword, confirmPasswordEvent);
|
||||
|
||||
const terms = queryByTestId('create-password-terms');
|
||||
fireEvent.click(terms);
|
||||
|
||||
const importWalletButton = queryByTestId('create-password-import');
|
||||
|
||||
expect(importWalletButton.textContent).toMatchInlineSnapshot(
|
||||
`"Import my wallet"`,
|
||||
);
|
||||
|
||||
fireEvent.click(importWalletButton);
|
||||
|
||||
expect(props.importWithRecoveryPhrase).toHaveBeenCalledWith(
|
||||
password,
|
||||
props.secretRecoveryPhrase,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockHistoryPush).toHaveBeenCalledWith(
|
||||
ONBOARDING_COMPLETION_ROUTE,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user