New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Increase Jest unit test coverage for the Swaps feature to ~43% #10934
Changes from all commits
427f733
f1f938c
3a1d34b
fbb5473
5ad663e
3fc0ff7
d9c8a01
9d7d156
d52b147
49915bd
87b907e
9aa65f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,7 +33,7 @@ | |
"test:e2e:firefox": "SELENIUM_BROWSER=firefox test/e2e/run-all.sh", | ||
"test:e2e:firefox:metrics": "SELENIUM_BROWSER=firefox mocha test/e2e/metrics.spec.js", | ||
"test:coverage": "nyc --silent --check-coverage yarn test:unit:strict && nyc --silent --no-clean yarn test:unit:lax && nyc report --reporter=text --reporter=html", | ||
"test:coverage:jest": "jest --coverage --maxWorkers=2 --collectCoverageFrom=**/ui/app/**/swaps/**", | ||
"test:coverage:jest": "jest --coverage --maxWorkers=2", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why the removal of the collectCoverageFrom flag There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
"test:coverage:strict": "nyc --check-coverage yarn test:unit:strict", | ||
"test:coverage:path": "nyc --check-coverage yarn test:unit:path", | ||
"ganache:start": "./development/run-ganache.sh", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import * as actions from '../../ui/app/store/actions'; | ||
|
||
export const setBackgroundConnection = (backgroundConnection = {}) => { | ||
actions._setBackgroundConnection(backgroundConnection); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const METASWAP_BASE_URL = 'https://api.metaswap.codefi.network'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import { createSwapsMockStore } from './mock-store'; | ||
import { renderWithProvider } from './rendering'; | ||
|
||
export { createSwapsMockStore, renderWithProvider }; | ||
export { createSwapsMockStore } from './mock-store'; | ||
export { renderWithProvider } from './rendering'; | ||
export { setBackgroundConnection } from './background'; | ||
export * as MOCKS from './mocks'; | ||
export * as CONSTANTS from './constants'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
export const TOP_ASSETS_GET_RESPONSE = [ | ||
{ | ||
symbol: 'LINK', | ||
address: '0x514910771af9ca656af840dff83e8264ecf986ca', | ||
}, | ||
{ | ||
symbol: 'UMA', | ||
address: '0x04fa0d235c4abf4bcf4787af4cf447de572ef828', | ||
}, | ||
{ | ||
symbol: 'YFI', | ||
address: '0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e', | ||
}, | ||
{ | ||
symbol: 'LEND', | ||
address: '0x80fb784b7ed66730e8b1dbd9820afd29931aab03', | ||
}, | ||
{ | ||
symbol: 'SNX', | ||
address: '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f', | ||
}, | ||
]; | ||
|
||
export const REFRESH_TIME_GET_RESPONSE = { | ||
seconds: 3600, | ||
}; | ||
|
||
export const AGGREGATOR_METADATA_GET_RESPONSE = {}; | ||
|
||
export const GAS_PRICES_GET_RESPONSE = { | ||
SafeGasPrice: '10', | ||
ProposeGasPrice: '20', | ||
FastGasPrice: '30', | ||
}; | ||
|
||
export const TOKENS_GET_RESPONSE = [ | ||
{ | ||
erc20: true, | ||
symbol: 'META', | ||
decimals: 18, | ||
address: '0x617b3f8050a0BD94b6b1da02B4384eE5B4DF13F4', | ||
}, | ||
{ | ||
erc20: true, | ||
symbol: 'ZRX', | ||
decimals: 18, | ||
address: '0xE41d2489571d322189246DaFA5ebDe1F4699F498', | ||
}, | ||
{ | ||
erc20: true, | ||
symbol: 'AST', | ||
decimals: 4, | ||
address: '0x27054b13b1B798B345b591a4d22e6562d47eA75a', | ||
}, | ||
{ | ||
erc20: true, | ||
symbol: 'BAT', | ||
decimals: 18, | ||
address: '0x0D8775F648430679A709E98d2b0Cb6250d2887EF', | ||
}, | ||
]; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,9 @@ const originalModule = jest.requireActual('react-router-dom'); | |
module.exports = { | ||
...originalModule, | ||
useHistory: jest.fn(), | ||
useLocation: jest.fn(() => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. presumably when we expand test coverage in our other areas of the repo we'll need to mock this out in those files to override the pathname? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's right. My assumption is that most of the tests will be fine with this path, but if they need to use a different one, they can just do this:
|
||
return { | ||
pathname: '/swaps/build-quote', | ||
}; | ||
}), | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Swap renders the component with initial props 1`] = ` | ||
<div> | ||
<div | ||
class="swaps" | ||
> | ||
<div | ||
class="swaps__container" | ||
> | ||
<div | ||
class="swaps__header" | ||
> | ||
<div | ||
class="swaps__title" | ||
> | ||
Swap | ||
</div> | ||
<div | ||
class="swaps__header-cancel" | ||
> | ||
Cancel | ||
</div> | ||
</div> | ||
<div | ||
class="swaps__content" | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`QuotesTimeoutIcon renders the component 1`] = ` | ||
<div> | ||
<svg | ||
fill="none" | ||
height="44" | ||
viewBox="0 0 44 44" | ||
width="44" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path | ||
d="M22 0C9.96768 0 0.178406 9.78928 0.178406 21.8216C0.178406 33.8539 9.96768 43.6432 22 43.6432C34.0323 43.6432 43.8216 33.8539 43.8216 21.8216C43.8216 9.78929 34.0323 0 22 0ZM22 3.27324C32.2633 3.27324 40.5484 11.5583 40.5484 21.8216C40.5484 32.0849 32.2633 40.3699 22 40.3699C11.7367 40.3699 3.45164 32.0849 3.45164 21.8216C3.45164 11.5583 11.7367 3.27324 22 3.27324ZM22 6.00094C21.0961 6.00094 20.3634 6.73371 20.3634 7.63756V21.8216C20.3634 22.4269 20.6932 22.9534 21.1817 23.2366L32.5187 29.783C33.3014 30.235 34.3001 29.9692 34.752 29.1864C35.2039 28.4036 34.938 27.405 34.1553 26.953L23.6366 20.8839V7.63756C23.6366 6.73371 22.9039 6.00094 22 6.00094Z" | ||
fill="#037DD6" | ||
/> | ||
</svg> | ||
</div> | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`SwapFailureIcon renders the component 1`] = ` | ||
<div> | ||
<svg | ||
fill="none" | ||
height="39" | ||
viewBox="0 0 45 39" | ||
width="45" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path | ||
d="M22.203 0.424438L0.285706 38.2816H44.1203L22.203 0.424438ZM22.203 8.39436L37.2064 34.2966H7.19961L22.203 8.39436ZM20.2105 16.3643V24.3342H24.1955V16.3643H20.2105ZM20.2105 28.3192V32.3041H24.1955V28.3192" | ||
fill="#D73A49" | ||
/> | ||
</svg> | ||
</div> | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`SwapSuccessIcon renders the component 1`] = ` | ||
<div> | ||
<svg | ||
fill="none" | ||
height="38" | ||
viewBox="0 0 38 38" | ||
width="38" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path | ||
d="M34.1429 19C34.1429 23.0161 32.5474 26.8678 29.7076 29.7076C26.8678 32.5474 23.0161 34.1428 19 34.1428C14.9839 34.1428 11.1322 32.5474 8.29238 29.7076C5.45254 26.8678 3.85714 23.0161 3.85714 19C3.85714 14.9838 5.45254 11.1322 8.29238 8.29237C11.1322 5.45253 14.9839 3.85713 19 3.85713C20.4386 3.85713 21.8393 4.06534 23.1643 4.44391L26.1361 1.47213C23.9404 0.563554 21.5364 0.0714111 19 0.0714111C16.5143 0.0714111 14.0529 0.561013 11.7563 1.51226C9.45983 2.46351 7.37316 3.85778 5.61548 5.61546C2.06568 9.16526 0.0714264 13.9798 0.0714264 19C0.0714264 24.0201 2.06568 28.8347 5.61548 32.3845C7.37316 34.1422 9.45983 35.5364 11.7563 36.4877C14.0529 37.4389 16.5143 37.9286 19 37.9286C24.0202 37.9286 28.8347 35.9343 32.3845 32.3845C35.9343 28.8347 37.9286 24.0201 37.9286 19H34.1429ZM11.2582 15.3657L8.58928 18.0536L17.1071 26.5714L36.0357 7.64284L33.3668 4.95498L17.1071 21.2146L11.2582 15.3657Z" | ||
fill="#28A745" | ||
/> | ||
</svg> | ||
</div> | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import React from 'react'; | ||
|
||
import { renderWithProvider } from '../../../../../test/jest'; | ||
import QuotesTimeoutIcon from './quotes-timeout-icon'; | ||
|
||
describe('QuotesTimeoutIcon', () => { | ||
it('renders the component', () => { | ||
const { container } = renderWithProvider(<QuotesTimeoutIcon />); | ||
expect(container).toMatchSnapshot(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import React from 'react'; | ||
|
||
import { renderWithProvider } from '../../../../../test/jest'; | ||
import SwapFailureIcon from './swap-failure-icon'; | ||
|
||
describe('SwapFailureIcon', () => { | ||
it('renders the component', () => { | ||
const { container } = renderWithProvider(<SwapFailureIcon />); | ||
expect(container).toMatchSnapshot(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import React from 'react'; | ||
|
||
import { renderWithProvider } from '../../../../../test/jest'; | ||
import SwapSuccessIcon from './swap-success-icon'; | ||
|
||
describe('SwapSuccessIcon', () => { | ||
it('renders the component', () => { | ||
const { container } = renderWithProvider(<SwapSuccessIcon />); | ||
expect(container).toMatchSnapshot(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`ViewOnEtherScanLink renders the component with a custom block explorer link 1`] = ` | ||
<div> | ||
<div | ||
class="awaiting-swap__view-on-etherscan awaiting-swap__view-on-etherscan--visible" | ||
> | ||
View at custom-blockchain.explorer | ||
</div> | ||
</div> | ||
`; | ||
|
||
exports[`ViewOnEtherScanLink renders the component with initial props 1`] = ` | ||
<div> | ||
<div | ||
class="awaiting-swap__view-on-etherscan awaiting-swap__view-on-etherscan--visible" | ||
> | ||
View on Etherscan | ||
</div> | ||
</div> | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import React from 'react'; | ||
|
||
import { renderWithProvider } from '../../../../../../test/jest'; | ||
import ViewOnEtherScanLink from '.'; | ||
|
||
const createProps = (customProps = {}) => { | ||
return { | ||
txHash: | ||
'0x58e5a0fc7fbc849eddc100d44e86276168a8c7baaa5604e44ba6f5eb8ba1b7eb', | ||
blockExplorerUrl: 'https://block.explorer', | ||
isCustomBlockExplorerUrl: false, | ||
...customProps, | ||
}; | ||
}; | ||
|
||
describe('ViewOnEtherScanLink', () => { | ||
it('renders the component with initial props', () => { | ||
const { container, getByText } = renderWithProvider( | ||
<ViewOnEtherScanLink {...createProps()} />, | ||
); | ||
expect(getByText('View on Etherscan')).toBeInTheDocument(); | ||
expect(container).toMatchSnapshot(); | ||
}); | ||
|
||
it('renders the component with a custom block explorer link', () => { | ||
const { container, getByText } = renderWithProvider( | ||
<ViewOnEtherScanLink | ||
{...createProps({ | ||
blockExplorerUrl: 'https://custom-blockchain.explorer', | ||
isCustomBlockExplorerUrl: true, | ||
})} | ||
/>, | ||
); | ||
expect(getByText('View at custom-blockchain.explorer')).toBeInTheDocument(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible for us to test what the URL will go to here instead of just checking the link text? It'd help to ensure that changes made to the URL but not the text don't pass through our test cases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great point, will add an assertion for a URL. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've checked the code and we don't render a link, but open a new tab via an I will be testing events in following PRs, so I would prefer to do it there. |
||
expect(container).toMatchSnapshot(); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did this get turned off?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great question! That's because I used
module.exports
in the link below: https://github.com/MetaMask/metamask-extension/pull/10934/files#diff-8fd96322fc664541ebc0326e3c5963e55db825809abb977c6ffad8be7555cbd1R7After which I started getting these errors:
I will give it little more time to use
export
instead ofmodule.exports
when re-exporting imported things. Then we hopefully wouldn't need to turnimport/named
off for tests.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I've changed it to
export
only:But even while tests are green, I'm getting the same ESLint issue when re-exporting:
That's why I would prefer to keep
'import/named': 'off',
, just for tests.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks legit. import-js/eslint-plugin-import#1998
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice find!