From fbbdaf04ed6b3a7cab4d09ec3d4de950f10490c5 Mon Sep 17 00:00:00 2001
From: Daniel <80175477+dan437@users.noreply.github.com>
Date: Wed, 21 Apr 2021 12:34:35 -0700
Subject: [PATCH] Increase Jest unit test coverage for the Swaps feature to
~25% (#10900)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 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
---
.eslintrc.js | 17 +-
jest.config.js | 9 +-
package.json | 4 +-
test/jest/index.js | 4 +
test/jest/mock-store.js | 69 ++++++
test/jest/rendering.js | 59 ++++++
test/jest/setup.js | 2 +
ui/app/__mocks__/react-router-dom.js | 6 +
.../actionable-message.test.js.snap | 16 ++
.../actionable-message/actionable-message.js | 2 +-
.../actionable-message.test.js | 22 ++
.../__snapshots__/awaiting-swap.test.js.snap | 45 ++++
.../swaps/awaiting-swap/awaiting-swap.test.js | 37 ++++
.../swaps/countdown-timer/countdown-timer.js | 1 +
.../countdown-timer/countdown-timer.test.js | 31 +++
.../dropdown-input-pair.test.js.snap | 20 ++
.../dropdown-input-pair.test.js | 23 ++
.../dropdown-search-list.test.js.snap | 40 ++++
.../dropdown-search-list.test.js | 25 +++
.../exchange-rate-display.test.js.snap | 45 ++++
.../exchange-rate-display.test.js | 28 +++
.../__snapshots__/fee-card.test.js.snap | 199 +++++-------------
ui/app/pages/swaps/fee-card/fee-card.test.js | 74 +++++--
.../__snapshots__/intro-popup.test.js.snap | 9 +
.../swaps/intro-popup/intro-popup.test.js | 24 +++
.../main-quote-summary.test.js.snap | 109 ++++++++++
.../main-quote-summary.test.js | 39 ++++
.../searchable-item-list.test.js.snap | 77 +++++++
.../searchable-item-list.test.js | 60 ++++++
.../select-quote-popover.test.js.snap | 9 +
.../select-quote-popover.test.js | 24 +++
.../slippage-buttons.test.js.snap | 42 ++++
.../slippage-buttons/slippage-buttons.test.js | 31 +++
.../__snapshots__/swaps-footer.test.js.snap | 41 ++++
.../swaps/swaps-footer/swaps-footer.test.js | 28 +++
yarn.lock | 60 +++++-
36 files changed, 1146 insertions(+), 185 deletions(-)
create mode 100644 test/jest/index.js
create mode 100644 test/jest/mock-store.js
create mode 100644 test/jest/rendering.js
create mode 100644 test/jest/setup.js
create mode 100644 ui/app/__mocks__/react-router-dom.js
create mode 100644 ui/app/pages/swaps/actionable-message/__snapshots__/actionable-message.test.js.snap
create mode 100644 ui/app/pages/swaps/actionable-message/actionable-message.test.js
create mode 100644 ui/app/pages/swaps/awaiting-swap/__snapshots__/awaiting-swap.test.js.snap
create mode 100644 ui/app/pages/swaps/awaiting-swap/awaiting-swap.test.js
create mode 100644 ui/app/pages/swaps/countdown-timer/countdown-timer.test.js
create mode 100644 ui/app/pages/swaps/dropdown-input-pair/__snapshots__/dropdown-input-pair.test.js.snap
create mode 100644 ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.test.js
create mode 100644 ui/app/pages/swaps/dropdown-search-list/__snapshots__/dropdown-search-list.test.js.snap
create mode 100644 ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.test.js
create mode 100644 ui/app/pages/swaps/exchange-rate-display/__snapshots__/exchange-rate-display.test.js.snap
create mode 100644 ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.test.js
create mode 100644 ui/app/pages/swaps/intro-popup/__snapshots__/intro-popup.test.js.snap
create mode 100644 ui/app/pages/swaps/intro-popup/intro-popup.test.js
create mode 100644 ui/app/pages/swaps/main-quote-summary/__snapshots__/main-quote-summary.test.js.snap
create mode 100644 ui/app/pages/swaps/main-quote-summary/main-quote-summary.test.js
create mode 100644 ui/app/pages/swaps/searchable-item-list/__snapshots__/searchable-item-list.test.js.snap
create mode 100644 ui/app/pages/swaps/searchable-item-list/searchable-item-list.test.js
create mode 100644 ui/app/pages/swaps/select-quote-popover/__snapshots__/select-quote-popover.test.js.snap
create mode 100644 ui/app/pages/swaps/select-quote-popover/select-quote-popover.test.js
create mode 100644 ui/app/pages/swaps/slippage-buttons/__snapshots__/slippage-buttons.test.js.snap
create mode 100644 ui/app/pages/swaps/slippage-buttons/slippage-buttons.test.js
create mode 100644 ui/app/pages/swaps/swaps-footer/__snapshots__/swaps-footer.test.js.snap
create mode 100644 ui/app/pages/swaps/swaps-footer/swaps-footer.test.js
diff --git a/.eslintrc.js b/.eslintrc.js
index 6fa28872a..b764ad39c 100644
--- a/.eslintrc.js
+++ b/.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',
},
},
{
diff --git a/jest.config.js b/jest.config.js
index c788b29f6..9b3dc4459 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -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'],
};
diff --git a/package.json b/package.json
index d9504c93e..72eeba7ad 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/test/jest/index.js b/test/jest/index.js
new file mode 100644
index 000000000..be8cd13bf
--- /dev/null
+++ b/test/jest/index.js
@@ -0,0 +1,4 @@
+import { createSwapsMockStore } from './mock-store';
+import { renderWithProvider } from './rendering';
+
+export { createSwapsMockStore, renderWithProvider };
diff --git a/test/jest/mock-store.js b/test/jest/mock-store.js
new file mode 100644
index 000000000..a90ada6d7
--- /dev/null
+++ b/test/jest/mock-store.js
@@ -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,
+ },
+ },
+ };
+};
diff --git a/test/jest/rendering.js b/test/jest/rendering.js
new file mode 100644
index 000000000..d215cbc0d
--- /dev/null
+++ b/test/jest/rendering.js
@@ -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 (
+
+ Using the best quote +
+ 6 quotes +
- [swapUsingBestQuote] -
-- [swapNQuotes] -
-