mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Convert unit test render from enzyme to @testing-library/react. (#15091)
* Use @testing-library/react for account-menu test * Add testids for account menu accounts and balances * Expand render wrapper functionality with metrics provider and router history * Add testid to menu-droppo-container and menu-droppo * Add network item nickname testid * Use @testing-library/react for network dropdown test * Add color icon testid * No need for interpolation for testid in menu-droppo
This commit is contained in:
parent
3b7074bcd8
commit
1f5964e450
@ -2,9 +2,11 @@ import React, { useMemo } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { render } from '@testing-library/react';
|
||||
import { mount, shallow } from 'enzyme';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { Router, MemoryRouter } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { I18nContext, LegacyI18nProvider } from '../../ui/contexts/i18n';
|
||||
import { LegacyMetaMetricsProvider } from '../../ui/contexts/metametrics';
|
||||
import { getMessage } from '../../ui/helpers/utils/i18n-helper';
|
||||
import * as en from '../../app/_locales/en/messages.json';
|
||||
|
||||
@ -77,25 +79,32 @@ I18nProvider.defaultProps = {
|
||||
children: undefined,
|
||||
};
|
||||
|
||||
export function renderWithProvider(component, store) {
|
||||
export function renderWithProvider(component, store, pathname = '/') {
|
||||
const history = createMemoryHistory({ initialEntries: [pathname] });
|
||||
const Wrapper = ({ children }) =>
|
||||
store ? (
|
||||
<Provider store={store}>
|
||||
<MemoryRouter initialEntries={['/']} initialIndex={0}>
|
||||
<Router history={history}>
|
||||
<I18nProvider currentLocale="en" current={en} en={en}>
|
||||
<LegacyI18nProvider>{children}</LegacyI18nProvider>
|
||||
<LegacyI18nProvider>
|
||||
<LegacyMetaMetricsProvider>{children}</LegacyMetaMetricsProvider>
|
||||
</LegacyI18nProvider>
|
||||
</I18nProvider>
|
||||
</MemoryRouter>
|
||||
</Router>
|
||||
</Provider>
|
||||
) : (
|
||||
<LegacyI18nProvider>{children}</LegacyI18nProvider>
|
||||
<LegacyI18nProvider>
|
||||
<LegacyMetaMetricsProvider>{children}</LegacyMetaMetricsProvider>
|
||||
</LegacyI18nProvider>
|
||||
);
|
||||
|
||||
Wrapper.propTypes = {
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
return render(component, { wrapper: Wrapper });
|
||||
return {
|
||||
...render(component, { wrapper: Wrapper }),
|
||||
history,
|
||||
};
|
||||
}
|
||||
|
||||
export function renderWithLocalization(component) {
|
||||
|
@ -219,6 +219,7 @@ export default class AccountMenu extends Component {
|
||||
showAccountDetail(identity.address);
|
||||
}}
|
||||
key={identity.address}
|
||||
data-testid="account-menu__account"
|
||||
>
|
||||
<div className="account-menu__check-mark">
|
||||
{isSelected ? (
|
||||
@ -230,6 +231,7 @@ export default class AccountMenu extends Component {
|
||||
<div className="account-menu__name">{identity.name || ''}</div>
|
||||
<UserPreferencedCurrencyDisplay
|
||||
className="account-menu__balance"
|
||||
data-testid="account-menu__balance"
|
||||
value={identity.balance}
|
||||
type={PRIMARY}
|
||||
/>
|
||||
|
@ -1,14 +1,11 @@
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import { Provider } from 'react-redux';
|
||||
import { mountWithRouter } from '../../../../test/lib/render-helpers';
|
||||
import Button from '../../ui/button';
|
||||
import { fireEvent, screen } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import AccountMenu from '.';
|
||||
|
||||
describe('Account Menu', () => {
|
||||
let wrapper;
|
||||
|
||||
const mockStore = {
|
||||
metamask: {
|
||||
provider: {
|
||||
@ -57,13 +54,8 @@ describe('Account Menu', () => {
|
||||
},
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
wrapper = mountWithRouter(
|
||||
<Provider store={store}>
|
||||
<AccountMenu.WrappedComponent {...props} />
|
||||
</Provider>,
|
||||
store,
|
||||
);
|
||||
beforeEach(() => {
|
||||
renderWithProvider(<AccountMenu.WrappedComponent {...props} />, store);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -73,58 +65,53 @@ describe('Account Menu', () => {
|
||||
|
||||
describe('Render Content', () => {
|
||||
it('returns account name from identities', () => {
|
||||
const accountName = wrapper.find('.account-menu__name');
|
||||
const accountName = screen.queryAllByTestId('account-menu__account');
|
||||
expect(accountName).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('renders user preference currency display balance from account balance', () => {
|
||||
const accountBalance = wrapper.find(
|
||||
'.currency-display-component.account-menu__balance',
|
||||
);
|
||||
const accountBalance = screen.queryAllByTestId('account-menu__balance');
|
||||
|
||||
expect(accountBalance).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('simulate click', () => {
|
||||
const click = wrapper.find(
|
||||
'.account-menu__account.account-menu__item--clickable',
|
||||
);
|
||||
click.first().simulate('click');
|
||||
const click = screen.getAllByTestId('account-menu__account');
|
||||
fireEvent.click(click[0]);
|
||||
|
||||
expect(props.showAccountDetail.calledOnce).toStrictEqual(true);
|
||||
expect(props.showAccountDetail.getCall(0).args[0]).toStrictEqual('0x00');
|
||||
});
|
||||
|
||||
it('render imported account label', () => {
|
||||
const importedAccount = wrapper.find('.keyring-label.allcaps');
|
||||
expect(importedAccount.text()).toStrictEqual('[imported]');
|
||||
const importedAccount = screen.getByText('Imported');
|
||||
expect(importedAccount).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Log Out', () => {
|
||||
let logout;
|
||||
|
||||
it('logout', () => {
|
||||
logout = wrapper.find(Button);
|
||||
expect(logout).toHaveLength(1);
|
||||
const logout = screen.getByText('Lock');
|
||||
expect(logout).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('simulate click', () => {
|
||||
logout.simulate('click');
|
||||
const logout = screen.getByText('Lock');
|
||||
fireEvent.click(logout);
|
||||
expect(props.lockMetamask.calledOnce).toStrictEqual(true);
|
||||
expect(props.history.push.getCall(0).args[0]).toStrictEqual('/');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Create Account', () => {
|
||||
let createAccount;
|
||||
|
||||
it('renders create account item', () => {
|
||||
createAccount = wrapper.find({ text: 'createAccount' });
|
||||
expect(createAccount).toHaveLength(1);
|
||||
const createAccount = screen.getByText('Create Account');
|
||||
expect(createAccount).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls toggle menu and push new-account route to history', () => {
|
||||
createAccount.simulate('click');
|
||||
const createAccount = screen.getByText('Create Account');
|
||||
fireEvent.click(createAccount);
|
||||
expect(props.toggleAccountMenu.calledOnce).toStrictEqual(true);
|
||||
expect(props.history.push.getCall(0).args[0]).toStrictEqual(
|
||||
'/new-account',
|
||||
@ -133,15 +120,14 @@ describe('Account Menu', () => {
|
||||
});
|
||||
|
||||
describe('Import Account', () => {
|
||||
let importAccount;
|
||||
|
||||
it('renders import account item', () => {
|
||||
importAccount = wrapper.find({ text: 'importAccount' });
|
||||
expect(importAccount).toHaveLength(1);
|
||||
const importAccount = screen.getByText('Import Account');
|
||||
expect(importAccount).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls toggle menu and push /new-account/import route to history', () => {
|
||||
importAccount.simulate('click');
|
||||
const importAccount = screen.getByText('Import Account');
|
||||
fireEvent.click(importAccount);
|
||||
expect(props.toggleAccountMenu.calledOnce).toStrictEqual(true);
|
||||
expect(props.history.push.getCall(0).args[0]).toStrictEqual(
|
||||
'/new-account/import',
|
||||
@ -150,15 +136,14 @@ describe('Account Menu', () => {
|
||||
});
|
||||
|
||||
describe('Connect Hardware Wallet', () => {
|
||||
let connectHardwareWallet;
|
||||
|
||||
it('renders import account item', () => {
|
||||
connectHardwareWallet = wrapper.find({ text: 'connectHardwareWallet' });
|
||||
expect(connectHardwareWallet).toHaveLength(1);
|
||||
const connectHardwareWallet = screen.getByText('Connect Hardware Wallet');
|
||||
expect(connectHardwareWallet).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls toggle menu and push /new-account/connect route to history', () => {
|
||||
connectHardwareWallet.simulate('click');
|
||||
const connectHardwareWallet = screen.getByText('Connect Hardware Wallet');
|
||||
fireEvent.click(connectHardwareWallet);
|
||||
expect(props.toggleAccountMenu.calledOnce).toStrictEqual(true);
|
||||
expect(props.history.push.getCall(0).args[0]).toStrictEqual(
|
||||
'/new-account/connect',
|
||||
@ -167,31 +152,29 @@ describe('Account Menu', () => {
|
||||
});
|
||||
|
||||
describe('Support', () => {
|
||||
let support;
|
||||
global.platform = { openTab: sinon.spy() };
|
||||
|
||||
it('renders import account item', () => {
|
||||
support = wrapper.find({ text: 'needHelpSubmitTicket' });
|
||||
expect(support).toHaveLength(1);
|
||||
const support = screen.getByText('Submit a Ticket');
|
||||
expect(support).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('opens support link when clicked', () => {
|
||||
support = wrapper.find({ text: 'needHelpSubmitTicket' });
|
||||
support.simulate('click');
|
||||
const support = screen.getByText('Submit a Ticket');
|
||||
fireEvent.click(support);
|
||||
expect(global.platform.openTab.calledOnce).toStrictEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Settings', () => {
|
||||
let settings;
|
||||
|
||||
it('renders import account item', () => {
|
||||
settings = wrapper.find({ text: 'settings' });
|
||||
expect(settings).toHaveLength(1);
|
||||
const settings = screen.getByText('Settings');
|
||||
expect(settings).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls toggle menu and push /new-account/connect route to history', () => {
|
||||
settings.simulate('click');
|
||||
const settings = screen.getByText('Settings');
|
||||
fireEvent.click(settings);
|
||||
expect(props.toggleAccountMenu.calledOnce).toStrictEqual(true);
|
||||
expect(props.history.push.getCall(0).args[0]).toStrictEqual('/settings');
|
||||
});
|
||||
|
@ -185,6 +185,7 @@ class NetworkDropdown extends Component {
|
||||
/>
|
||||
<span
|
||||
className="network-name-item"
|
||||
data-testid={`${nickname}-network-item`}
|
||||
style={{
|
||||
color: isCurrentRpcTarget
|
||||
? 'var(--color-text-default)'
|
||||
@ -258,6 +259,7 @@ class NetworkDropdown extends Component {
|
||||
/>
|
||||
<span
|
||||
className="network-name-item"
|
||||
data-testid={`${network}-network-item`}
|
||||
style={{
|
||||
color:
|
||||
providerType === network
|
||||
|
@ -1,15 +1,12 @@
|
||||
import React from 'react';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import thunk from 'redux-thunk';
|
||||
import Button from '../../ui/button';
|
||||
import { mountWithRouter } from '../../../../test/lib/render-helpers';
|
||||
import ColorIndicator from '../../ui/color-indicator';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import { LOCALHOST_RPC_URL } from '../../../../shared/constants/network';
|
||||
import NetworkDropdown from './network-dropdown';
|
||||
import { DropdownMenuItem } from './dropdown';
|
||||
|
||||
describe('Network Dropdown', () => {
|
||||
let wrapper;
|
||||
const createMockStore = configureMockStore([thunk]);
|
||||
|
||||
describe('NetworkDropdown in appState in false', () => {
|
||||
@ -32,15 +29,17 @@ describe('Network Dropdown', () => {
|
||||
const store = createMockStore(mockState);
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = mountWithRouter(<NetworkDropdown store={store} />);
|
||||
renderWithProvider(<NetworkDropdown />, store);
|
||||
});
|
||||
|
||||
it('should not render menu dropdown when network dropdown is in false state', () => {
|
||||
const menuDropdown = screen.queryByTestId('menu-dropdown');
|
||||
expect(menuDropdown).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('checks for network droppo class', () => {
|
||||
expect(wrapper.find('.network-droppo')).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('renders only one child when networkDropdown is false in state', () => {
|
||||
expect(wrapper.children()).toHaveLength(1);
|
||||
const networkDropdown = screen.queryByTestId('network-droppo');
|
||||
expect(networkDropdown).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@ -72,82 +71,52 @@ describe('Network Dropdown', () => {
|
||||
|
||||
const store = createMockStore(mockState);
|
||||
|
||||
let testNetworkIndex = 1;
|
||||
|
||||
const findTestNetworkFirstIndex = (_wrapper) => {
|
||||
let i = 1;
|
||||
let found = false;
|
||||
while (!found) {
|
||||
if (
|
||||
_wrapper.find(ColorIndicator).at(i).prop('color') === 'icon-muted'
|
||||
) {
|
||||
i += 1;
|
||||
} else {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
testNetworkIndex = i;
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
wrapper = mountWithRouter(<NetworkDropdown store={store} />);
|
||||
findTestNetworkFirstIndex(wrapper);
|
||||
beforeEach(() => {
|
||||
renderWithProvider(<NetworkDropdown />, store);
|
||||
});
|
||||
|
||||
it('checks background color for first ColorIndicator', () => {
|
||||
const colorIndicator = wrapper.find(ColorIndicator).at(0);
|
||||
expect(colorIndicator.prop('color')).toStrictEqual('mainnet');
|
||||
const mainnetColorIndicator = screen.queryByTestId('color-icon-mainnet');
|
||||
expect(mainnetColorIndicator).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('checks background color for second ColorIndicator', () => {
|
||||
// find where test networks start in case there are custom RPCs
|
||||
const colorIndicator = wrapper.find(ColorIndicator).at(testNetworkIndex);
|
||||
expect(colorIndicator.prop('color')).toStrictEqual('ropsten');
|
||||
const ropstenColorIndicator = screen.queryByTestId('color-icon-ropsten');
|
||||
expect(ropstenColorIndicator).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('checks background color for third ColorIndicator', () => {
|
||||
const colorIndicator = wrapper
|
||||
.find(ColorIndicator)
|
||||
.at(testNetworkIndex + 1);
|
||||
expect(colorIndicator.prop('color')).toStrictEqual('kovan');
|
||||
const kovanColorIndicator = screen.queryByTestId('color-icon-kovan');
|
||||
expect(kovanColorIndicator).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('checks background color for fourth ColorIndicator', () => {
|
||||
const colorIndicator = wrapper
|
||||
.find(ColorIndicator)
|
||||
.at(testNetworkIndex + 2);
|
||||
expect(colorIndicator.prop('color')).toStrictEqual('rinkeby');
|
||||
const rinkebyColorIndicator = screen.queryByTestId('color-icon-rinkeby');
|
||||
expect(rinkebyColorIndicator).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('checks background color for fifth ColorIndicator', () => {
|
||||
const colorIndicator = wrapper
|
||||
.find(ColorIndicator)
|
||||
.at(testNetworkIndex + 3);
|
||||
expect(colorIndicator.prop('color')).toStrictEqual('goerli');
|
||||
const goerliColorIndicator = screen.queryByTestId('color-icon-goerli');
|
||||
expect(goerliColorIndicator).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('checks background color for sixth ColorIndicator', () => {
|
||||
const colorIndicator = wrapper
|
||||
.find(ColorIndicator)
|
||||
.at(testNetworkIndex + 4);
|
||||
expect(colorIndicator.prop('color')).toStrictEqual('localhost');
|
||||
expect(
|
||||
wrapper
|
||||
.find(DropdownMenuItem)
|
||||
.at(testNetworkIndex + 4)
|
||||
.text(),
|
||||
).toStrictEqual('✓localhost');
|
||||
const localhostColorIndicator = screen.queryByTestId(
|
||||
'color-icon-localhost',
|
||||
);
|
||||
expect(localhostColorIndicator).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('checks that Add Network button is rendered', () => {
|
||||
expect(wrapper.find(Button).at(0).children().text()).toStrictEqual(
|
||||
'addNetwork',
|
||||
);
|
||||
const addNetworkButton = screen.queryByText('Add Network');
|
||||
expect(addNetworkButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows test networks in the dropdown', () => {
|
||||
expect(wrapper.find('.network-dropdown-list li')).toHaveLength(8);
|
||||
const networkItems = screen.queryAllByTestId(/network-item/u);
|
||||
|
||||
expect(networkItems).toHaveLength(8);
|
||||
});
|
||||
});
|
||||
|
||||
@ -178,26 +147,24 @@ describe('Network Dropdown', () => {
|
||||
|
||||
const store = createMockStore(mockState);
|
||||
|
||||
beforeAll(() => {
|
||||
wrapper = mountWithRouter(<NetworkDropdown store={store} />);
|
||||
beforeEach(() => {
|
||||
renderWithProvider(<NetworkDropdown />, store);
|
||||
});
|
||||
|
||||
it('checks background color for first ColorIndicator', () => {
|
||||
const colorIndicator = wrapper.find(ColorIndicator).at(0);
|
||||
expect(colorIndicator.prop('color')).toStrictEqual('mainnet');
|
||||
expect(wrapper.find(DropdownMenuItem).at(0).text()).toStrictEqual(
|
||||
'✓mainnet',
|
||||
);
|
||||
const mainnetColorIndicator = screen.queryByTestId('color-icon-mainnet');
|
||||
expect(mainnetColorIndicator).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('checks that Add Network button is rendered', () => {
|
||||
expect(wrapper.find(Button).at(0).children().text()).toStrictEqual(
|
||||
'addNetwork',
|
||||
);
|
||||
const addNetworkButton = screen.queryByText('Add Network');
|
||||
expect(addNetworkButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not show test networks in the dropdown', () => {
|
||||
expect(wrapper.find('.network-dropdown-list li')).toHaveLength(3);
|
||||
const networkItems = screen.queryAllByTestId(/network-item/u);
|
||||
|
||||
expect(networkItems).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -25,7 +25,12 @@ export default class MenuDroppoComponent extends Component {
|
||||
const innerStyle = this.props.innerStyle || {};
|
||||
|
||||
return (
|
||||
<div className="menu-droppo" key="menu-droppo-drawer" style={innerStyle}>
|
||||
<div
|
||||
className="menu-droppo"
|
||||
key="menu-droppo-drawer"
|
||||
data-testid="menu-droppo"
|
||||
style={innerStyle}
|
||||
>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
@ -76,6 +81,7 @@ export default class MenuDroppoComponent extends Component {
|
||||
<div
|
||||
style={baseStyle}
|
||||
className={`menu-droppo-container ${containerClassName}`}
|
||||
data-testid={containerClassName}
|
||||
>
|
||||
<style>
|
||||
{`
|
||||
|
@ -19,7 +19,10 @@ export default function ColorIndicator({
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={colorIndicatorClassName}>
|
||||
<div
|
||||
className={colorIndicatorClassName}
|
||||
data-testid={`color-icon-${color}`}
|
||||
>
|
||||
{iconClassName ? (
|
||||
<i className={classnames('color-indicator__icon', iconClassName)} />
|
||||
) : (
|
||||
|
Loading…
Reference in New Issue
Block a user