mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Continue converting tests from enzyme to @testing-library/react (#16373)
* Add transaction activity log component * Remove duplicate tx activity log snapshot. * Convert Identicon test to tlr. * Convert Metafoxlogo test to tlr. * Convert Reveal Seed Phrase test to tlr. * Consolidate and convert Send Footer test to tlr. * Convert Settings test to tlr. * Consolidate and convert security tab test to tlr. * Convert null selectedOption to empty string, and add test id to Dropdown component. * Add Send state to mock-state * Lint mock-state.json
This commit is contained in:
parent
83ec64ddd2
commit
646dbaaff2
@ -12,12 +12,15 @@
|
||||
"previousModalState": {
|
||||
"name": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"warning": null
|
||||
},
|
||||
"history": {
|
||||
"mostRecentOverviewPage": "/"
|
||||
"mostRecentOverviewPage": "/mostRecentOverviewPage"
|
||||
},
|
||||
"metamask": {
|
||||
"usePhishDetect": true,
|
||||
"participateInMetaMetrics": false,
|
||||
"gasEstimateType": "fee-market",
|
||||
"gasFeeEstimates": {
|
||||
"low": {
|
||||
@ -46,6 +49,7 @@
|
||||
"priorityFeeTrend": "down",
|
||||
"networkCongestion": 0.90625
|
||||
},
|
||||
"snaps": [{}],
|
||||
"preferences": {
|
||||
"hideZeroBalanceTokens": false,
|
||||
"showFiatInTestnets": false,
|
||||
@ -241,20 +245,6 @@
|
||||
"unapprovedEncryptionPublicKeyMsgCount": 0,
|
||||
"unapprovedTypedMessages": {},
|
||||
"unapprovedTypedMessagesCount": 0,
|
||||
"send": {
|
||||
"gasLimit": "0x5208",
|
||||
"gasPrice": "0xee6b2800",
|
||||
"gasTotal": "0x4c65c6294000",
|
||||
"tokenBalance": null,
|
||||
"from": "0xc42edfcc21ed14dda456aa0756c153f7985d8813",
|
||||
"to": "",
|
||||
"amount": "1bc16d674ec80000",
|
||||
"memo": "",
|
||||
"errors": {},
|
||||
"maxModeOn": false,
|
||||
"editingTransactionId": null,
|
||||
"toNickname": ""
|
||||
},
|
||||
"useTokenDetection": true,
|
||||
"advancedGasFee": {
|
||||
"maxBaseFee": "75",
|
||||
@ -1284,5 +1274,24 @@
|
||||
"origin": "tmashuang.github.io"
|
||||
}
|
||||
]
|
||||
},
|
||||
"send": {
|
||||
"amountMode": "INPUT",
|
||||
"currentTransactionUUID": null,
|
||||
"draftTransactions": {},
|
||||
"eip1559support": false,
|
||||
"gasEstimateIsLoading": true,
|
||||
"gasEstimatePollToken": null,
|
||||
"gasIsSetInModal": false,
|
||||
"gasPriceEstimate": "0x0",
|
||||
"gasLimitMinimum": "0x5208",
|
||||
"gasTotalForLayer1": "0x0",
|
||||
"recipientMode": "CONTACT_LIST",
|
||||
"recipientInput": "",
|
||||
"selectedAccount": {
|
||||
"address": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
|
||||
"balance": "0x0"
|
||||
},
|
||||
"stage": "INACTIVE"
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,10 @@ const Dropdown = ({
|
||||
disabled = false,
|
||||
onChange,
|
||||
options,
|
||||
selectedOption = null,
|
||||
selectedOption = '',
|
||||
style,
|
||||
title,
|
||||
'data-testid': dataTestId,
|
||||
}) => {
|
||||
const _onChange = useCallback(
|
||||
(event) => {
|
||||
@ -25,6 +26,7 @@ const Dropdown = ({
|
||||
<div className={classnames('dropdown', className)}>
|
||||
<select
|
||||
className="dropdown__select"
|
||||
data-testid={dataTestId}
|
||||
disabled={disabled}
|
||||
title={title}
|
||||
onChange={_onChange}
|
||||
@ -78,6 +80,10 @@ Dropdown.propTypes = {
|
||||
* Add inline style for the component
|
||||
*/
|
||||
style: PropTypes.object,
|
||||
/**
|
||||
* Unit testing test id
|
||||
*/
|
||||
'data-testid': PropTypes.string,
|
||||
};
|
||||
|
||||
export default Dropdown;
|
||||
|
@ -0,0 +1,70 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Identicon should match snapshot with address prop div 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<div
|
||||
class="identicon test-address"
|
||||
style="height: 46px; width: 46px; border-radius: 23px;"
|
||||
>
|
||||
<div
|
||||
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 46px; height: 46px; display: inline-block; background: rgb(24, 151, 242);"
|
||||
>
|
||||
<svg
|
||||
height="46"
|
||||
width="46"
|
||||
x="0"
|
||||
y="0"
|
||||
>
|
||||
<rect
|
||||
fill="#2362E1"
|
||||
height="46"
|
||||
transform="translate(5.159662140639244 -7.668071520898189) rotate(458.4 23 23)"
|
||||
width="46"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="#F94301"
|
||||
height="46"
|
||||
transform="translate(-22.084972728872177 11.489005476012034) rotate(268.8 23 23)"
|
||||
width="46"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="#FA7900"
|
||||
height="46"
|
||||
transform="translate(-13.047115238995795 42.377522828482356) rotate(117.3 23 23)"
|
||||
width="46"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Identicon should match snapshot with custom image and className props 1`] = `
|
||||
<div>
|
||||
<img
|
||||
alt=""
|
||||
class="identicon test-image"
|
||||
src="test-image"
|
||||
style="height: 46px; width: 46px; border-radius: 23px;"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Identicon should match snapshot with default props 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="identicon__image-border"
|
||||
style="height: 46px; width: 46px; border-radius: 23px;"
|
||||
/>
|
||||
</div>
|
||||
`;
|
@ -1,52 +1,51 @@
|
||||
import React from 'react';
|
||||
import thunk from 'redux-thunk';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import { mount } from 'enzyme';
|
||||
import Identicon from './identicon.component';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import Identicon from '.';
|
||||
|
||||
describe('Identicon', () => {
|
||||
const state = {
|
||||
const mockState = {
|
||||
metamask: {
|
||||
provider: {
|
||||
chainId: '0x99',
|
||||
},
|
||||
useBlockie: false,
|
||||
},
|
||||
};
|
||||
|
||||
const middlewares = [thunk];
|
||||
const mockStore = configureMockStore(middlewares);
|
||||
const store = mockStore(state);
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
|
||||
it('renders empty identicon with no props', () => {
|
||||
const wrapper = mount(<Identicon store={store} />);
|
||||
it('should match snapshot with default props', () => {
|
||||
const { container } = renderWithProvider(<Identicon />, mockStore);
|
||||
|
||||
expect(wrapper.find('div').prop('className')).toStrictEqual(
|
||||
'identicon__image-border',
|
||||
);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders custom image and add className props', () => {
|
||||
const wrapper = mount(
|
||||
<Identicon store={store} className="test-image" image="test-image" />,
|
||||
it('should match snapshot with custom image and className props', () => {
|
||||
const props = {
|
||||
className: 'test-image',
|
||||
image: 'test-image',
|
||||
};
|
||||
|
||||
const { container } = renderWithProvider(
|
||||
<Identicon {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
expect(wrapper.find('img.test-image').prop('className')).toStrictEqual(
|
||||
'identicon test-image',
|
||||
);
|
||||
expect(wrapper.find('img.test-image').prop('src')).toStrictEqual(
|
||||
'test-image',
|
||||
);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders div with address prop', () => {
|
||||
const wrapper = mount(
|
||||
<Identicon
|
||||
store={store}
|
||||
className="test-address"
|
||||
address="0x0000000000000000000000000000000000000000"
|
||||
/>,
|
||||
it('should match snapshot with address prop div', () => {
|
||||
const props = {
|
||||
className: 'test-address',
|
||||
address: '0x0000000000000000000000000000000000000000',
|
||||
};
|
||||
|
||||
const { container } = renderWithProvider(
|
||||
<Identicon {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
expect(wrapper.find('div.test-address').prop('className')).toStrictEqual(
|
||||
'identicon test-address',
|
||||
);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,35 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`MetaFoxLogo does not set icon height and width when unsetIconHeight is true 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="app-header__logo-container"
|
||||
data-testid="app-header-logo"
|
||||
>
|
||||
<div />
|
||||
<img
|
||||
alt=""
|
||||
class="app-header__metafox-logo--icon"
|
||||
src="./images/logo/metamask-fox.svg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`MetaFoxLogo should match snapshot with img width and height default set to 42 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="app-header__logo-container"
|
||||
data-testid="app-header-logo"
|
||||
>
|
||||
<div />
|
||||
<img
|
||||
alt=""
|
||||
class="app-header__metafox-logo--icon"
|
||||
height="42"
|
||||
src="./images/logo/metamask-fox.svg"
|
||||
width="42"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -1,27 +1,22 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import MetaFoxLogo from '.';
|
||||
|
||||
describe('MetaFoxLogo', () => {
|
||||
it('sets icon height and width to 42 by default', () => {
|
||||
const wrapper = mount(<MetaFoxLogo />);
|
||||
// eslint-disable-next-line react/display-name
|
||||
jest.mock('./horizontal-logo.js', () => () => {
|
||||
return <div></div>;
|
||||
});
|
||||
|
||||
expect(
|
||||
wrapper.find('img.app-header__metafox-logo--icon').prop('width'),
|
||||
).toStrictEqual(42);
|
||||
expect(
|
||||
wrapper.find('img.app-header__metafox-logo--icon').prop('height'),
|
||||
).toStrictEqual(42);
|
||||
describe('MetaFoxLogo', () => {
|
||||
it('should match snapshot with img width and height default set to 42', () => {
|
||||
const { container } = renderWithProvider(<MetaFoxLogo />);
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('does not set icon height and width when unsetIconHeight is true', () => {
|
||||
const wrapper = mount(<MetaFoxLogo unsetIconHeight />);
|
||||
const { container } = renderWithProvider(<MetaFoxLogo unsetIconHeight />);
|
||||
|
||||
expect(
|
||||
wrapper.find('img.app-header__metafox-logo--icon').prop('width'),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
wrapper.find('img.app-header__metafox-logo--icon').prop('height'),
|
||||
).toBeUndefined();
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,135 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Reveal Secret Recovery Phrase should match snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="reveal-seed-phrase"
|
||||
data-testid="reveal-seed-phrase"
|
||||
>
|
||||
<div
|
||||
class="seed-phrase__sections"
|
||||
>
|
||||
<div
|
||||
class="seed-phrase__main"
|
||||
>
|
||||
<div
|
||||
class="box box--margin-bottom-4 box--flex-direction-row"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
>
|
||||
< Back
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="first-time-flow__header"
|
||||
>
|
||||
Secret Recovery Phrase
|
||||
</div>
|
||||
<div
|
||||
class="first-time-flow__text-block"
|
||||
>
|
||||
Your Secret Recovery Phrase makes it easy to back up and restore your account.
|
||||
</div>
|
||||
<div
|
||||
class="first-time-flow__text-block"
|
||||
>
|
||||
WARNING: Never disclose your Secret Recovery Phrase. Anyone with this phrase can take your Ether forever.
|
||||
</div>
|
||||
<div
|
||||
class="reveal-seed-phrase__secret"
|
||||
>
|
||||
<div
|
||||
class="reveal-seed-phrase__secret-words notranslate reveal-seed-phrase__secret-words--hidden"
|
||||
data-testid="hidden-seed-phrase"
|
||||
>
|
||||
debris dizzy just program just float decrease vacant alarm reduce speak stadium
|
||||
</div>
|
||||
<div
|
||||
class="reveal-seed-phrase__secret-blocker"
|
||||
data-testid="reveal-seed-blocker"
|
||||
>
|
||||
<svg
|
||||
fill="var(--color-overlay-inverse)"
|
||||
height="35px"
|
||||
id="Capa_1"
|
||||
style="enable-background: new 0 0 401.998 401.998;"
|
||||
version="1.1"
|
||||
viewBox="0 0 401.998 401.998"
|
||||
width="28px"
|
||||
x="0px"
|
||||
xml:space="preserve"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
y="0px"
|
||||
>
|
||||
<g>
|
||||
<path
|
||||
d="M357.45,190.721c-5.331-5.33-11.8-7.993-19.417-7.993h-9.131v-54.821c0-35.022-12.559-65.093-37.685-90.218 C266.093,12.563,236.025,0,200.998,0c-35.026,0-65.1,12.563-90.222,37.688C85.65,62.814,73.091,92.884,73.091,127.907v54.821 h-9.135c-7.611,0-14.084,2.663-19.414,7.993c-5.33,5.326-7.994,11.799-7.994,19.417V374.59c0,7.611,2.665,14.086,7.994,19.417 c5.33,5.325,11.803,7.991,19.414,7.991H338.04c7.617,0,14.085-2.663,19.417-7.991c5.325-5.331,7.994-11.806,7.994-19.417V210.135 C365.455,202.523,362.782,196.051,357.45,190.721z M274.087,182.728H127.909v-54.821c0-20.175,7.139-37.402,21.414-51.675 c14.277-14.275,31.501-21.411,51.678-21.411c20.179,0,37.399,7.135,51.677,21.411c14.271,14.272,21.409,31.5,21.409,51.675V182.728 z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
<div
|
||||
class="reveal-seed-phrase__reveal-button"
|
||||
>
|
||||
Click here to reveal secret words
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="seed-phrase__side"
|
||||
>
|
||||
<div
|
||||
class="first-time-flow__text-block"
|
||||
>
|
||||
Tips:
|
||||
</div>
|
||||
<div
|
||||
class="first-time-flow__text-block"
|
||||
>
|
||||
Store this phrase in a password manager like 1Password.
|
||||
</div>
|
||||
<div
|
||||
class="first-time-flow__text-block"
|
||||
>
|
||||
Write this phrase on a piece of paper and store in a secure location. If you want even more security, write it down on multiple pieces of paper and store each in 2 - 3 different locations.
|
||||
</div>
|
||||
<div
|
||||
class="first-time-flow__text-block"
|
||||
>
|
||||
Memorize this phrase.
|
||||
</div>
|
||||
<div
|
||||
class="first-time-flow__text-block"
|
||||
>
|
||||
<a
|
||||
class="reveal-seed-phrase__export-text"
|
||||
>
|
||||
Download this Secret Recovery Phrase and keep it stored safely on an external encrypted hard drive or storage medium.
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="reveal-seed-phrase__buttons"
|
||||
>
|
||||
<button
|
||||
class="button btn--rounded btn-secondary first-time-flow__button"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Remind me later
|
||||
</button>
|
||||
<button
|
||||
class="button btn--rounded btn-primary first-time-flow__button"
|
||||
disabled=""
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -112,12 +112,16 @@ export default class RevealSeedPhrase extends PureComponent {
|
||||
'reveal-seed-phrase__secret-words--hidden': !isShowingSeedPhrase,
|
||||
},
|
||||
)}
|
||||
data-testid={
|
||||
isShowingSeedPhrase ? 'showing-seed-phrase' : 'hidden-seed-phrase'
|
||||
}
|
||||
>
|
||||
{seedPhrase}
|
||||
</div>
|
||||
{!isShowingSeedPhrase && (
|
||||
<div
|
||||
className="reveal-seed-phrase__secret-blocker"
|
||||
data-testid="reveal-seed-blocker"
|
||||
onClick={() => {
|
||||
this.context.trackEvent({
|
||||
category: EVENT.CATEGORIES.ONBOARDING,
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { mount } from 'enzyme';
|
||||
import RevealSeedPhrase from './reveal-seed-phrase.container';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
|
||||
import RevealSeedPhrase from '.';
|
||||
|
||||
describe('Reveal Secret Recovery Phrase', () => {
|
||||
let wrapper;
|
||||
|
||||
const TEST_SEED =
|
||||
'debris dizzy just program just float decrease vacant alarm reduce speak stadium';
|
||||
|
||||
@ -18,31 +18,29 @@ describe('Reveal Secret Recovery Phrase', () => {
|
||||
setCompletedOnboarding: sinon.spy(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = mount(<RevealSeedPhrase.WrappedComponent {...props} />, {
|
||||
context: {
|
||||
t: (str) => str,
|
||||
trackEvent: () => undefined,
|
||||
},
|
||||
});
|
||||
});
|
||||
const mockState = {
|
||||
metamask: {},
|
||||
};
|
||||
|
||||
it('secret recovery phrase', () => {
|
||||
const seedPhrase = wrapper.find(
|
||||
'.reveal-seed-phrase__secret-words--hidden',
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
|
||||
it('should match snapshot', () => {
|
||||
const { container } = renderWithProvider(
|
||||
<RevealSeedPhrase {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
expect(seedPhrase).toHaveLength(1);
|
||||
expect(seedPhrase.text()).toStrictEqual(TEST_SEED);
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('clicks to reveal', () => {
|
||||
const reveal = wrapper.find('.reveal-seed-phrase__secret-blocker');
|
||||
it('clicks to reveal shows seed phrase', () => {
|
||||
const { queryByTestId } = renderWithProvider(
|
||||
<RevealSeedPhrase {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
expect(wrapper.state().isShowingSeedPhrase).toStrictEqual(false);
|
||||
reveal.simulate('click');
|
||||
expect(wrapper.state().isShowingSeedPhrase).toStrictEqual(true);
|
||||
fireEvent.click(queryByTestId('reveal-seed-blocker'));
|
||||
|
||||
const showSeed = wrapper.find('.reveal-seed-phrase__secret-words');
|
||||
expect(showSeed).toHaveLength(1);
|
||||
expect(queryByTestId('showing-seed-phrase')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,55 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SendFooter Component Component Update should match snapshot when component updated with errors 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="page-container__footer"
|
||||
>
|
||||
<footer>
|
||||
<button
|
||||
class="button btn--rounded btn-secondary page-container__footer-button"
|
||||
data-testid="page-container-footer-cancel"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
[cancel]
|
||||
</button>
|
||||
<button
|
||||
class="button btn--rounded btn-primary page-container__footer-button"
|
||||
data-testid="page-container-footer-next"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
[next]
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`SendFooter Component should match snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="page-container__footer"
|
||||
>
|
||||
<footer>
|
||||
<button
|
||||
class="button btn--rounded btn-secondary page-container__footer-button"
|
||||
data-testid="page-container-footer-cancel"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
class="button btn--rounded btn-primary page-container__footer-button"
|
||||
data-testid="page-container-footer-next"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -1,207 +0,0 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import sinon from 'sinon';
|
||||
import {
|
||||
CONFIRM_TRANSACTION_ROUTE,
|
||||
DEFAULT_ROUTE,
|
||||
} from '../../../helpers/constants/routes';
|
||||
import PageContainerFooter from '../../../components/ui/page-container/page-container-footer';
|
||||
import { renderWithProvider } from '../../../../test/jest';
|
||||
import SendFooter from './send-footer.component';
|
||||
|
||||
describe('SendFooter Component', () => {
|
||||
let wrapper;
|
||||
|
||||
const propsMethodSpies = {
|
||||
addToAddressBookIfNew: sinon.spy(),
|
||||
cancelTx: sinon.spy(),
|
||||
resetSendState: sinon.spy(),
|
||||
sign: sinon.spy(),
|
||||
update: sinon.spy(),
|
||||
mostRecentOverviewPage: '/',
|
||||
};
|
||||
const historySpies = {
|
||||
push: sinon.spy(),
|
||||
};
|
||||
const MOCK_EVENT = { preventDefault: () => undefined };
|
||||
|
||||
const renderShallow = (props) => {
|
||||
return shallow(
|
||||
<SendFooter
|
||||
addToAddressBookIfNew={propsMethodSpies.addToAddressBookIfNew}
|
||||
resetSendState={propsMethodSpies.resetSendState}
|
||||
cancelTx={propsMethodSpies.cancelTx}
|
||||
disabled
|
||||
draftTransactionID="ID"
|
||||
history={historySpies}
|
||||
sign={propsMethodSpies.sign}
|
||||
to="mockTo"
|
||||
toAccounts={['mockAccount']}
|
||||
sendErrors={{}}
|
||||
sendStage="DRAFT"
|
||||
gasEstimateType="BASIC"
|
||||
mostRecentOverviewPage="mostRecentOverviewPage"
|
||||
{...props}
|
||||
/>,
|
||||
{ context: { t: (str) => str, trackEvent: () => ({}) } },
|
||||
);
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
sinon.spy(SendFooter.prototype, 'onCancel');
|
||||
sinon.spy(SendFooter.prototype, 'onSubmit');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = renderShallow();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
propsMethodSpies.resetSendState.resetHistory();
|
||||
propsMethodSpies.cancelTx.resetHistory();
|
||||
propsMethodSpies.addToAddressBookIfNew.resetHistory();
|
||||
propsMethodSpies.resetSendState.resetHistory();
|
||||
propsMethodSpies.sign.resetHistory();
|
||||
propsMethodSpies.update.resetHistory();
|
||||
historySpies.push.resetHistory();
|
||||
SendFooter.prototype.onCancel.resetHistory();
|
||||
SendFooter.prototype.onSubmit.resetHistory();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
describe('onCancel', () => {
|
||||
it('should call resetSendState', () => {
|
||||
expect(propsMethodSpies.resetSendState.callCount).toStrictEqual(0);
|
||||
wrapper.instance().onCancel();
|
||||
expect(propsMethodSpies.resetSendState.callCount).toStrictEqual(1);
|
||||
});
|
||||
|
||||
it('should call cancelTx', () => {
|
||||
expect(propsMethodSpies.cancelTx.callCount).toStrictEqual(0);
|
||||
wrapper.instance().onCancel();
|
||||
expect(propsMethodSpies.cancelTx.callCount).toStrictEqual(1);
|
||||
expect(propsMethodSpies.cancelTx.getCall(0).args[0]?.id).toStrictEqual(
|
||||
'ID',
|
||||
);
|
||||
});
|
||||
|
||||
it('should call history.push', () => {
|
||||
expect(historySpies.push.callCount).toStrictEqual(0);
|
||||
wrapper.instance().onCancel();
|
||||
expect(historySpies.push.callCount).toStrictEqual(1);
|
||||
expect(historySpies.push.getCall(0).args[0]).toStrictEqual(
|
||||
'mostRecentOverviewPage',
|
||||
);
|
||||
});
|
||||
|
||||
it('should call history.push with DEFAULT_ROUTE in edit stage', () => {
|
||||
wrapper = renderShallow({ sendStage: 'EDIT' });
|
||||
expect(historySpies.push.callCount).toStrictEqual(0);
|
||||
wrapper.instance().onCancel();
|
||||
expect(historySpies.push.callCount).toStrictEqual(1);
|
||||
expect(historySpies.push.getCall(0).args[0]).toStrictEqual(DEFAULT_ROUTE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSubmit', () => {
|
||||
it('should call addToAddressBookIfNew with the correct params', () => {
|
||||
wrapper.instance().onSubmit(MOCK_EVENT);
|
||||
expect(propsMethodSpies.addToAddressBookIfNew.calledOnce).toStrictEqual(
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
propsMethodSpies.addToAddressBookIfNew.getCall(0).args,
|
||||
).toStrictEqual(['mockTo', ['mockAccount']]);
|
||||
});
|
||||
|
||||
it('should call props.sign whe submitting', async () => {
|
||||
await wrapper.instance().onSubmit(MOCK_EVENT);
|
||||
expect(propsMethodSpies.sign.calledOnce).toStrictEqual(true);
|
||||
});
|
||||
|
||||
it('should call history.push', async () => {
|
||||
await wrapper.instance().onSubmit(MOCK_EVENT);
|
||||
expect(historySpies.push.callCount).toStrictEqual(1);
|
||||
expect(historySpies.push.getCall(0).args[0]).toStrictEqual(
|
||||
CONFIRM_TRANSACTION_ROUTE,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('render', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<SendFooter
|
||||
addToAddressBookIfNew={propsMethodSpies.addToAddressBookIfNew}
|
||||
amount="mockAmount"
|
||||
resetSendState={propsMethodSpies.resetSendState}
|
||||
cancelTx={propsMethodSpies.cancelTx}
|
||||
disabled
|
||||
draftTransactionID="ID"
|
||||
editingTransactionId="mockEditingTransactionId"
|
||||
errors={{}}
|
||||
from={{ address: 'mockAddress', balance: 'mockBalance' }}
|
||||
gasLimit="mockGasLimit"
|
||||
gasPrice="mockGasPrice"
|
||||
gasTotal="mockGasTotal"
|
||||
history={historySpies}
|
||||
sendToken={{ mockProp: 'mockSendTokenProp' }}
|
||||
sign={propsMethodSpies.sign}
|
||||
to="mockTo"
|
||||
toAccounts={['mockAccount']}
|
||||
tokenBalance="mockTokenBalance"
|
||||
unapprovedTxs={{}}
|
||||
update={propsMethodSpies.update}
|
||||
mostRecentOverviewPage="mostRecentOverviewPage"
|
||||
/>,
|
||||
{ context: { t: (str) => str, trackEvent: () => ({}) } },
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a PageContainerFooter component', () => {
|
||||
expect(wrapper.find(PageContainerFooter)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should pass the correct props to PageContainerFooter', () => {
|
||||
const { onCancel, onSubmit, disabled } = wrapper
|
||||
.find(PageContainerFooter)
|
||||
.props();
|
||||
expect(disabled).toStrictEqual(true);
|
||||
|
||||
expect(SendFooter.prototype.onSubmit.callCount).toStrictEqual(0);
|
||||
onSubmit(MOCK_EVENT);
|
||||
expect(SendFooter.prototype.onSubmit.callCount).toStrictEqual(1);
|
||||
|
||||
expect(SendFooter.prototype.onCancel.callCount).toStrictEqual(0);
|
||||
onCancel();
|
||||
expect(SendFooter.prototype.onCancel.callCount).toStrictEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Cancel Button', () => {
|
||||
const renderFooter = (props) =>
|
||||
renderWithProvider(
|
||||
<SendFooter
|
||||
disabled
|
||||
mostRecentOverviewPage="mostRecentOverviewPage"
|
||||
draftTransactionID="ID"
|
||||
sendErrors={{}}
|
||||
sendStage="DRAFT"
|
||||
{...props}
|
||||
/>,
|
||||
);
|
||||
|
||||
it('has a cancel button in footer', () => {
|
||||
const { getByText } = renderFooter();
|
||||
expect(getByText('Cancel')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('has label changed to Reject in editing stage', () => {
|
||||
const { getByText } = renderFooter({ sendStage: 'EDIT' });
|
||||
expect(getByText('Reject')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
@ -1,87 +0,0 @@
|
||||
import sinon from 'sinon';
|
||||
|
||||
import { addToAddressBook, cancelTx } from '../../../store/actions';
|
||||
import { resetSendState, signTransaction } from '../../../ducks/send';
|
||||
|
||||
let mapDispatchToProps;
|
||||
|
||||
jest.mock('react-redux', () => ({
|
||||
connect: (_, md) => {
|
||||
mapDispatchToProps = md;
|
||||
return () => ({});
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../../store/actions', () => ({
|
||||
addToAddressBook: jest.fn(),
|
||||
cancelTx: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../../ducks/metamask/metamask', () => ({
|
||||
getSendToAccounts: (s) => [`mockToAccounts:${s}`],
|
||||
}));
|
||||
|
||||
jest.mock('../../../ducks/send', () => ({
|
||||
getGasPrice: (s) => `mockGasPrice:${s}`,
|
||||
getSendTo: (s) => `mockTo:${s}`,
|
||||
getSendErrors: (s) => `mockSendErrors:${s}`,
|
||||
getSendStage: (s) => `mockStage:${s}`,
|
||||
getDraftTransaction: (s) => ({ id: `draftTransaction:${s}` }),
|
||||
resetSendState: jest.fn(),
|
||||
signTransaction: jest.fn(),
|
||||
}));
|
||||
|
||||
require('./send-footer.container');
|
||||
|
||||
describe('send-footer container', () => {
|
||||
describe('mapDispatchToProps()', () => {
|
||||
let dispatchSpy;
|
||||
let mapDispatchToPropsObject;
|
||||
|
||||
beforeEach(() => {
|
||||
dispatchSpy = sinon.spy();
|
||||
mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy);
|
||||
});
|
||||
|
||||
describe('resetSendState()', () => {
|
||||
it('should dispatch an action', () => {
|
||||
mapDispatchToPropsObject.resetSendState();
|
||||
expect(dispatchSpy.calledOnce).toStrictEqual(true);
|
||||
expect(resetSendState).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('cancelTx()', () => {
|
||||
it('should dispatch an action', () => {
|
||||
const draftTansaction = { id: 'ID' };
|
||||
mapDispatchToPropsObject.cancelTx(draftTansaction);
|
||||
expect(dispatchSpy.calledOnce).toStrictEqual(true);
|
||||
expect(cancelTx).toHaveBeenCalledTimes(1);
|
||||
expect(cancelTx).toHaveBeenCalledWith(draftTansaction);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sign()', () => {
|
||||
it('should dispatch a signTransaction action', () => {
|
||||
mapDispatchToPropsObject.sign();
|
||||
expect(dispatchSpy.calledOnce).toStrictEqual(true);
|
||||
expect(signTransaction).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('addToAddressBookIfNew()', () => {
|
||||
it('should dispatch an action', () => {
|
||||
mapDispatchToPropsObject.addToAddressBookIfNew(
|
||||
'mockNewAddress',
|
||||
[{ address: 'mockToAccounts' }],
|
||||
'mockNickname',
|
||||
);
|
||||
expect(dispatchSpy.calledOnce).toStrictEqual(true);
|
||||
expect(addToAddressBook).toHaveBeenCalledWith(
|
||||
'0xmockNewAddress',
|
||||
'mockNickname',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
136
ui/pages/send/send-footer/send-footer.test.js
Normal file
136
ui/pages/send/send-footer/send-footer.test.js
Normal file
@ -0,0 +1,136 @@
|
||||
import React from 'react';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import { fireEvent, waitFor } from '@testing-library/react';
|
||||
import thunk from 'redux-thunk';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import {
|
||||
CONFIRM_TRANSACTION_ROUTE,
|
||||
DEFAULT_ROUTE,
|
||||
} from '../../../helpers/constants/routes';
|
||||
import { SEND_STAGES } from '../../../ducks/send';
|
||||
import SendFooter from '.';
|
||||
|
||||
const mockResetSendState = jest.fn();
|
||||
const mockSendTransaction = jest.fn();
|
||||
const mockAddtoAddressBook = jest.fn();
|
||||
const mockCancelTx = jest.fn();
|
||||
|
||||
jest.mock('../../../ducks/send/index.js', () => ({
|
||||
...jest.requireActual('../../../ducks/send/index.js'),
|
||||
signTransaction: () => mockSendTransaction,
|
||||
resetSendState: () => mockResetSendState,
|
||||
}));
|
||||
|
||||
jest.mock('../../../store/actions.js', () => ({
|
||||
addToAddressBook: () => mockAddtoAddressBook,
|
||||
cancelTx: () => mockCancelTx,
|
||||
}));
|
||||
|
||||
describe('SendFooter Component', () => {
|
||||
const props = {
|
||||
history: {
|
||||
push: jest.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
props.history.push.mockReset();
|
||||
});
|
||||
|
||||
const mockStore = configureMockStore([thunk])(mockState);
|
||||
|
||||
it('should match snapshot', () => {
|
||||
const { container } = renderWithProvider(
|
||||
<SendFooter {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('onCancel', () => {
|
||||
it('should call reset send state and route to recent page without cancelling tx', () => {
|
||||
const { queryByText } = renderWithProvider(
|
||||
<SendFooter {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const cancelText = queryByText('Cancel');
|
||||
fireEvent.click(cancelText);
|
||||
|
||||
expect(mockResetSendState).toHaveBeenCalled();
|
||||
expect(mockCancelTx).not.toHaveBeenCalled();
|
||||
expect(props.history.push).toHaveBeenCalledWith(
|
||||
'/mostRecentOverviewPage',
|
||||
);
|
||||
});
|
||||
|
||||
it('should reject/cancel tx when coming from tx editing and route to index', () => {
|
||||
const sendDataState = {
|
||||
...mockState,
|
||||
send: {
|
||||
currentTransactionUUID: '01',
|
||||
draftTransactions: {
|
||||
'01': {
|
||||
id: '99',
|
||||
},
|
||||
},
|
||||
stage: SEND_STAGES.EDIT,
|
||||
},
|
||||
};
|
||||
|
||||
const sendStateStore = configureMockStore([thunk])(sendDataState);
|
||||
|
||||
const { queryByText } = renderWithProvider(
|
||||
<SendFooter {...props} />,
|
||||
sendStateStore,
|
||||
);
|
||||
|
||||
const rejectText = queryByText('Reject');
|
||||
fireEvent.click(rejectText);
|
||||
|
||||
expect(mockResetSendState).toHaveBeenCalled();
|
||||
expect(mockCancelTx).toHaveBeenCalled();
|
||||
expect(props.history.push).toHaveBeenCalledWith(DEFAULT_ROUTE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSubmit', () => {
|
||||
it('should', async () => {
|
||||
const { queryByText } = renderWithProvider(
|
||||
<SendFooter {...props} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
const nextText = queryByText('Next');
|
||||
fireEvent.click(nextText);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockAddtoAddressBook).toHaveBeenCalled();
|
||||
expect(mockSendTransaction).toHaveBeenCalled();
|
||||
expect(props.history.push).toHaveBeenCalledWith(
|
||||
CONFIRM_TRANSACTION_ROUTE,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Component Update', () => {
|
||||
it('should match snapshot when component updated with errors', () => {
|
||||
const { container, rerender } = renderWithProvider(
|
||||
<SendFooter.WrappedComponent />,
|
||||
);
|
||||
|
||||
const sendErrorProps = {
|
||||
sendErrors: {
|
||||
gasFee: 'gas fee error',
|
||||
amount: 'amount error',
|
||||
},
|
||||
};
|
||||
|
||||
rerender(<SendFooter.WrappedComponent {...sendErrorProps} />);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,246 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Security Tab should match snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="settings-page__body"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-row"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
<span>
|
||||
Reveal Secret Recovery Phrase
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item-col"
|
||||
>
|
||||
<button
|
||||
class="button btn--rounded btn-danger btn--large"
|
||||
data-testid="reveal-seed-words"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Reveal Secret Recovery Phrase
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-row"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
<span>
|
||||
Show incoming transactions
|
||||
</span>
|
||||
<div
|
||||
class="settings-page__content-description"
|
||||
>
|
||||
Select this to use Etherscan to show incoming transactions in the transactions list
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item-col"
|
||||
>
|
||||
<label
|
||||
class="toggle-button toggle-button--on"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
>
|
||||
<div
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 0;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(3, 125, 214); left: 18px;"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="true"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-row"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
<span>
|
||||
Use phishing detection
|
||||
</span>
|
||||
<div
|
||||
class="settings-page__content-description"
|
||||
>
|
||||
Display a warning for phishing domains targeting Ethereum users
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item-col"
|
||||
>
|
||||
<label
|
||||
class="toggle-button toggle-button--on"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
>
|
||||
<div
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 0;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(3, 125, 214); left: 18px;"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="true"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-row"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
<span>
|
||||
Participate in MetaMetrics
|
||||
</span>
|
||||
<div
|
||||
class="settings-page__content-description"
|
||||
>
|
||||
<span>
|
||||
Participate in MetaMetrics to help us make MetaMask better
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item-col"
|
||||
>
|
||||
<label
|
||||
class="toggle-button toggle-button--off"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
>
|
||||
<div
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 1;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(106, 115, 125); left: 3px;"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="false"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -59,6 +59,7 @@ export default class SecurityTab extends PureComponent {
|
||||
<div className="settings-page__content-item">
|
||||
<div className="settings-page__content-item-col">
|
||||
<Button
|
||||
data-testid="reveal-seed-words"
|
||||
type="danger"
|
||||
large
|
||||
onClick={(event) => {
|
||||
|
@ -1,63 +0,0 @@
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { mount } from 'enzyme';
|
||||
import SecurityTab from './security-tab.container';
|
||||
|
||||
describe('Security Tab', () => {
|
||||
let wrapper;
|
||||
|
||||
const props = {
|
||||
revealSeedConfirmation: sinon.spy(),
|
||||
showClearApprovalModal: sinon.spy(),
|
||||
setParticipateInMetaMetrics: sinon.spy(),
|
||||
displayWarning: sinon.spy(),
|
||||
showIncomingTransactions: false,
|
||||
setShowIncomingTransactionsFeatureFlag: sinon.spy(),
|
||||
history: {
|
||||
push: sinon.spy(),
|
||||
},
|
||||
privacyMode: true,
|
||||
warning: '',
|
||||
participateInMetaMetrics: false,
|
||||
setUsePhishDetect: sinon.spy(),
|
||||
usePhishDetect: true,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = mount(<SecurityTab.WrappedComponent {...props} />, {
|
||||
context: {
|
||||
t: (str) => str,
|
||||
trackEvent: () => undefined,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('navigates to reveal seed words page', () => {
|
||||
const seedWords = wrapper.find('.button.btn-danger.btn--large');
|
||||
|
||||
seedWords.simulate('click');
|
||||
expect(props.history.push.calledOnce).toStrictEqual(true);
|
||||
expect(props.history.push.getCall(0).args[0]).toStrictEqual('/seed');
|
||||
});
|
||||
|
||||
it('toggles incoming txs', () => {
|
||||
const incomingTxs = wrapper.find({ type: 'checkbox' }).at(0);
|
||||
incomingTxs.simulate('click');
|
||||
expect(
|
||||
props.setShowIncomingTransactionsFeatureFlag.calledOnce,
|
||||
).toStrictEqual(true);
|
||||
});
|
||||
|
||||
it('toggles phishing detection', () => {
|
||||
const phishDetect = wrapper.find({ type: 'checkbox' }).at(1);
|
||||
phishDetect.simulate('click');
|
||||
expect(props.setUsePhishDetect.calledOnce).toStrictEqual(true);
|
||||
});
|
||||
|
||||
it('toggles metaMetrics', () => {
|
||||
const metaMetrics = wrapper.find({ type: 'checkbox' }).at(2);
|
||||
|
||||
metaMetrics.simulate('click');
|
||||
expect(props.setParticipateInMetaMetrics.calledOnce).toStrictEqual(true);
|
||||
});
|
||||
});
|
86
ui/pages/settings/security-tab/security-tab.test.js
Normal file
86
ui/pages/settings/security-tab/security-tab.test.js
Normal file
@ -0,0 +1,86 @@
|
||||
import React from 'react';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import SecurityTab from './security-tab.container';
|
||||
|
||||
const mockSetFeatureFlag = jest.fn();
|
||||
const mockSetParticipateInMetaMetrics = jest.fn();
|
||||
const mockSetUsePhishDetect = jest.fn();
|
||||
|
||||
jest.mock('../../../store/actions.js', () => {
|
||||
return {
|
||||
setFeatureFlag: () => mockSetFeatureFlag,
|
||||
setParticipateInMetaMetrics: () => mockSetParticipateInMetaMetrics,
|
||||
setUsePhishDetect: () => mockSetUsePhishDetect,
|
||||
};
|
||||
});
|
||||
|
||||
describe('Security Tab', () => {
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
|
||||
it('should match snapshot', () => {
|
||||
const { container } = renderWithProvider(<SecurityTab />, mockStore);
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('navigates to reveal seed words page', () => {
|
||||
const { queryByTestId, history } = renderWithProvider(
|
||||
<SecurityTab />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
expect(history.location.pathname).toStrictEqual('/');
|
||||
|
||||
fireEvent.click(queryByTestId('reveal-seed-words'));
|
||||
|
||||
expect(history.location.pathname).toStrictEqual('/seed');
|
||||
});
|
||||
|
||||
it('toggles incoming txs', () => {
|
||||
const { queryAllByRole } = renderWithProvider(<SecurityTab />, mockStore);
|
||||
|
||||
const checkboxes = queryAllByRole('checkbox');
|
||||
const showIncomingCheckbox = checkboxes[0];
|
||||
|
||||
expect(showIncomingCheckbox).toHaveAttribute('value', 'true');
|
||||
|
||||
fireEvent.change(showIncomingCheckbox, {
|
||||
target: { value: false },
|
||||
});
|
||||
|
||||
expect(showIncomingCheckbox).toHaveAttribute('value', 'false');
|
||||
});
|
||||
|
||||
it('toggles phishing detection', () => {
|
||||
const { queryAllByRole } = renderWithProvider(<SecurityTab />, mockStore);
|
||||
|
||||
const checkboxes = queryAllByRole('checkbox');
|
||||
const showIncomingCheckbox = checkboxes[1];
|
||||
|
||||
expect(showIncomingCheckbox).toHaveAttribute('value', 'true');
|
||||
|
||||
fireEvent.change(showIncomingCheckbox, {
|
||||
target: { value: false },
|
||||
});
|
||||
|
||||
expect(showIncomingCheckbox).toHaveAttribute('value', 'false');
|
||||
});
|
||||
|
||||
it('toggles metaMetrics', () => {
|
||||
const { queryAllByRole } = renderWithProvider(<SecurityTab />, mockStore);
|
||||
|
||||
const checkboxes = queryAllByRole('checkbox');
|
||||
const showIncomingCheckbox = checkboxes[2];
|
||||
|
||||
expect(showIncomingCheckbox).toHaveAttribute('value', 'false');
|
||||
|
||||
fireEvent.change(showIncomingCheckbox, {
|
||||
target: { value: true },
|
||||
});
|
||||
|
||||
expect(showIncomingCheckbox).toHaveAttribute('value', 'true');
|
||||
});
|
||||
});
|
@ -1,61 +0,0 @@
|
||||
import React from 'react';
|
||||
import { mount, shallow } from 'enzyme';
|
||||
import { Provider } from 'react-redux';
|
||||
import TextField from '../../components/ui/text-field';
|
||||
import configureStore from '../../store/store';
|
||||
import Settings from './settings.container';
|
||||
import SettingsSearch from './settings-search';
|
||||
|
||||
describe('SettingsPage', () => {
|
||||
let wrapper;
|
||||
|
||||
const props = {
|
||||
addNewNetwork: false,
|
||||
addressName: '',
|
||||
backRoute: '/',
|
||||
conversionDate: Date.now(),
|
||||
currentPath: '/settings',
|
||||
initialBreadCrumbKey: undefined,
|
||||
initialBreadCrumbRoute: undefined,
|
||||
isAddressEntryPage: false,
|
||||
isPopup: false,
|
||||
location: '/settings',
|
||||
mostRecentOverviewPage: '',
|
||||
pathnameI18nKey: undefined,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(<Settings.WrappedComponent {...props} />, {
|
||||
context: {
|
||||
t: (str) => str,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should render title correctly', () => {
|
||||
expect(
|
||||
wrapper.find('.settings-page__header__title-container__title').text(),
|
||||
).toStrictEqual('settings');
|
||||
});
|
||||
|
||||
it('should render search correctly', () => {
|
||||
const store = configureStore({
|
||||
metamask: {
|
||||
snaps: {},
|
||||
},
|
||||
});
|
||||
wrapper = mount(
|
||||
<Provider store={store}>
|
||||
<SettingsSearch onSearch={() => undefined} settingsRoutesList={[]} />
|
||||
</Provider>,
|
||||
{
|
||||
context: {
|
||||
t: (s) => `${s}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(wrapper.find(TextField).props().id).toStrictEqual('search-settings');
|
||||
expect(wrapper.find(TextField).props().value).toStrictEqual('');
|
||||
});
|
||||
});
|
45
ui/pages/settings/settings.test.js
Normal file
45
ui/pages/settings/settings.test.js
Normal file
@ -0,0 +1,45 @@
|
||||
import React from 'react';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import { renderWithProvider } from '../../../test/lib/render-helpers';
|
||||
import mockState from '../../../test/data/mock-state.json';
|
||||
import Settings from '.';
|
||||
import 'jest-canvas-mock';
|
||||
|
||||
describe('SettingsPage', () => {
|
||||
const props = {
|
||||
addNewNetwork: false,
|
||||
addressName: '',
|
||||
backRoute: '/',
|
||||
breadCrumbTextKey: '',
|
||||
conversionDate: Date.now(),
|
||||
initialBreadCrumbKey: '',
|
||||
initialBreadCrumbRoute: '',
|
||||
isAddressEntryPage: false,
|
||||
isPopup: false,
|
||||
isSnapViewPage: false,
|
||||
mostRecentOverviewPage: '/',
|
||||
pathnameI18nKey: '',
|
||||
};
|
||||
|
||||
const mockStore = configureMockStore()(mockState);
|
||||
|
||||
it('should render correctly', () => {
|
||||
const { queryByText } = renderWithProvider(
|
||||
<Settings {...props} />,
|
||||
mockStore,
|
||||
'/settings',
|
||||
);
|
||||
|
||||
expect(queryByText('Settings')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render search correctly', () => {
|
||||
const { queryByPlaceholderText } = renderWithProvider(
|
||||
<Settings {...props} />,
|
||||
mockStore,
|
||||
'/settings',
|
||||
);
|
||||
|
||||
expect(queryByPlaceholderText('Search in Settings')).toBeInTheDocument();
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user