mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Unit tests for various modals (#18115)
* Unit tests for Hide Token Confirmation modal * Unit test for Export Private Key modal * Unit test for Customize Nonce modal * Bump coverage targets --------- Co-authored-by: Brad Decker <bhdecker84@gmail.com>
This commit is contained in:
parent
6f2a5faaea
commit
e65b955b19
@ -0,0 +1,119 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Customize Nonce should match snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="modal-container customize-nonce-modal-container"
|
||||
>
|
||||
<div
|
||||
class="modal-container__content customize-nonce-modal-content"
|
||||
>
|
||||
<div
|
||||
class="customize-nonce-modal"
|
||||
>
|
||||
<div
|
||||
class="customize-nonce-modal__main-header"
|
||||
>
|
||||
<h4
|
||||
class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography customize-nonce-modal__main-title typography--h4 typography--weight-bold typography--style-normal typography--color-text-default"
|
||||
>
|
||||
Edit nonce
|
||||
</h4>
|
||||
<button
|
||||
aria-label="Close"
|
||||
class="box mm-button-icon mm-button-icon--size-sm customize-nonce-modal__close box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-icon-default box--background-color-transparent box--rounded-lg"
|
||||
>
|
||||
<span
|
||||
class="box mm-icon mm-icon--size-sm box--display-inline-block box--flex-direction-row box--color-inherit"
|
||||
style="mask-image: url('./images/icons/close.svg');"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-top-2 box--display-inline-flex box--flex-direction-row box--align-items-center"
|
||||
>
|
||||
<h6
|
||||
class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography typography--h6 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
This is an advanced feature, use cautiously.
|
||||
<a
|
||||
class="button btn-link customize-nonce-modal__link"
|
||||
href="https://metamask.zendesk.com/hc/en-us/articles/7417499333531-How-to-customize-a-transaction-nonce"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-top-3 box--flex-direction-row"
|
||||
>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-row box--align-items-center"
|
||||
>
|
||||
<h6
|
||||
class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row box--width-5/6 typography typography--h6 typography--weight-bold typography--style-normal typography--color-text-default"
|
||||
>
|
||||
Edit nonce
|
||||
</h6>
|
||||
<div
|
||||
class="box box--flex-direction-row box--width-1/6"
|
||||
>
|
||||
<a
|
||||
class="button btn-link customize-nonce-modal__reset"
|
||||
data-testid="customize-nonce-reset"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Reset
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="customize-nonce-modal__input"
|
||||
>
|
||||
<div
|
||||
class="MuiFormControl-root MuiTextField-root MuiFormControl-marginDense MuiFormControl-fullWidth"
|
||||
>
|
||||
<div
|
||||
class="MuiInputBase-root MuiInput-root TextField-inputRoot-12 MuiInputBase-fullWidth MuiInput-fullWidth MuiInputBase-formControl MuiInput-formControl MuiInputBase-marginDense MuiInput-marginDense"
|
||||
>
|
||||
<input
|
||||
aria-invalid="false"
|
||||
class="MuiInputBase-input MuiInput-input MuiInputBase-inputMarginDense MuiInput-inputMarginDense"
|
||||
data-testid="custom-nonce-input"
|
||||
dir="auto"
|
||||
id="custom-nonce-id"
|
||||
min="0"
|
||||
placeholder="1"
|
||||
type="number"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="modal-container__footer"
|
||||
>
|
||||
<button
|
||||
class="button btn--rounded btn-secondary modal-container__footer-button"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
class="button btn--rounded btn-primary modal-container__footer-button"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -99,6 +99,7 @@ const CustomizeNonce = ({
|
||||
<Button
|
||||
type="link"
|
||||
className="customize-nonce-modal__reset"
|
||||
data-testid="customize-nonce-reset"
|
||||
onClick={() => {
|
||||
setCustomNonce(nextNonce);
|
||||
}}
|
||||
@ -110,6 +111,7 @@ const CustomizeNonce = ({
|
||||
<div className="customize-nonce-modal__input">
|
||||
<TextField
|
||||
type="number"
|
||||
data-testid="custom-nonce-input"
|
||||
min="0"
|
||||
placeholder={
|
||||
customNonceValue ||
|
||||
|
132
ui/components/app/modals/customize-nonce/customize-nonce.test.js
Normal file
132
ui/components/app/modals/customize-nonce/customize-nonce.test.js
Normal file
@ -0,0 +1,132 @@
|
||||
import React from 'react';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import thunk from 'redux-thunk';
|
||||
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
|
||||
import CustomizeNonce from '.';
|
||||
|
||||
const mockHideModal = jest.fn();
|
||||
|
||||
jest.mock('../../../../store/actions.ts', () => ({
|
||||
...jest.requireActual('../../../../store/actions.ts'),
|
||||
hideModal: () => mockHideModal,
|
||||
}));
|
||||
|
||||
describe('Customize Nonce', () => {
|
||||
const mockState = {
|
||||
appState: {
|
||||
modal: {
|
||||
modalState: {
|
||||
props: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const mockStore = configureMockStore([thunk])(mockState);
|
||||
|
||||
const props = {
|
||||
nextNonce: 1,
|
||||
customNonceValue: '',
|
||||
updateCustomNonce: jest.fn(),
|
||||
getNextNonce: jest.fn(),
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should match snapshot', () => {
|
||||
const { container } = renderWithProvider(
|
||||
<CustomizeNonce {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should change and submit custom nonce', async () => {
|
||||
const { queryByTestId, queryByText } = renderWithProvider(
|
||||
<CustomizeNonce {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const nonceInputEvent = {
|
||||
target: {
|
||||
value: 101,
|
||||
},
|
||||
};
|
||||
|
||||
const nonceInput = queryByTestId('custom-nonce-input');
|
||||
fireEvent.change(nonceInput, nonceInputEvent);
|
||||
expect(nonceInput).toHaveValue(101);
|
||||
|
||||
const saveButton = queryByText('Save');
|
||||
fireEvent.click(saveButton);
|
||||
|
||||
expect(props.updateCustomNonce).toHaveBeenCalledWith('101');
|
||||
expect(props.getNextNonce).toHaveBeenCalled();
|
||||
expect(mockHideModal).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle emptry string custom nonce', () => {
|
||||
const { queryByTestId, queryByText } = renderWithProvider(
|
||||
<CustomizeNonce {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const nonceInputEvent = {
|
||||
target: {
|
||||
value: '',
|
||||
},
|
||||
};
|
||||
|
||||
const nonceInput = queryByTestId('custom-nonce-input');
|
||||
fireEvent.change(nonceInput, nonceInputEvent);
|
||||
|
||||
const saveButton = queryByText('Save');
|
||||
|
||||
fireEvent.click(saveButton);
|
||||
|
||||
expect(props.updateCustomNonce).toHaveBeenCalledWith(
|
||||
props.customNonceValue,
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle cancel', async () => {
|
||||
const { queryByText } = renderWithProvider(
|
||||
<CustomizeNonce {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const modalClose = queryByText('Cancel');
|
||||
|
||||
fireEvent.click(modalClose);
|
||||
|
||||
expect(mockHideModal).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle reset of nonce', async () => {
|
||||
const { queryByTestId } = renderWithProvider(
|
||||
<CustomizeNonce {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const resetNonce = queryByTestId('customize-nonce-reset');
|
||||
|
||||
const nonceInputEvent = {
|
||||
target: {
|
||||
value: 101,
|
||||
},
|
||||
};
|
||||
|
||||
const nonceInput = queryByTestId('custom-nonce-input');
|
||||
|
||||
fireEvent.change(nonceInput, nonceInputEvent);
|
||||
expect(nonceInput).toHaveValue(101);
|
||||
|
||||
fireEvent.click(resetNonce);
|
||||
|
||||
expect(nonceInput).toHaveValue(props.nextNonce);
|
||||
});
|
||||
});
|
@ -0,0 +1,120 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Export PrivateKey Modal should match snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="export-private-key-modal account-modal"
|
||||
style="border-radius: 4px;"
|
||||
>
|
||||
<div
|
||||
class="account-modal__container"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<div
|
||||
class="identicon"
|
||||
style="height: 64px; width: 64px; border-radius: 32px;"
|
||||
>
|
||||
<div
|
||||
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 64px; height: 64px; display: inline-block; background: rgb(250, 58, 0);"
|
||||
>
|
||||
<svg
|
||||
height="64"
|
||||
width="64"
|
||||
x="0"
|
||||
y="0"
|
||||
>
|
||||
<rect
|
||||
fill="#18CDF2"
|
||||
height="64"
|
||||
transform="translate(-2.09678700758788 -6.608568138920997) rotate(328.9 32 32)"
|
||||
width="64"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="#035E56"
|
||||
height="64"
|
||||
transform="translate(-36.59692341766409 21.1849237434972) rotate(176.2 32 32)"
|
||||
width="64"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="#F26602"
|
||||
height="64"
|
||||
transform="translate(33.335684036447844 -28.410279445994163) rotate(468.9 32 32)"
|
||||
width="64"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="account-modal__close"
|
||||
/>
|
||||
<span
|
||||
class="export-private-key-modal__account-name"
|
||||
>
|
||||
Test Account
|
||||
</span>
|
||||
<div
|
||||
class="ellip-address-wrapper"
|
||||
>
|
||||
0x0DCD5D886577d5081B0c52e242Ef29E70Be3E7bc
|
||||
</div>
|
||||
<div
|
||||
class="export-private-key-modal__divider"
|
||||
/>
|
||||
<span
|
||||
class="export-private-key-modal__body-title"
|
||||
>
|
||||
Show Private Keys
|
||||
</span>
|
||||
<div
|
||||
class="export-private-key-modal__password"
|
||||
>
|
||||
<span
|
||||
class="export-private-key-modal__password-label"
|
||||
>
|
||||
Type your MetaMask password
|
||||
</span>
|
||||
<input
|
||||
class="export-private-key-modal__password-input"
|
||||
data-testid="password-input"
|
||||
type="password"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="export-private-key-modal__password--warning"
|
||||
>
|
||||
Warning: Never disclose this key. Anyone with your private keys can steal any assets held in your account.
|
||||
</div>
|
||||
<div
|
||||
class="export-private-key-modal__buttons"
|
||||
>
|
||||
<button
|
||||
class="button btn--rounded btn-secondary btn--large export-private-key-modal__button export-private-key-modal__button--cancel"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
class="button btn--rounded btn-primary btn--large export-private-key-modal__button"
|
||||
disabled=""
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Confirm
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -98,6 +98,7 @@ export default class ExportPrivateKeyModal extends Component {
|
||||
<input
|
||||
type="password"
|
||||
className="export-private-key-modal__password-input"
|
||||
data-testid="password-input"
|
||||
onChange={(event) => this.setState({ password: event.target.value })}
|
||||
/>
|
||||
);
|
||||
|
@ -0,0 +1,81 @@
|
||||
import React from 'react';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import thunk from 'redux-thunk';
|
||||
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
|
||||
import mockState from '../../../../../test/data/mock-state.json';
|
||||
import * as actions from '../../../../store/actions';
|
||||
import ExportPrivateKeyModal from '.';
|
||||
|
||||
jest.mock('../../../../store/actions.ts', () => ({
|
||||
...jest.requireActual('../../../../store/actions.ts'),
|
||||
exportAccount: jest.fn().mockReturnValue(jest.fn().mockResolvedValueOnce()),
|
||||
hideWarning: () => jest.fn(),
|
||||
showModal: () => jest.fn(),
|
||||
hideModal: () => jest.fn(),
|
||||
clearAccountDetails: () => jest.fn(),
|
||||
}));
|
||||
|
||||
describe('Export PrivateKey Modal', () => {
|
||||
const password = 'a-password';
|
||||
|
||||
const privKeyModalState = {
|
||||
...mockState,
|
||||
appState: {
|
||||
...mockState.appState,
|
||||
accountDetail: {
|
||||
privateKey: '0xPrivKey',
|
||||
},
|
||||
},
|
||||
};
|
||||
const mockStore = configureMockStore([thunk])(privKeyModalState);
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should match snapshot', () => {
|
||||
const { container } = renderWithProvider(
|
||||
<ExportPrivateKeyModal />,
|
||||
mockStore,
|
||||
);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should disable confirm button by default', () => {
|
||||
const { queryByText } = renderWithProvider(
|
||||
<ExportPrivateKeyModal />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const confirmButton = queryByText('Confirm');
|
||||
|
||||
expect(confirmButton).toBeDisabled();
|
||||
});
|
||||
|
||||
it('should call export account with password and selected address', () => {
|
||||
const { queryByTestId, queryByText } = renderWithProvider(
|
||||
<ExportPrivateKeyModal />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const passwordInput = queryByTestId('password-input');
|
||||
|
||||
const passwordInputEvent = {
|
||||
target: {
|
||||
value: password,
|
||||
},
|
||||
};
|
||||
|
||||
fireEvent.change(passwordInput, passwordInputEvent);
|
||||
|
||||
const confirmButton = queryByText('Confirm');
|
||||
|
||||
fireEvent.click(confirmButton);
|
||||
|
||||
expect(actions.exportAccount).toHaveBeenCalledWith(
|
||||
password,
|
||||
mockState.metamask.selectedAddress,
|
||||
);
|
||||
});
|
||||
});
|
@ -0,0 +1,93 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Hide Token Confirmation Modal should match snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="hide-token-confirmation"
|
||||
>
|
||||
<div
|
||||
class="hide-token-confirmation__container"
|
||||
>
|
||||
<div
|
||||
class="hide-token-confirmation__title"
|
||||
>
|
||||
Hide token?
|
||||
</div>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<div
|
||||
class="identicon hide-token-confirmation__identicon"
|
||||
style="height: 45px; width: 45px; border-radius: 22.5px;"
|
||||
>
|
||||
<div
|
||||
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 45px; height: 45px; display: inline-block; background: rgb(24, 151, 242);"
|
||||
>
|
||||
<svg
|
||||
height="45"
|
||||
width="45"
|
||||
x="0"
|
||||
y="0"
|
||||
>
|
||||
<rect
|
||||
fill="#2362E1"
|
||||
height="45"
|
||||
transform="translate(5.047495572364477 -7.501374313922141) rotate(458.4 22.5 22.5)"
|
||||
width="45"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="#F94301"
|
||||
height="45"
|
||||
transform="translate(-21.604864626070608 11.239244487403075) rotate(268.8 22.5 22.5)"
|
||||
width="45"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="#FA7900"
|
||||
height="45"
|
||||
transform="translate(-12.763482299017626 41.456272332211) rotate(117.3 22.5 22.5)"
|
||||
width="45"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="hide-token-confirmation__symbol"
|
||||
>
|
||||
TKN
|
||||
</div>
|
||||
<div
|
||||
class="hide-token-confirmation__copy"
|
||||
>
|
||||
You can add this token back in the future by going to “Import token” in your accounts options menu.
|
||||
</div>
|
||||
<div
|
||||
class="hide-token-confirmation__buttons"
|
||||
>
|
||||
<button
|
||||
class="button btn--rounded btn-secondary hide-token-confirmation__button"
|
||||
data-testid="hide-token-confirmation__cancel"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
class="button btn--rounded btn-primary hide-token-confirmation__button"
|
||||
data-testid="hide-token-confirmation__hide"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Hide
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,84 @@
|
||||
import React from 'react';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import thunk from 'redux-thunk';
|
||||
import * as actions from '../../../../store/actions';
|
||||
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
|
||||
import mockState from '../../../../../test/data/mock-state.json';
|
||||
import HideTokenConfirmationModal from '.';
|
||||
|
||||
const mockHistoryPush = jest.fn();
|
||||
const mockHideModal = jest.fn();
|
||||
const mockHideToken = jest.fn().mockResolvedValue();
|
||||
|
||||
jest.mock('../../../../store/actions.ts', () => ({
|
||||
...jest.requireActual('../../../../store/actions.ts'),
|
||||
hideModal: () => mockHideModal,
|
||||
hideToken: () => mockHideToken,
|
||||
ignoreTokens: jest.fn().mockReturnValue(jest.fn().mockResolvedValue()),
|
||||
}));
|
||||
|
||||
describe('Hide Token Confirmation Modal', () => {
|
||||
const tokenState = {
|
||||
address: '0xTokenAddress',
|
||||
symbol: 'TKN',
|
||||
image: '',
|
||||
};
|
||||
|
||||
const tokenModalState = {
|
||||
...mockState,
|
||||
appState: {
|
||||
...mockState.appState,
|
||||
modal: {
|
||||
modalState: {
|
||||
props: {
|
||||
history: {
|
||||
push: mockHistoryPush,
|
||||
},
|
||||
token: tokenState,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const mockStore = configureMockStore([thunk])(tokenModalState);
|
||||
|
||||
it('should match snapshot', () => {
|
||||
const { container } = renderWithProvider(
|
||||
<HideTokenConfirmationModal />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should hide modal', () => {
|
||||
const { queryByTestId } = renderWithProvider(
|
||||
<HideTokenConfirmationModal />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const cancelButton = queryByTestId('hide-token-confirmation__cancel');
|
||||
|
||||
fireEvent.click(cancelButton);
|
||||
|
||||
expect(mockHideModal).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should hide token with token address from state', () => {
|
||||
const { queryByTestId } = renderWithProvider(
|
||||
<HideTokenConfirmationModal />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const hideButton = queryByTestId('hide-token-confirmation__hide');
|
||||
|
||||
fireEvent.click(hideButton);
|
||||
|
||||
expect(mockHideModal).toHaveBeenCalled();
|
||||
expect(actions.ignoreTokens).toHaveBeenCalledWith({
|
||||
tokensToIgnore: tokenState.address,
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user