mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-24 19:10:22 +01:00
Increase Jest unit test coverage for the Swaps feature to ~25% (#10900)
* Swaps: Show a network name dynamically in a tooltip * Replace “Ethereum” with “$1”, change “Test” to “Testnet” * Replace 이더리움 with $1 * Translate network names, use ‘Ethereum’ by default if a translation is not available yet * Reorder messages to resolve ESLint issues * Add a snapshot test for the FeeCard component, increase Jest threshold * Enable snapshot testing into external .snap files in ESLint * Add the “networkNameEthereum” key in ko/messages.json, remove default “Ethereum” value * Throw an error if chain ID is not supported by the Swaps feature * Use string literals when calling the `t` fn, * Watch Jest tests silently (no React warnings in terminal, only errors) * Add @testing-library/jest-dom, import it before running Jest tests * Add snapshot testing of Swaps’ React components for happy paths, increase minimum threshold for Jest * Add the test/jest folder for Jest setup and shared functions, use it in Swaps Jest tests * Fix ESLint issues, update linting config * Enable ESLint for .snap files (Jest snapshots), throw an error if a snapshot is bigger than 50 lines * Don’t run lint:fix for .snap files * Move `createProps` outside of `describe` blocks, move store creation inside tests * Use translations instead of keys, update a rendering function to load translations * Make sure all Jest snapshots are shorter than 50 lines (default limit) * Add / update props for Swaps tests * Fix React warnings when running tests for Swaps
This commit is contained in:
parent
d01bc9bb51
commit
fbbdaf04ed
17
.eslintrc.js
17
.eslintrc.js
@ -70,7 +70,7 @@ module.exports = {
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['ui/**/*.js', 'test/lib/render-helpers.js'],
|
||||
files: ['ui/**/*.js', 'test/lib/render-helpers.js', 'test/jest/*.js'],
|
||||
plugins: ['react'],
|
||||
extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'],
|
||||
rules: {
|
||||
@ -108,17 +108,28 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
files: ['**/*.test.js'],
|
||||
excludedFiles: ['ui/**/*.test.js'],
|
||||
excludedFiles: ['ui/**/*.test.js', 'ui/app/__mocks__/*.js'],
|
||||
extends: ['@metamask/eslint-config-mocha'],
|
||||
rules: {
|
||||
'mocha/no-setup-in-describe': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['ui/**/*.test.js'],
|
||||
files: ['**/__snapshots__/*.snap'],
|
||||
plugins: ['jest'],
|
||||
rules: {
|
||||
'jest/no-large-snapshots': [
|
||||
'error',
|
||||
{ maxSize: 50, inlineMaxSize: 50 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['ui/**/*.test.js', 'ui/app/__mocks__/*.js'],
|
||||
extends: ['@metamask/eslint-config-jest'],
|
||||
rules: {
|
||||
'jest/no-restricted-matchers': 'off',
|
||||
'import/unambiguous': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -3,12 +3,13 @@ module.exports = {
|
||||
coverageDirectory: 'jest-coverage/',
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
branches: 6.94,
|
||||
functions: 8.85,
|
||||
lines: 11.76,
|
||||
statements: 11.78,
|
||||
branches: 21.24,
|
||||
functions: 23.01,
|
||||
lines: 27.19,
|
||||
statements: 27.07,
|
||||
},
|
||||
},
|
||||
setupFiles: ['./test/setup.js', './test/env.js'],
|
||||
setupFilesAfterEnv: ['./test/jest/setup.js'],
|
||||
testMatch: ['**/ui/**/?(*.)+(test).js'],
|
||||
};
|
||||
|
@ -24,6 +24,7 @@
|
||||
"test:unit:global": "mocha --exit --require test/env.js --require test/setup.js --recursive test/unit-global/*.test.js",
|
||||
"test:unit:jest": "jest",
|
||||
"test:unit:jest:watch": "jest --watch",
|
||||
"test:unit:jest:watch:silent": "jest --watch --silent",
|
||||
"test:unit:jest:ci": "jest --maxWorkers=2",
|
||||
"test:unit:lax": "mocha --exit --require test/env.js --require test/setup.js --ignore './app/scripts/controllers/permissions/*.test.js' --recursive './{app,shared}/**/*.test.js'",
|
||||
"test:unit:strict": "mocha --exit --require test/env.js --require test/setup.js --recursive './app/scripts/controllers/permissions/*.test.js'",
|
||||
@ -38,7 +39,7 @@
|
||||
"test:coverage:path": "nyc --check-coverage yarn test:unit:path",
|
||||
"ganache:start": "./development/run-ganache.sh",
|
||||
"sentry:publish": "node ./development/sentry-publish.js",
|
||||
"lint": "prettier --check '**/*.json' && eslint . --ext js --cache && yarn lint:styles",
|
||||
"lint": "prettier --check '**/*.json' && eslint . --ext js,snap --cache && yarn lint:styles",
|
||||
"lint:fix": "prettier --write '**/*.json' && eslint . --ext js --cache --fix",
|
||||
"lint:changed": "{ git ls-files --others --exclude-standard ; git diff-index --name-only --diff-filter=d HEAD ; } | grep --regexp='[.]js$' | tr '\\n' '\\0' | xargs -0 eslint",
|
||||
"lint:changed:fix": "{ git ls-files --others --exclude-standard ; git diff-index --name-only --diff-filter=d HEAD ; } | grep --regexp='[.]js$' | tr '\\n' '\\0' | xargs -0 eslint --fix",
|
||||
@ -218,6 +219,7 @@
|
||||
"@storybook/core": "^6.1.17",
|
||||
"@storybook/react": "^6.1.17",
|
||||
"@storybook/storybook-deployer": "^2.8.7",
|
||||
"@testing-library/jest-dom": "^5.11.10",
|
||||
"@testing-library/react": "^10.4.8",
|
||||
"@testing-library/react-hooks": "^3.2.1",
|
||||
"@types/react": "^16.9.53",
|
||||
|
4
test/jest/index.js
Normal file
4
test/jest/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
import { createSwapsMockStore } from './mock-store';
|
||||
import { renderWithProvider } from './rendering';
|
||||
|
||||
export { createSwapsMockStore, renderWithProvider };
|
69
test/jest/mock-store.js
Normal file
69
test/jest/mock-store.js
Normal file
@ -0,0 +1,69 @@
|
||||
import { MAINNET_CHAIN_ID } from '../../shared/constants/network';
|
||||
|
||||
export const createSwapsMockStore = () => {
|
||||
return {
|
||||
swaps: {
|
||||
customGas: {
|
||||
fallBackPrice: 5,
|
||||
},
|
||||
},
|
||||
metamask: {
|
||||
provider: {
|
||||
chainId: MAINNET_CHAIN_ID,
|
||||
},
|
||||
cachedBalances: {
|
||||
[MAINNET_CHAIN_ID]: 5,
|
||||
},
|
||||
accounts: {
|
||||
'0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': {
|
||||
address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
|
||||
balance: '0x0',
|
||||
},
|
||||
'0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b': {
|
||||
address: '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b',
|
||||
balance: '0x0',
|
||||
},
|
||||
},
|
||||
selectedAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
|
||||
frequentRpcListDetail: [],
|
||||
swapsState: {
|
||||
quotes: {},
|
||||
fetchParams: {
|
||||
metaData: {
|
||||
sourceTokenInfo: {
|
||||
symbol: 'BAT',
|
||||
},
|
||||
destinationTokenInfo: {
|
||||
symbol: 'ETH',
|
||||
},
|
||||
},
|
||||
},
|
||||
tokens: [
|
||||
{
|
||||
erc20: true,
|
||||
symbol: 'BAT',
|
||||
decimals: 18,
|
||||
address: '0x0D8775F648430679A709E98d2b0Cb6250d2887EF',
|
||||
},
|
||||
{
|
||||
erc20: true,
|
||||
symbol: 'USDT',
|
||||
decimals: 6,
|
||||
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
|
||||
},
|
||||
],
|
||||
tradeTxId: null,
|
||||
approveTxId: null,
|
||||
quotesLastFetched: null,
|
||||
customMaxGas: '',
|
||||
customGasPrice: null,
|
||||
selectedAggId: null,
|
||||
customApproveTxData: '',
|
||||
errorKey: '',
|
||||
topAggId: null,
|
||||
routeState: '',
|
||||
swapsFeatureIsLive: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
59
test/jest/rendering.js
Normal file
59
test/jest/rendering.js
Normal file
@ -0,0 +1,59 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { render } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { I18nContext, LegacyI18nProvider } from '../../ui/app/contexts/i18n';
|
||||
import { getMessage } from '../../ui/app/helpers/utils/i18n-helper';
|
||||
import * as en from '../../app/_locales/en/messages.json';
|
||||
|
||||
export const I18nProvider = (props) => {
|
||||
const { currentLocale, current, en: eng } = props;
|
||||
|
||||
const t = useMemo(() => {
|
||||
return (key, ...args) =>
|
||||
getMessage(currentLocale, current, key, ...args) ||
|
||||
getMessage(currentLocale, eng, key, ...args);
|
||||
}, [currentLocale, current, eng]);
|
||||
|
||||
return (
|
||||
<I18nContext.Provider value={t}>{props.children}</I18nContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
I18nProvider.propTypes = {
|
||||
currentLocale: PropTypes.string,
|
||||
current: PropTypes.object,
|
||||
en: PropTypes.object,
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
I18nProvider.defaultProps = {
|
||||
children: undefined,
|
||||
};
|
||||
|
||||
export function renderWithProvider(component, store) {
|
||||
const Wrapper = ({ children }) => {
|
||||
const WithoutStore = () => (
|
||||
<MemoryRouter initialEntries={['/']} initialIndex={0}>
|
||||
<I18nProvider currentLocale="en" current={en} en={en}>
|
||||
<LegacyI18nProvider>{children}</LegacyI18nProvider>
|
||||
</I18nProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
return store ? (
|
||||
<Provider store={store}>
|
||||
<WithoutStore></WithoutStore>
|
||||
</Provider>
|
||||
) : (
|
||||
<WithoutStore></WithoutStore>
|
||||
);
|
||||
};
|
||||
|
||||
Wrapper.propTypes = {
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
return render(component, { wrapper: Wrapper });
|
||||
}
|
2
test/jest/setup.js
Normal file
2
test/jest/setup.js
Normal file
@ -0,0 +1,2 @@
|
||||
// jest-setup.js is for Jest-specific setup only and runs before our Jest tests.
|
||||
import '@testing-library/jest-dom';
|
6
ui/app/__mocks__/react-router-dom.js
vendored
Normal file
6
ui/app/__mocks__/react-router-dom.js
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
const originalModule = jest.requireActual('react-router-dom');
|
||||
|
||||
module.exports = {
|
||||
...originalModule,
|
||||
useHistory: jest.fn(),
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ActionableMessage renders the component with initial props 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="actionable-message"
|
||||
>
|
||||
|
||||
<div
|
||||
class="actionable-message__message"
|
||||
>
|
||||
I am an actionable message!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -80,6 +80,6 @@ ActionableMessage.propTypes = {
|
||||
}),
|
||||
className: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
withRightButton: PropTypes.boolean,
|
||||
withRightButton: PropTypes.bool,
|
||||
infoTooltipText: PropTypes.string,
|
||||
};
|
||||
|
@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
|
||||
import { renderWithProvider } from '../../../../../test/jest';
|
||||
import ActionableMessage from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
message: 'I am an actionable message!',
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('ActionableMessage', () => {
|
||||
it('renders the component with initial props', () => {
|
||||
const props = createProps();
|
||||
const { container, getByText } = renderWithProvider(
|
||||
<ActionableMessage {...props} />,
|
||||
);
|
||||
expect(getByText(props.message)).toBeInTheDocument();
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,45 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AwaitingSwap renders the component with initial props 1`] = `
|
||||
<div
|
||||
class="awaiting-swap__main-descrption"
|
||||
>
|
||||
<span>
|
||||
|
||||
Your
|
||||
<span
|
||||
class="awaiting-swap__amount-and-symbol"
|
||||
>
|
||||
ETH
|
||||
</span>
|
||||
will be added to your account once this transaction has processed.
|
||||
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`AwaitingSwap renders the component with initial props 2`] = `
|
||||
<div
|
||||
class="swaps-footer"
|
||||
>
|
||||
<div
|
||||
class="swaps-footer__buttons"
|
||||
>
|
||||
<div
|
||||
class="page-container__footer swaps-footer__custom-page-container-footer-class"
|
||||
>
|
||||
<footer>
|
||||
<button
|
||||
class="button btn-primary page-container__footer-button swaps-footer__custom-page-container-footer-button-class swaps-footer__custom-page-container-footer-button-class--single"
|
||||
data-testid="page-container-footer-next"
|
||||
disabled=""
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
View in activity
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
37
ui/app/pages/swaps/awaiting-swap/awaiting-swap.test.js
Normal file
37
ui/app/pages/swaps/awaiting-swap/awaiting-swap.test.js
Normal file
@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
|
||||
import {
|
||||
renderWithProvider,
|
||||
createSwapsMockStore,
|
||||
} from '../../../../../test/jest';
|
||||
import AwaitingSwap from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
swapComplete: false,
|
||||
txHash: 'txHash',
|
||||
tokensReceived: 'tokensReceived',
|
||||
submittingSwap: true,
|
||||
inputValue: 5,
|
||||
maxSlippage: 3,
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('AwaitingSwap', () => {
|
||||
it('renders the component with initial props', () => {
|
||||
const store = configureMockStore()(createSwapsMockStore());
|
||||
const { getByText } = renderWithProvider(
|
||||
<AwaitingSwap {...createProps()} />,
|
||||
store,
|
||||
);
|
||||
expect(getByText('Processing')).toBeInTheDocument();
|
||||
expect(getByText('View on Etherscan')).toBeInTheDocument();
|
||||
expect(getByText('View in activity')).toBeInTheDocument();
|
||||
expect(
|
||||
document.querySelector('.awaiting-swap__main-descrption'),
|
||||
).toMatchSnapshot();
|
||||
expect(document.querySelector('.swaps-footer')).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -94,6 +94,7 @@ export default function CountdownTimer({
|
||||
return (
|
||||
<div className="countdown-timer">
|
||||
<div
|
||||
data-testid="countdown-timer__timer-container"
|
||||
className={classnames('countdown-timer__timer-container', {
|
||||
'countdown-timer__timer-container--warning':
|
||||
warningTime && timeBelowWarningTime(timer, warningTime),
|
||||
|
31
ui/app/pages/swaps/countdown-timer/countdown-timer.test.js
Normal file
31
ui/app/pages/swaps/countdown-timer/countdown-timer.test.js
Normal file
@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
|
||||
import {
|
||||
renderWithProvider,
|
||||
createSwapsMockStore,
|
||||
} from '../../../../../test/jest';
|
||||
import CountdownTimer from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
timeStarted: 1,
|
||||
timeOnly: true,
|
||||
timerBase: 5,
|
||||
warningTime: '0:30',
|
||||
labelKey: 'swapNewQuoteIn',
|
||||
infoTooltipLabelKey: 'swapQuotesAreRefreshed',
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('CountdownTimer', () => {
|
||||
it('renders the component with initial props', () => {
|
||||
const store = configureMockStore()(createSwapsMockStore());
|
||||
const { getByTestId } = renderWithProvider(
|
||||
<CountdownTimer {...createProps()} />,
|
||||
store,
|
||||
);
|
||||
expect(getByTestId('countdown-timer__timer-container')).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -0,0 +1,20 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DropdownInputPair renders the component with initial props 1`] = `
|
||||
<div
|
||||
class="MuiFormControl-root MuiTextField-root dropdown-input-pair__input 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"
|
||||
dir="auto"
|
||||
placeholder="0"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
|
||||
import { renderWithProvider } from '../../../../../test/jest';
|
||||
import DropdownInputPair from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('DropdownInputPair', () => {
|
||||
it('renders the component with initial props', () => {
|
||||
const props = createProps();
|
||||
const { getByPlaceholderText } = renderWithProvider(
|
||||
<DropdownInputPair {...props} />,
|
||||
);
|
||||
expect(getByPlaceholderText('0')).toBeInTheDocument();
|
||||
expect(
|
||||
document.querySelector('.dropdown-input-pair__input'),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,40 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DropdownSearchList renders the component with initial props 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="dropdown-search-list"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="dropdown-search-list__selector-closed-container"
|
||||
>
|
||||
<div
|
||||
class="dropdown-search-list__selector-closed"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
class="url-icon dropdown-search-list__selector-closed-icon"
|
||||
src="iconUrl"
|
||||
/>
|
||||
<div
|
||||
class="dropdown-search-list__labels"
|
||||
>
|
||||
<div
|
||||
class="dropdown-search-list__item-labels"
|
||||
>
|
||||
<span
|
||||
class="dropdown-search-list__closed-primary-label"
|
||||
>
|
||||
symbol
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<i
|
||||
class="fa fa-caret-down fa-lg dropdown-search-list__caret"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
|
||||
import { renderWithProvider } from '../../../../../test/jest';
|
||||
import DropdownSearchList from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
startingItem: {
|
||||
iconUrl: 'iconUrl',
|
||||
symbol: 'symbol',
|
||||
},
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('DropdownSearchList', () => {
|
||||
it('renders the component with initial props', () => {
|
||||
const props = createProps();
|
||||
const { container, getByText } = renderWithProvider(
|
||||
<DropdownSearchList {...props} />,
|
||||
);
|
||||
expect(container).toMatchSnapshot();
|
||||
expect(getByText('symbol')).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -0,0 +1,45 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ExchangeRateDisplay renders the component with initial props 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="exchange-rate-display"
|
||||
>
|
||||
<span>
|
||||
1
|
||||
</span>
|
||||
<span
|
||||
class="exchange-rate-display__bold"
|
||||
>
|
||||
ETH
|
||||
</span>
|
||||
<span>
|
||||
=
|
||||
</span>
|
||||
<span>
|
||||
0.1
|
||||
</span>
|
||||
<span
|
||||
class="exchange-rate-display__bold"
|
||||
>
|
||||
BAT
|
||||
</span>
|
||||
<div
|
||||
class="exchange-rate-display__switch-arrows"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="13"
|
||||
viewBox="0 0 13 13"
|
||||
width="13"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M4.15294 4.38514H9.99223L8.50853 5.86884C8.30421 6.07297 8.30421 6.40418 8.50853 6.60869C8.61069 6.71085 8.74443 6.76203 8.87836 6.76203C9.01229 6.76203 9.14603 6.71085 9.24819 6.60869L11.6249 4.23219C11.649 4.20803 11.6707 4.1814 11.6899 4.15305C11.6947 4.14563 11.6981 4.13726 11.7025 4.12965C11.7154 4.10815 11.7282 4.08646 11.7381 4.06325C11.7426 4.05222 11.7447 4.04043 11.7487 4.0292C11.7558 4.00827 11.7636 3.98754 11.7681 3.96547C11.775 3.93161 11.7786 3.89717 11.7786 3.86198C11.7786 3.82678 11.775 3.79235 11.7681 3.75849C11.7638 3.73642 11.756 3.71568 11.7487 3.69476C11.7447 3.68353 11.7428 3.67174 11.7381 3.6607C11.7282 3.63749 11.7156 3.616 11.7025 3.59431C11.6981 3.5867 11.6947 3.57833 11.6899 3.57091C11.6707 3.54256 11.649 3.51593 11.6249 3.49177L9.24876 1.11564C9.04444 0.911322 8.71342 0.911322 8.50891 1.11564C8.30459 1.31977 8.30459 1.65098 8.50891 1.85549L9.99223 3.339H4.15294C2.22978 3.339 0.665039 4.90374 0.665039 6.8269C0.665039 7.11588 0.899227 7.35007 1.1882 7.35007C1.47718 7.35007 1.71137 7.11588 1.71137 6.8269C1.71137 5.48037 2.80659 4.38514 4.15294 4.38514ZM12.2066 6.57445C11.9177 6.57445 11.6835 6.80864 11.6835 7.09762C11.6835 8.44396 10.5883 9.53919 9.24191 9.53919H3.40262L4.88632 8.05549C5.09064 7.85136 5.09064 7.52014 4.88632 7.31563C4.682 7.11112 4.35098 7.11131 4.14647 7.31563L1.76977 9.69233C1.74561 9.71649 1.72393 9.74312 1.70471 9.77147C1.70015 9.7787 1.69691 9.78669 1.69273 9.79392C1.6796 9.81561 1.66647 9.83748 1.65677 9.86126C1.6524 9.87211 1.6503 9.88371 1.64631 9.89475C1.63927 9.91586 1.63128 9.93679 1.62671 9.95905C1.61986 9.99291 1.61625 10.0273 1.61625 10.0625C1.61625 10.0977 1.61986 10.1322 1.62671 10.166C1.63109 10.1883 1.63908 10.2092 1.64631 10.2303C1.6503 10.2414 1.65221 10.253 1.65677 10.2638C1.66666 10.2874 1.6796 10.3093 1.69273 10.3312C1.69691 10.3384 1.70015 10.3464 1.70471 10.3536C1.72393 10.382 1.74561 10.4086 1.76977 10.4328L4.14609 12.8091C4.24825 12.9112 4.38199 12.9624 4.51592 12.9624C4.64985 12.9624 4.78359 12.9112 4.88575 12.8091C5.09007 12.6049 5.09007 12.2737 4.88575 12.0692L3.40243 10.5857H9.24172C11.1649 10.5857 12.7296 9.02097 12.7296 7.09781C12.7298 6.80864 12.4956 6.57445 12.2066 6.57445Z"
|
||||
fill="black"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
|
||||
import { renderWithProvider } from '../../../../../test/jest';
|
||||
import ExchangeRateDisplay from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
primaryTokenValue: '2000000000000000000',
|
||||
primaryTokenDecimals: 18,
|
||||
primaryTokenSymbol: 'ETH',
|
||||
secondaryTokenValue: '200000000000000000',
|
||||
secondaryTokenDecimals: 18,
|
||||
secondaryTokenSymbol: 'BAT',
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('ExchangeRateDisplay', () => {
|
||||
it('renders the component with initial props', () => {
|
||||
const props = createProps();
|
||||
const { container, getByText } = renderWithProvider(
|
||||
<ExchangeRateDisplay {...props} />,
|
||||
);
|
||||
expect(getByText(props.primaryTokenSymbol)).toBeInTheDocument();
|
||||
expect(getByText(props.secondaryTokenSymbol)).toBeInTheDocument();
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -1,172 +1,67 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`FeeCard renders the component with initial props 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="fee-card__savings-and-quotes-header"
|
||||
>
|
||||
<div
|
||||
class="fee-card"
|
||||
class="fee-card__savings-and-quotes-row"
|
||||
>
|
||||
<div
|
||||
class="fee-card__savings-and-quotes-header"
|
||||
<p
|
||||
class="fee-card__savings-text"
|
||||
>
|
||||
<div
|
||||
class="fee-card__savings-and-quotes-row"
|
||||
Using the best quote
|
||||
</p>
|
||||
<div
|
||||
class="fee-card__quote-link-container"
|
||||
>
|
||||
<p
|
||||
class="fee-card__quote-link-text"
|
||||
>
|
||||
<p
|
||||
class="fee-card__savings-text"
|
||||
>
|
||||
[swapUsingBestQuote]
|
||||
</p>
|
||||
<div
|
||||
class="fee-card__quote-link-container"
|
||||
>
|
||||
<p
|
||||
class="fee-card__quote-link-text"
|
||||
>
|
||||
[swapNQuotes]
|
||||
</p>
|
||||
<div
|
||||
class="fee-card__caret-right"
|
||||
>
|
||||
<i
|
||||
class="fa fa-angle-up"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
6 quotes
|
||||
</p>
|
||||
<div
|
||||
class="fee-card__caret-right"
|
||||
>
|
||||
<i
|
||||
class="fa fa-angle-up"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`FeeCard renders the component with initial props 2`] = `
|
||||
<div
|
||||
class="fee-card__top-bordered-row"
|
||||
>
|
||||
<div
|
||||
class="fee-card__row-label"
|
||||
>
|
||||
<div
|
||||
class="fee-card__main"
|
||||
class="fee-card__row-header-text"
|
||||
>
|
||||
Quote includes a 0.875% MetaMask fee
|
||||
</div>
|
||||
<div
|
||||
class="info-tooltip"
|
||||
>
|
||||
<div
|
||||
class="fee-card__row-header"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="fee-card__row-header-text--bold"
|
||||
>
|
||||
[swapEstimatedNetworkFee]
|
||||
</div>
|
||||
<div
|
||||
class="info-tooltip"
|
||||
>
|
||||
<div
|
||||
class="fee-card__row-label fee-card__info-tooltip-container"
|
||||
>
|
||||
<div
|
||||
aria-describedby="tippy-tooltip-1"
|
||||
class="info-tooltip__tooltip-container fee-card__info-tooltip-content-container"
|
||||
data-original-title="null"
|
||||
data-tooltipped=""
|
||||
style="display: inline;"
|
||||
tabindex="0"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
src="images/mm-info-icon.svg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="fee-card__row-header-secondary--bold"
|
||||
/>
|
||||
<div
|
||||
class="fee-card__row-header-primary--bold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="fee-card__row-header"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="fee-card__row-header-text"
|
||||
>
|
||||
[swapMaxNetworkFees]
|
||||
</div>
|
||||
<div
|
||||
class="fee-card__link"
|
||||
>
|
||||
[edit]
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="fee-card__row-header-secondary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="fee-card__row-header"
|
||||
class="fee-card__info-tooltip-container"
|
||||
>
|
||||
<div
|
||||
class="fee-card__row-label"
|
||||
aria-describedby="tippy-tooltip-3"
|
||||
class="info-tooltip__tooltip-container"
|
||||
data-original-title="null"
|
||||
data-tooltipped=""
|
||||
style="display: inline;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="fee-card__row-header-text"
|
||||
>
|
||||
[swapThisWillAllowApprove]
|
||||
</div>
|
||||
<div
|
||||
class="info-tooltip"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
aria-describedby="tippy-tooltip-2"
|
||||
class="info-tooltip__tooltip-container fee-card__info-tooltip-container"
|
||||
data-original-title="null"
|
||||
data-tooltipped=""
|
||||
style="display: inline;"
|
||||
tabindex="0"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
src="images/mm-info-icon.svg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="fee-card__link"
|
||||
>
|
||||
[swapEditLimit]
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="fee-card__top-bordered-row"
|
||||
>
|
||||
<div
|
||||
class="fee-card__row-label"
|
||||
>
|
||||
<div
|
||||
class="fee-card__row-header-text"
|
||||
>
|
||||
[swapQuoteIncludesRate]
|
||||
</div>
|
||||
<div
|
||||
class="info-tooltip"
|
||||
>
|
||||
<div
|
||||
class="fee-card__info-tooltip-container"
|
||||
>
|
||||
<div
|
||||
aria-describedby="tippy-tooltip-3"
|
||||
class="info-tooltip__tooltip-container"
|
||||
data-original-title="null"
|
||||
data-tooltipped=""
|
||||
style="display: inline;"
|
||||
tabindex="0"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
src="images/mm-info-icon.svg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<img
|
||||
alt=""
|
||||
src="images/mm-info-icon.svg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,31 +1,61 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
import { renderWithProvider } from '../../../../../test/jest';
|
||||
import { MAINNET_CHAIN_ID } from '../../../../../shared/constants/network';
|
||||
import FeeCard from './fee-card';
|
||||
import FeeCard from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
primaryFee: {
|
||||
fee: '0.0441 ETH',
|
||||
maxFee: '0.04851 ETH',
|
||||
},
|
||||
secondaryFee: {
|
||||
fee: '$101.98',
|
||||
maxFee: '$112.17',
|
||||
},
|
||||
hideTokenApprovalRow: false,
|
||||
onFeeCardMaxRowClick: jest.fn(),
|
||||
tokenApprovalTextComponent: (
|
||||
<span
|
||||
key="swaps-view-quote-approve-symbol-1"
|
||||
className="view-quote__bold"
|
||||
>
|
||||
ABC
|
||||
</span>
|
||||
),
|
||||
tokenApprovalSourceTokenSymbol: 'ABC',
|
||||
onTokenApprovalClick: jest.fn(),
|
||||
metaMaskFee: '0.875',
|
||||
isBestQuote: true,
|
||||
numberOfQuotes: 6,
|
||||
onQuotesClick: jest.fn(),
|
||||
tokenConversionRate: 0.015,
|
||||
chainId: MAINNET_CHAIN_ID,
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('FeeCard', () => {
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
primaryFee: '1 ETH',
|
||||
secondaryFee: '2500 USD',
|
||||
hideTokenApprovalRow: false,
|
||||
onFeeCardMaxRowClick: jest.fn(),
|
||||
tokenApprovalTextComponent: <></>,
|
||||
tokenApprovalSourceTokenSymbol: 'ABC',
|
||||
onTokenApprovalClick: jest.fn(),
|
||||
metaMaskFee: '0.875',
|
||||
isBestQuote: true,
|
||||
numberOfQuotes: 6,
|
||||
onQuotesClick: jest.fn(),
|
||||
tokenConversionRate: 0.015,
|
||||
chainId: MAINNET_CHAIN_ID,
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
it('renders the component with initial props', () => {
|
||||
const { container } = render(<FeeCard {...createProps()} />);
|
||||
expect(container).toMatchSnapshot();
|
||||
const props = createProps();
|
||||
const { getByText } = renderWithProvider(<FeeCard {...props} />);
|
||||
expect(getByText('Using the best quote')).toBeInTheDocument();
|
||||
expect(getByText('6 quotes')).toBeInTheDocument();
|
||||
expect(getByText('Max network fee')).toBeInTheDocument();
|
||||
expect(getByText('Estimated network fee')).toBeInTheDocument();
|
||||
expect(getByText(props.primaryFee.fee)).toBeInTheDocument();
|
||||
expect(getByText(props.primaryFee.maxFee)).toBeInTheDocument();
|
||||
expect(getByText(props.secondaryFee.fee)).toBeInTheDocument();
|
||||
expect(getByText(props.secondaryFee.maxFee)).toBeInTheDocument();
|
||||
expect(
|
||||
getByText('Quote includes a 0.875% MetaMask fee'),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
document.querySelector('.fee-card__savings-and-quotes-header'),
|
||||
).toMatchSnapshot();
|
||||
expect(
|
||||
document.querySelector('.fee-card__top-bordered-row'),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,9 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`IntroPopup renders the component with initial props 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="intro-popup"
|
||||
/>
|
||||
</div>
|
||||
`;
|
24
ui/app/pages/swaps/intro-popup/intro-popup.test.js
Normal file
24
ui/app/pages/swaps/intro-popup/intro-popup.test.js
Normal file
@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
|
||||
import {
|
||||
renderWithProvider,
|
||||
createSwapsMockStore,
|
||||
} from '../../../../../test/jest';
|
||||
import IntroPopup from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
onClose: jest.fn(),
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('IntroPopup', () => {
|
||||
it('renders the component with initial props', () => {
|
||||
const store = configureMockStore()(createSwapsMockStore());
|
||||
const props = createProps();
|
||||
const { container } = renderWithProvider(<IntroPopup {...props} />, store);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,109 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`MainQuoteSummary renders the component with initial props 1`] = `
|
||||
<div
|
||||
class="main-quote-summary__source-row"
|
||||
>
|
||||
<span
|
||||
class="main-quote-summary__source-row-value"
|
||||
title="2"
|
||||
>
|
||||
2
|
||||
</span>
|
||||
<i
|
||||
class="icon-with-fallback__fallback url-icon__fallback main-quote-summary__icon-fallback"
|
||||
>
|
||||
E
|
||||
</i>
|
||||
<span
|
||||
class="main-quote-summary__source-row-symbol"
|
||||
title="ETH"
|
||||
>
|
||||
ETH
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`MainQuoteSummary renders the component with initial props 2`] = `
|
||||
<div
|
||||
class="main-quote-summary__destination-row"
|
||||
>
|
||||
<i
|
||||
class="icon-with-fallback__fallback url-icon__fallback main-quote-summary__icon-fallback"
|
||||
>
|
||||
B
|
||||
</i>
|
||||
<span
|
||||
class="main-quote-summary__destination-row-symbol"
|
||||
>
|
||||
BAT
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`MainQuoteSummary renders the component with initial props 3`] = `
|
||||
<div
|
||||
class="main-quote-summary__quote-large"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class=""
|
||||
style="display: inline;"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="main-quote-summary__quote-large-number"
|
||||
style="font-size: 60px; line-height: 48px;"
|
||||
>
|
||||
0.2
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`MainQuoteSummary renders the component with initial props 4`] = `
|
||||
<div
|
||||
class="main-quote-summary__exchange-rate-container"
|
||||
>
|
||||
<div
|
||||
class="exchange-rate-display main-quote-summary__exchange-rate-display"
|
||||
>
|
||||
<span>
|
||||
1
|
||||
</span>
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
ETH
|
||||
</span>
|
||||
<span>
|
||||
=
|
||||
</span>
|
||||
<span>
|
||||
0.1
|
||||
</span>
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
BAT
|
||||
</span>
|
||||
<div
|
||||
class="exchange-rate-display__switch-arrows"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="13"
|
||||
viewBox="0 0 13 13"
|
||||
width="13"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M4.15294 4.38514H9.99223L8.50853 5.86884C8.30421 6.07297 8.30421 6.40418 8.50853 6.60869C8.61069 6.71085 8.74443 6.76203 8.87836 6.76203C9.01229 6.76203 9.14603 6.71085 9.24819 6.60869L11.6249 4.23219C11.649 4.20803 11.6707 4.1814 11.6899 4.15305C11.6947 4.14563 11.6981 4.13726 11.7025 4.12965C11.7154 4.10815 11.7282 4.08646 11.7381 4.06325C11.7426 4.05222 11.7447 4.04043 11.7487 4.0292C11.7558 4.00827 11.7636 3.98754 11.7681 3.96547C11.775 3.93161 11.7786 3.89717 11.7786 3.86198C11.7786 3.82678 11.775 3.79235 11.7681 3.75849C11.7638 3.73642 11.756 3.71568 11.7487 3.69476C11.7447 3.68353 11.7428 3.67174 11.7381 3.6607C11.7282 3.63749 11.7156 3.616 11.7025 3.59431C11.6981 3.5867 11.6947 3.57833 11.6899 3.57091C11.6707 3.54256 11.649 3.51593 11.6249 3.49177L9.24876 1.11564C9.04444 0.911322 8.71342 0.911322 8.50891 1.11564C8.30459 1.31977 8.30459 1.65098 8.50891 1.85549L9.99223 3.339H4.15294C2.22978 3.339 0.665039 4.90374 0.665039 6.8269C0.665039 7.11588 0.899227 7.35007 1.1882 7.35007C1.47718 7.35007 1.71137 7.11588 1.71137 6.8269C1.71137 5.48037 2.80659 4.38514 4.15294 4.38514ZM12.2066 6.57445C11.9177 6.57445 11.6835 6.80864 11.6835 7.09762C11.6835 8.44396 10.5883 9.53919 9.24191 9.53919H3.40262L4.88632 8.05549C5.09064 7.85136 5.09064 7.52014 4.88632 7.31563C4.682 7.11112 4.35098 7.11131 4.14647 7.31563L1.76977 9.69233C1.74561 9.71649 1.72393 9.74312 1.70471 9.77147C1.70015 9.7787 1.69691 9.78669 1.69273 9.79392C1.6796 9.81561 1.66647 9.83748 1.65677 9.86126C1.6524 9.87211 1.6503 9.88371 1.64631 9.89475C1.63927 9.91586 1.63128 9.93679 1.62671 9.95905C1.61986 9.99291 1.61625 10.0273 1.61625 10.0625C1.61625 10.0977 1.61986 10.1322 1.62671 10.166C1.63109 10.1883 1.63908 10.2092 1.64631 10.2303C1.6503 10.2414 1.65221 10.253 1.65677 10.2638C1.66666 10.2874 1.6796 10.3093 1.69273 10.3312C1.69691 10.3384 1.70015 10.3464 1.70471 10.3536C1.72393 10.382 1.74561 10.4086 1.76977 10.4328L4.14609 12.8091C4.24825 12.9112 4.38199 12.9624 4.51592 12.9624C4.64985 12.9624 4.78359 12.9112 4.88575 12.8091C5.09007 12.6049 5.09007 12.2737 4.88575 12.0692L3.40243 10.5857H9.24172C11.1649 10.5857 12.7296 9.02097 12.7296 7.09781C12.7298 6.80864 12.4956 6.57445 12.2066 6.57445Z"
|
||||
fill="#037DD6"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
|
||||
import { renderWithProvider } from '../../../../../test/jest';
|
||||
import MainQuoteSummary from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
sourceValue: '2000000000000000000',
|
||||
sourceDecimals: 18,
|
||||
sourceSymbol: 'ETH',
|
||||
destinationValue: '200000000000000000',
|
||||
destinationDecimals: 18,
|
||||
destinationSymbol: 'BAT',
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('MainQuoteSummary', () => {
|
||||
it('renders the component with initial props', () => {
|
||||
const props = createProps();
|
||||
const { getAllByText } = renderWithProvider(
|
||||
<MainQuoteSummary {...props} />,
|
||||
);
|
||||
expect(getAllByText(props.sourceSymbol)).toHaveLength(2);
|
||||
expect(getAllByText(props.destinationSymbol)).toHaveLength(2);
|
||||
expect(
|
||||
document.querySelector('.main-quote-summary__source-row'),
|
||||
).toMatchSnapshot();
|
||||
expect(
|
||||
document.querySelector('.main-quote-summary__destination-row'),
|
||||
).toMatchSnapshot();
|
||||
expect(
|
||||
document.querySelector('.main-quote-summary__quote-large'),
|
||||
).toMatchSnapshot();
|
||||
expect(
|
||||
document.querySelector('.main-quote-summary__exchange-rate-container'),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,77 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SearchableItemList renders the component with initial props 1`] = `
|
||||
<div
|
||||
class="MuiFormControl-root MuiTextField-root searchable-item-list__search MuiFormControl-fullWidth"
|
||||
data-testid="search-list-items"
|
||||
>
|
||||
<div
|
||||
class="MuiInputBase-root MuiInput-root TextField-inputRoot-12 MuiInputBase-fullWidth MuiInput-fullWidth Mui-focused Mui-focused TextField-inputFocused-11 MuiInputBase-formControl MuiInput-formControl MuiInputBase-adornedStart"
|
||||
>
|
||||
<div
|
||||
class="MuiInputAdornment-root MuiInputAdornment-positionStart"
|
||||
style="margin-right: 12px;"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
height="17"
|
||||
src="images/search.svg"
|
||||
width="17"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
aria-invalid="false"
|
||||
autocomplete="off"
|
||||
class="MuiInputBase-input MuiInput-input MuiInputBase-inputAdornedStart"
|
||||
dir="auto"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`SearchableItemList renders the component with initial props 2`] = `
|
||||
<div
|
||||
class="searchable-item-list__item searchable-item-list__item--selected"
|
||||
tabindex="0"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
class="url-icon"
|
||||
src="iconUrl"
|
||||
/>
|
||||
<div
|
||||
class="searchable-item-list__labels"
|
||||
>
|
||||
<div
|
||||
class="searchable-item-list__item-labels"
|
||||
>
|
||||
<span
|
||||
class="searchable-item-list__primary-label"
|
||||
>
|
||||
primaryLabel
|
||||
</span>
|
||||
<span
|
||||
class="searchable-item-list__secondary-label"
|
||||
>
|
||||
secondaryLabel
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="searchable-item-list__right-labels"
|
||||
>
|
||||
<span
|
||||
class="searchable-item-list__right-primary-label"
|
||||
>
|
||||
rightPrimaryLabel
|
||||
</span>
|
||||
<span
|
||||
class="searchable-item-list__right-secondary-label"
|
||||
>
|
||||
rightSecondaryLabel
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
|
||||
import { renderWithProvider } from '../../../../../test/jest';
|
||||
import SearchableItemList from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
defaultToAll: true,
|
||||
listTitle: 'listTitle',
|
||||
itemsToSearch: [
|
||||
{
|
||||
iconUrl: 'iconUrl',
|
||||
selected: true,
|
||||
primaryLabel: 'primaryLabel',
|
||||
secondaryLabel: 'secondaryLabel',
|
||||
rightPrimaryLabel: 'rightPrimaryLabel',
|
||||
rightSecondaryLabel: 'rightSecondaryLabel',
|
||||
},
|
||||
],
|
||||
fuseSearchKeys: [
|
||||
{
|
||||
name: 'name',
|
||||
weight: 0.499,
|
||||
},
|
||||
{
|
||||
name: 'symbol',
|
||||
weight: 0.499,
|
||||
},
|
||||
{
|
||||
name: 'address',
|
||||
weight: 0.002,
|
||||
},
|
||||
],
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('SearchableItemList', () => {
|
||||
it('renders the component with initial props', () => {
|
||||
const props = createProps();
|
||||
const { getByText } = renderWithProvider(<SearchableItemList {...props} />);
|
||||
expect(getByText(props.listTitle)).toBeInTheDocument();
|
||||
expect(getByText(props.itemsToSearch[0].primaryLabel)).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(props.itemsToSearch[0].secondaryLabel),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(props.itemsToSearch[0].rightPrimaryLabel),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(props.itemsToSearch[0].rightSecondaryLabel),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
document.querySelector('.searchable-item-list__search'),
|
||||
).toMatchSnapshot();
|
||||
expect(
|
||||
document.querySelector('.searchable-item-list__item'),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,9 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SelectQuotePopover renders the component with initial props 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="select-quote-popover"
|
||||
/>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
|
||||
import { renderWithProvider } from '../../../../../test/jest';
|
||||
import SelectQuotePopover from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
onClose: jest.fn(),
|
||||
onSubmit: jest.fn(),
|
||||
swapToSymbol: 'ETH',
|
||||
initialAggId: 'initialAggId',
|
||||
onQuoteDetailsIsOpened: jest.fn(),
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('SelectQuotePopover', () => {
|
||||
it('renders the component with initial props', () => {
|
||||
const { container } = renderWithProvider(
|
||||
<SelectQuotePopover {...createProps()} />,
|
||||
);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,42 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SlippageButtons renders the component with initial props 1`] = `
|
||||
<div
|
||||
class="slippage-buttons__header"
|
||||
>
|
||||
<div
|
||||
class="slippage-buttons__header-text"
|
||||
>
|
||||
Advanced Options
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`SlippageButtons renders the component with initial props 2`] = `
|
||||
<div
|
||||
class="button-group slippage-buttons__button-group radio-button-group"
|
||||
role="radiogroup"
|
||||
>
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="button-group__button radio-button"
|
||||
role="radio"
|
||||
>
|
||||
2%
|
||||
</button>
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="button-group__button radio-button button-group__button--active radio-button--active"
|
||||
role="radio"
|
||||
>
|
||||
3%
|
||||
</button>
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="button-group__button slippage-buttons__button-group-custom-button radio-button"
|
||||
role="radio"
|
||||
>
|
||||
custom
|
||||
</button>
|
||||
</div>
|
||||
`;
|
31
ui/app/pages/swaps/slippage-buttons/slippage-buttons.test.js
Normal file
31
ui/app/pages/swaps/slippage-buttons/slippage-buttons.test.js
Normal file
@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
|
||||
import { renderWithProvider } from '../../../../../test/jest';
|
||||
import SlippageButtons from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
onSelect: jest.fn(),
|
||||
maxAllowedSlippage: 15,
|
||||
currentSlippage: 3,
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('SlippageButtons', () => {
|
||||
it('renders the component with initial props', () => {
|
||||
const { getByText } = renderWithProvider(
|
||||
<SlippageButtons {...createProps()} />,
|
||||
);
|
||||
expect(getByText('2%')).toBeInTheDocument();
|
||||
expect(getByText('3%')).toBeInTheDocument();
|
||||
expect(getByText('custom')).toBeInTheDocument();
|
||||
expect(getByText('Advanced Options')).toBeInTheDocument();
|
||||
expect(
|
||||
document.querySelector('.slippage-buttons__header'),
|
||||
).toMatchSnapshot();
|
||||
expect(
|
||||
document.querySelector('.slippage-buttons__button-group'),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,41 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SwapsFooter renders the component with initial props 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="swaps-footer"
|
||||
>
|
||||
<div
|
||||
class="swaps-footer__buttons"
|
||||
>
|
||||
<div
|
||||
class="page-container__footer swaps-footer__custom-page-container-footer-class"
|
||||
>
|
||||
<footer>
|
||||
<button
|
||||
class="button btn-default page-container__footer-button swaps-footer__custom-page-container-footer-button-class"
|
||||
data-testid="page-container-footer-cancel"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
<button
|
||||
class="button btn-primary page-container__footer-button swaps-footer__custom-page-container-footer-button-class"
|
||||
data-testid="page-container-footer-next"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
submitText
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="swaps-footer__bottom-text"
|
||||
>
|
||||
Terms of Service
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
28
ui/app/pages/swaps/swaps-footer/swaps-footer.test.js
Normal file
28
ui/app/pages/swaps/swaps-footer/swaps-footer.test.js
Normal file
@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
|
||||
import { renderWithProvider } from '../../../../../test/jest';
|
||||
import SwapsFooter from '.';
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
onCancel: jest.fn(),
|
||||
onSubmit: jest.fn(),
|
||||
submitText: 'submitText',
|
||||
disabled: false,
|
||||
showTermsOfService: true,
|
||||
...customProps,
|
||||
};
|
||||
};
|
||||
|
||||
describe('SwapsFooter', () => {
|
||||
it('renders the component with initial props', () => {
|
||||
const props = createProps();
|
||||
const { container, getByText } = renderWithProvider(
|
||||
<SwapsFooter {...props} />,
|
||||
);
|
||||
expect(getByText(props.submitText)).toBeInTheDocument();
|
||||
expect(getByText('Back')).toBeInTheDocument();
|
||||
expect(getByText('Terms of Service')).toBeInTheDocument();
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
60
yarn.lock
60
yarn.lock
@ -3522,6 +3522,20 @@
|
||||
dom-accessibility-api "^0.5.0"
|
||||
pretty-format "^25.5.0"
|
||||
|
||||
"@testing-library/jest-dom@^5.11.10":
|
||||
version "5.11.10"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.10.tgz#1cd90715023e1627f5ed26ab3b38e6f22d77046c"
|
||||
integrity sha512-FuKiq5xuk44Fqm0000Z9w0hjOdwZRNzgx7xGGxQYepWFZy+OYUMOT/wPI4nLYXCaVltNVpU1W/qmD88wLWDsqQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.9.2"
|
||||
"@types/testing-library__jest-dom" "^5.9.1"
|
||||
aria-query "^4.2.2"
|
||||
chalk "^3.0.0"
|
||||
css "^3.0.0"
|
||||
css.escape "^1.5.1"
|
||||
lodash "^4.17.15"
|
||||
redent "^3.0.0"
|
||||
|
||||
"@testing-library/react-hooks@^3.2.1":
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-3.2.1.tgz#19b6caa048ef15faa69d439c469033873ea01294"
|
||||
@ -3720,6 +3734,14 @@
|
||||
dependencies:
|
||||
"@types/istanbul-lib-report" "*"
|
||||
|
||||
"@types/jest@*":
|
||||
version "26.0.22"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.22.tgz#8308a1debdf1b807aa47be2838acdcd91e88fbe6"
|
||||
integrity sha512-eeWwWjlqxvBxc4oQdkueW5OF/gtfSceKk4OnOAGlUSwS/liBRtZppbJuz1YkgbrbfGOoeBHun9fOvXnjNwrSOw==
|
||||
dependencies:
|
||||
jest-diff "^26.0.0"
|
||||
pretty-format "^26.0.0"
|
||||
|
||||
"@types/json-schema@^7.0.3":
|
||||
version "7.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
|
||||
@ -3906,6 +3928,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74"
|
||||
integrity sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==
|
||||
|
||||
"@types/testing-library__jest-dom@^5.9.1":
|
||||
version "5.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.9.5.tgz#5bf25c91ad2d7b38f264b12275e5c92a66d849b0"
|
||||
integrity sha512-ggn3ws+yRbOHog9GxnXiEZ/35Mow6YtPZpd7Z5mKDeZS/o7zx3yAle0ov/wjhVB5QT4N2Dt+GNoGCdqkBGCajQ==
|
||||
dependencies:
|
||||
"@types/jest" "*"
|
||||
|
||||
"@types/testing-library__react-hooks@^3.0.0":
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/testing-library__react-hooks/-/testing-library__react-hooks-3.2.0.tgz#52f3a109bef06080e3b1e3ae7ea1c014ce859897"
|
||||
@ -5299,6 +5328,11 @@ atob@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a"
|
||||
integrity sha1-ri1acpR38onWDdf5amMUoi3Wwio=
|
||||
|
||||
atob@^2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||
|
||||
autoprefixer@^8.0.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-8.1.0.tgz#374cf35be1c0e8fce97408d876f95f66f5cb4641"
|
||||
@ -8492,6 +8526,11 @@ css-what@2.1:
|
||||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
|
||||
integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==
|
||||
|
||||
css.escape@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
|
||||
integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=
|
||||
|
||||
css@2.X, css@^2.0.0, css@^2.2.1:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/css/-/css-2.2.3.tgz#f861f4ba61e79bedc962aa548e5780fd95cbc6be"
|
||||
@ -8502,6 +8541,15 @@ css@2.X, css@^2.0.0, css@^2.2.1:
|
||||
source-map-resolve "^0.5.1"
|
||||
urix "^0.1.0"
|
||||
|
||||
css@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d"
|
||||
integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==
|
||||
dependencies:
|
||||
inherits "^2.0.4"
|
||||
source-map "^0.6.1"
|
||||
source-map-resolve "^0.6.0"
|
||||
|
||||
cssesc@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
||||
@ -15490,7 +15538,7 @@ jest-config@^26.6.3:
|
||||
micromatch "^4.0.2"
|
||||
pretty-format "^26.6.2"
|
||||
|
||||
jest-diff@^26.6.2:
|
||||
jest-diff@^26.0.0, jest-diff@^26.6.2:
|
||||
version "26.6.2"
|
||||
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394"
|
||||
integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==
|
||||
@ -20905,7 +20953,7 @@ pretty-format@^25.5.0:
|
||||
ansi-styles "^4.0.0"
|
||||
react-is "^16.12.0"
|
||||
|
||||
pretty-format@^26.6.2:
|
||||
pretty-format@^26.0.0, pretty-format@^26.6.2:
|
||||
version "26.6.2"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93"
|
||||
integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==
|
||||
@ -23984,6 +24032,14 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.1:
|
||||
source-map-url "^0.4.0"
|
||||
urix "^0.1.0"
|
||||
|
||||
source-map-resolve@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2"
|
||||
integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==
|
||||
dependencies:
|
||||
atob "^2.1.2"
|
||||
decode-uri-component "^0.2.0"
|
||||
|
||||
source-map-support@0.5.12:
|
||||
version "0.5.12"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
|
||||
|
Loading…
Reference in New Issue
Block a user