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
feature/default_network_editable
Daniel 4 years ago committed by GitHub
parent d01bc9bb51
commit fbbdaf04ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      .eslintrc.js
  2. 9
      jest.config.js
  3. 4
      package.json
  4. 4
      test/jest/index.js
  5. 69
      test/jest/mock-store.js
  6. 59
      test/jest/rendering.js
  7. 2
      test/jest/setup.js
  8. 6
      ui/app/__mocks__/react-router-dom.js
  9. 16
      ui/app/pages/swaps/actionable-message/__snapshots__/actionable-message.test.js.snap
  10. 2
      ui/app/pages/swaps/actionable-message/actionable-message.js
  11. 22
      ui/app/pages/swaps/actionable-message/actionable-message.test.js
  12. 45
      ui/app/pages/swaps/awaiting-swap/__snapshots__/awaiting-swap.test.js.snap
  13. 37
      ui/app/pages/swaps/awaiting-swap/awaiting-swap.test.js
  14. 1
      ui/app/pages/swaps/countdown-timer/countdown-timer.js
  15. 31
      ui/app/pages/swaps/countdown-timer/countdown-timer.test.js
  16. 20
      ui/app/pages/swaps/dropdown-input-pair/__snapshots__/dropdown-input-pair.test.js.snap
  17. 23
      ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.test.js
  18. 40
      ui/app/pages/swaps/dropdown-search-list/__snapshots__/dropdown-search-list.test.js.snap
  19. 25
      ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.test.js
  20. 45
      ui/app/pages/swaps/exchange-rate-display/__snapshots__/exchange-rate-display.test.js.snap
  21. 28
      ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.test.js
  22. 117
      ui/app/pages/swaps/fee-card/__snapshots__/fee-card.test.js.snap
  23. 46
      ui/app/pages/swaps/fee-card/fee-card.test.js
  24. 9
      ui/app/pages/swaps/intro-popup/__snapshots__/intro-popup.test.js.snap
  25. 24
      ui/app/pages/swaps/intro-popup/intro-popup.test.js
  26. 109
      ui/app/pages/swaps/main-quote-summary/__snapshots__/main-quote-summary.test.js.snap
  27. 39
      ui/app/pages/swaps/main-quote-summary/main-quote-summary.test.js
  28. 77
      ui/app/pages/swaps/searchable-item-list/__snapshots__/searchable-item-list.test.js.snap
  29. 60
      ui/app/pages/swaps/searchable-item-list/searchable-item-list.test.js
  30. 9
      ui/app/pages/swaps/select-quote-popover/__snapshots__/select-quote-popover.test.js.snap
  31. 24
      ui/app/pages/swaps/select-quote-popover/select-quote-popover.test.js
  32. 42
      ui/app/pages/swaps/slippage-buttons/__snapshots__/slippage-buttons.test.js.snap
  33. 31
      ui/app/pages/swaps/slippage-buttons/slippage-buttons.test.js
  34. 41
      ui/app/pages/swaps/swaps-footer/__snapshots__/swaps-footer.test.js.snap
  35. 28
      ui/app/pages/swaps/swaps-footer/swaps-footer.test.js
  36. 60
      yarn.lock

@ -70,7 +70,7 @@ module.exports = {
}, },
overrides: [ overrides: [
{ {
files: ['ui/**/*.js', 'test/lib/render-helpers.js'], files: ['ui/**/*.js', 'test/lib/render-helpers.js', 'test/jest/*.js'],
plugins: ['react'], plugins: ['react'],
extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'], extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'],
rules: { rules: {
@ -108,17 +108,28 @@ module.exports = {
}, },
{ {
files: ['**/*.test.js'], files: ['**/*.test.js'],
excludedFiles: ['ui/**/*.test.js'], excludedFiles: ['ui/**/*.test.js', 'ui/app/__mocks__/*.js'],
extends: ['@metamask/eslint-config-mocha'], extends: ['@metamask/eslint-config-mocha'],
rules: { rules: {
'mocha/no-setup-in-describe': 'off', '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'], extends: ['@metamask/eslint-config-jest'],
rules: { rules: {
'jest/no-restricted-matchers': 'off', 'jest/no-restricted-matchers': 'off',
'import/unambiguous': 'off',
}, },
}, },
{ {

@ -3,12 +3,13 @@ module.exports = {
coverageDirectory: 'jest-coverage/', coverageDirectory: 'jest-coverage/',
coverageThreshold: { coverageThreshold: {
global: { global: {
branches: 6.94, branches: 21.24,
functions: 8.85, functions: 23.01,
lines: 11.76, lines: 27.19,
statements: 11.78, statements: 27.07,
}, },
}, },
setupFiles: ['./test/setup.js', './test/env.js'], setupFiles: ['./test/setup.js', './test/env.js'],
setupFilesAfterEnv: ['./test/jest/setup.js'],
testMatch: ['**/ui/**/?(*.)+(test).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:global": "mocha --exit --require test/env.js --require test/setup.js --recursive test/unit-global/*.test.js",
"test:unit:jest": "jest", "test:unit:jest": "jest",
"test:unit:jest:watch": "jest --watch", "test:unit:jest:watch": "jest --watch",
"test:unit:jest:watch:silent": "jest --watch --silent",
"test:unit:jest:ci": "jest --maxWorkers=2", "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: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'", "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", "test:coverage:path": "nyc --check-coverage yarn test:unit:path",
"ganache:start": "./development/run-ganache.sh", "ganache:start": "./development/run-ganache.sh",
"sentry:publish": "node ./development/sentry-publish.js", "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: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": "{ 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", "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/core": "^6.1.17",
"@storybook/react": "^6.1.17", "@storybook/react": "^6.1.17",
"@storybook/storybook-deployer": "^2.8.7", "@storybook/storybook-deployer": "^2.8.7",
"@testing-library/jest-dom": "^5.11.10",
"@testing-library/react": "^10.4.8", "@testing-library/react": "^10.4.8",
"@testing-library/react-hooks": "^3.2.1", "@testing-library/react-hooks": "^3.2.1",
"@types/react": "^16.9.53", "@types/react": "^16.9.53",

@ -0,0 +1,4 @@
import { createSwapsMockStore } from './mock-store';
import { renderWithProvider } from './rendering';
export { createSwapsMockStore, renderWithProvider };

@ -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,
},
},
};
};

@ -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 });
}

@ -0,0 +1,2 @@
// jest-setup.js is for Jest-specific setup only and runs before our Jest tests.
import '@testing-library/jest-dom';

@ -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, className: PropTypes.string,
type: PropTypes.string, type: PropTypes.string,
withRightButton: PropTypes.boolean, withRightButton: PropTypes.bool,
infoTooltipText: PropTypes.string, 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>
`;

@ -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 ( return (
<div className="countdown-timer"> <div className="countdown-timer">
<div <div
data-testid="countdown-timer__timer-container"
className={classnames('countdown-timer__timer-container', { className={classnames('countdown-timer__timer-container', {
'countdown-timer__timer-container--warning': 'countdown-timer__timer-container--warning':
warningTime && timeBelowWarningTime(timer, warningTime), warningTime && timeBelowWarningTime(timer, warningTime),

@ -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,10 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FeeCard renders the component with initial props 1`] = ` exports[`FeeCard renders the component with initial props 1`] = `
<div>
<div
class="fee-card"
>
<div <div
class="fee-card__savings-and-quotes-header" class="fee-card__savings-and-quotes-header"
> >
@ -14,7 +10,7 @@ exports[`FeeCard renders the component with initial props 1`] = `
<p <p
class="fee-card__savings-text" class="fee-card__savings-text"
> >
[swapUsingBestQuote] Using the best quote
</p> </p>
<div <div
class="fee-card__quote-link-container" class="fee-card__quote-link-container"
@ -22,7 +18,7 @@ exports[`FeeCard renders the component with initial props 1`] = `
<p <p
class="fee-card__quote-link-text" class="fee-card__quote-link-text"
> >
[swapNQuotes] 6 quotes
</p> </p>
<div <div
class="fee-card__caret-right" class="fee-card__caret-right"
@ -34,107 +30,9 @@ exports[`FeeCard renders the component with initial props 1`] = `
</div> </div>
</div> </div>
</div> </div>
<div `;
class="fee-card__main"
> exports[`FeeCard renders the component with initial props 2`] = `
<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"
>
<div
class="fee-card__row-label"
>
<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 <div
class="fee-card__top-bordered-row" class="fee-card__top-bordered-row"
> >
@ -144,7 +42,7 @@ exports[`FeeCard renders the component with initial props 1`] = `
<div <div
class="fee-card__row-header-text" class="fee-card__row-header-text"
> >
[swapQuoteIncludesRate] Quote includes a 0.875% MetaMask fee
</div> </div>
<div <div
class="info-tooltip" class="info-tooltip"
@ -169,7 +67,4 @@ exports[`FeeCard renders the component with initial props 1`] = `
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
</div>
`; `;

@ -1,17 +1,29 @@
import React from 'react'; import React from 'react';
import { render } from '@testing-library/react';
import { renderWithProvider } from '../../../../../test/jest';
import { MAINNET_CHAIN_ID } from '../../../../../shared/constants/network'; import { MAINNET_CHAIN_ID } from '../../../../../shared/constants/network';
import FeeCard from './fee-card'; import FeeCard from '.';
describe('FeeCard', () => {
const createProps = (customProps = {}) => { const createProps = (customProps = {}) => {
return { return {
primaryFee: '1 ETH', primaryFee: {
secondaryFee: '2500 USD', fee: '0.0441 ETH',
maxFee: '0.04851 ETH',
},
secondaryFee: {
fee: '$101.98',
maxFee: '$112.17',
},
hideTokenApprovalRow: false, hideTokenApprovalRow: false,
onFeeCardMaxRowClick: jest.fn(), onFeeCardMaxRowClick: jest.fn(),
tokenApprovalTextComponent: <></>, tokenApprovalTextComponent: (
<span
key="swaps-view-quote-approve-symbol-1"
className="view-quote__bold"
>
ABC
</span>
),
tokenApprovalSourceTokenSymbol: 'ABC', tokenApprovalSourceTokenSymbol: 'ABC',
onTokenApprovalClick: jest.fn(), onTokenApprovalClick: jest.fn(),
metaMaskFee: '0.875', metaMaskFee: '0.875',
@ -24,8 +36,26 @@ describe('FeeCard', () => {
}; };
}; };
describe('FeeCard', () => {
it('renders the component with initial props', () => { it('renders the component with initial props', () => {
const { container } = render(<FeeCard {...createProps()} />); const props = createProps();
expect(container).toMatchSnapshot(); 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>
`;

@ -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>
`;

@ -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>
`;

@ -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();
});
});

@ -3522,6 +3522,20 @@
dom-accessibility-api "^0.5.0" dom-accessibility-api "^0.5.0"
pretty-format "^25.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": "@testing-library/react-hooks@^3.2.1":
version "3.2.1" version "3.2.1"
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-3.2.1.tgz#19b6caa048ef15faa69d439c469033873ea01294" resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-3.2.1.tgz#19b6caa048ef15faa69d439c469033873ea01294"
@ -3720,6 +3734,14 @@
dependencies: dependencies:
"@types/istanbul-lib-report" "*" "@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": "@types/json-schema@^7.0.3":
version "7.0.7" version "7.0.7"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" 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" resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74"
integrity sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA== 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": "@types/testing-library__react-hooks@^3.0.0":
version "3.2.0" version "3.2.0"
resolved "https://registry.yarnpkg.com/@types/testing-library__react-hooks/-/testing-library__react-hooks-3.2.0.tgz#52f3a109bef06080e3b1e3ae7ea1c014ce859897" 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" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a"
integrity sha1-ri1acpR38onWDdf5amMUoi3Wwio= 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: autoprefixer@^8.0.0:
version "8.1.0" version "8.1.0"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-8.1.0.tgz#374cf35be1c0e8fce97408d876f95f66f5cb4641" 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" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== 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: css@2.X, css@^2.0.0, css@^2.2.1:
version "2.2.3" version "2.2.3"
resolved "https://registry.yarnpkg.com/css/-/css-2.2.3.tgz#f861f4ba61e79bedc962aa548e5780fd95cbc6be" 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" source-map-resolve "^0.5.1"
urix "^0.1.0" 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: cssesc@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" 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" micromatch "^4.0.2"
pretty-format "^26.6.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" version "26.6.2"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394"
integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==
@ -20905,7 +20953,7 @@ pretty-format@^25.5.0:
ansi-styles "^4.0.0" ansi-styles "^4.0.0"
react-is "^16.12.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" version "26.6.2"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93"
integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== 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" source-map-url "^0.4.0"
urix "^0.1.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: source-map-support@0.5.12:
version "0.5.12" version "0.5.12"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"

Loading…
Cancel
Save