Cypress (#734)
* Add some basic integration tests and CI in GitHub * Add push trigger * Add badge for tests to readme * Unit tests * Just use the development infura URL in the tests * Remove unused webpack config * Make integration test run on the same port as yarn start * make test a little bit better * rename describe
This commit is contained in:
parent
a1a9d9f041
commit
28b24036c6
4
.env
Normal file
4
.env
Normal file
@ -0,0 +1,4 @@
|
||||
REACT_APP_CHAIN_ID="1"
|
||||
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/b8800ce81b8c451698081d269b86692b"
|
||||
REACT_APP_PORTIS_ID=""
|
||||
REACT_APP_FORTMATIC_KEY=""
|
34
.github/workflows/tests.yaml
vendored
Normal file
34
.github/workflows/tests.yaml
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
name: Tests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- v2
|
||||
pull_request:
|
||||
branches:
|
||||
- v2
|
||||
jobs:
|
||||
integration-tests:
|
||||
name: Integration tests
|
||||
runs-on: ubuntu-16.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12'
|
||||
- run: yarn
|
||||
- run: yarn integration-test
|
||||
|
||||
unit-tests:
|
||||
name: Unit tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12'
|
||||
- run: yarn
|
||||
- run: yarn test
|
||||
|
||||
# todo: add job for typescript linting
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -11,7 +11,6 @@
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
@ -29,3 +28,6 @@ notes.txt
|
||||
.vscode/
|
||||
|
||||
package-lock.json
|
||||
|
||||
cypress/videos
|
||||
cypress/screenshots
|
13
.travis.yml
13
.travis.yml
@ -1,13 +0,0 @@
|
||||
branches:
|
||||
except:
|
||||
- master
|
||||
language: node_js
|
||||
node_js:
|
||||
- '10'
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
install: yarn
|
||||
script:
|
||||
- yarn check:all
|
||||
- yarn build
|
@ -1,7 +1,7 @@
|
||||
# Uniswap Frontend
|
||||
|
||||
[![Netlify Status](https://api.netlify.com/api/v1/badges/fa110555-b3c7-4eeb-b840-88a835009c62/deploy-status)](https://app.netlify.com/sites/uniswap/deploys)
|
||||
[![Build Status](https://travis-ci.org/Uniswap/uniswap-frontend.svg)](https://travis-ci.org/Uniswap/uniswap-frontend)
|
||||
[![Tests](https://github.com/Uniswap/uniswap-frontend/workflows/Tests/badge.svg?branch=v2)](https://github.com/Uniswap/uniswap-frontend/actions?query=workflow%3ATests)
|
||||
[![Styled With Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://prettier.io/)
|
||||
|
||||
This an an open source interface for Uniswap - a protocol for decentralized exchange of Ethereum tokens.
|
||||
|
3
cypress.json
Normal file
3
cypress.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"baseUrl": "http://localhost:3000"
|
||||
}
|
18
cypress/integration/no-connect.ts
Normal file
18
cypress/integration/no-connect.ts
Normal file
@ -0,0 +1,18 @@
|
||||
describe('Homepage', () => {
|
||||
beforeEach(() => cy.visit('/'))
|
||||
it('loads exchange page', () => {
|
||||
cy.get('#exchangePage')
|
||||
})
|
||||
|
||||
it('has url /swap', () => {
|
||||
cy.url().should('include', '/swap')
|
||||
})
|
||||
|
||||
it('can enter an amount into input', () => {
|
||||
cy.get('#swapInputField').type('0.001')
|
||||
})
|
||||
|
||||
it('can enter an amount into output', () => {
|
||||
cy.get('#swapOutputField').type('0.001')
|
||||
})
|
||||
})
|
21
cypress/plugins/index.js
Normal file
21
cypress/plugins/index.js
Normal file
@ -0,0 +1,21 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
27
cypress/support/commands.ts
Normal file
27
cypress/support/commands.ts
Normal file
@ -0,0 +1,27 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add("login", (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
||||
|
||||
// TODO(moodysalem): commands for connecting a mock ethereum provider.
|
20
cypress/support/index.ts
Normal file
20
cypress/support/index.ts
Normal file
@ -0,0 +1,20 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.ts is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.ts using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
17
cypress/tsconfig.json
Normal file
17
cypress/tsconfig.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"baseUrl": "../node_modules",
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"es5",
|
||||
"dom"
|
||||
],
|
||||
"types": [
|
||||
"cypress"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
]
|
||||
}
|
@ -56,7 +56,10 @@
|
||||
"@types/react": "^16.9.34",
|
||||
"@types/react-dom": "^16.9.7",
|
||||
"@types/styled-components": "^4.2.0",
|
||||
"cypress": "^4.5.0",
|
||||
"prettier": "^1.17.0",
|
||||
"serve": "^11.3.0",
|
||||
"start-server-and-test": "^1.11.0",
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"scripts": {
|
||||
@ -71,7 +74,10 @@
|
||||
"fix:all": "yarn fix:lint && yarn fix:format",
|
||||
"check:lint": "yarn lint:base",
|
||||
"check:format": "yarn format:base --check",
|
||||
"check:all": "yarn check:lint && yarn check:format"
|
||||
"check:all": "yarn check:lint && yarn check:format",
|
||||
"cy:run": "cypress run",
|
||||
"serve:build": "serve -s build -l 3000",
|
||||
"integration-test": "yarn build && start-server-and-test 'yarn run serve:build' http://localhost:3000 cy:run"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
|
@ -151,7 +151,8 @@ export default function CurrencyInputPanel({
|
||||
hideInput = false,
|
||||
showSendWithSwap = false,
|
||||
otherSelectedTokenAddress = null,
|
||||
advanced = false
|
||||
advanced = false,
|
||||
inputId,
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@ -195,6 +196,7 @@ export default function CurrencyInputPanel({
|
||||
<>
|
||||
<NumericalInput
|
||||
value={value}
|
||||
id={inputId}
|
||||
onUserInput={val => {
|
||||
onUserInput(field, val)
|
||||
}}
|
||||
|
@ -940,7 +940,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Wrapper id="exchangePage">
|
||||
<ConfirmationModal
|
||||
isOpen={showConfirm}
|
||||
title={sendingWithSwap ? 'Confirm swap and send' : sending ? 'Confirm Send' : 'Confirm Swap'}
|
||||
@ -985,6 +985,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
|
||||
showSendWithSwap={true}
|
||||
advanced={advanced}
|
||||
label={''}
|
||||
inputId="swapInputField"
|
||||
otherSelectedTokenAddress={tokens[Field.OUTPUT]?.address}
|
||||
/>
|
||||
</InputGroup>
|
||||
@ -1008,6 +1009,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
|
||||
}}
|
||||
onTokenSelection={address => onTokenSelection(Field.INPUT, address)}
|
||||
otherSelectedTokenAddress={tokens[Field.OUTPUT]?.address}
|
||||
inputId="swapInputField"
|
||||
/>
|
||||
{sendingWithSwap ? (
|
||||
<ColumnCenter>
|
||||
@ -1048,6 +1050,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
|
||||
pair={pair}
|
||||
advanced={advanced}
|
||||
otherSelectedTokenAddress={tokens[Field.INPUT]?.address}
|
||||
inputId="swapOutputField"
|
||||
/>
|
||||
{sendingWithSwap && (
|
||||
<RowBetween padding="0 12px">
|
||||
|
@ -722,6 +722,7 @@ function AddLiquidity({ token0, token1, step = false }) {
|
||||
error={inputError}
|
||||
pair={pair}
|
||||
label="Input"
|
||||
inputId="addLiquidityInput"
|
||||
/>
|
||||
<ColumnCenter>
|
||||
<Plus size="16" color="#888D9B" />
|
||||
@ -738,6 +739,7 @@ function AddLiquidity({ token0, token1, step = false }) {
|
||||
onTokenSelection={address => onTokenSelection(Field.OUTPUT, address)}
|
||||
error={outputError}
|
||||
pair={pair}
|
||||
inputId="addLiquidityOutput"
|
||||
/>
|
||||
{tokens[Field.OUTPUT] && tokens[Field.INPUT] && (
|
||||
<LightCard padding="1rem" borderRadius={'20px'}>
|
||||
|
@ -704,6 +704,7 @@ export default function RemoveLiquidity({ token0, token1 }) {
|
||||
token={pair?.liquidityToken}
|
||||
isExchange={true}
|
||||
pair={pair}
|
||||
inputId="liquidityAmount"
|
||||
/>
|
||||
<ColumnCenter>
|
||||
<ArrowDown size="16" color="#888D9B"/>
|
||||
@ -718,6 +719,7 @@ export default function RemoveLiquidity({ token0, token1 }) {
|
||||
error={inputError}
|
||||
label={'Output'}
|
||||
disableTokenSelect
|
||||
inputId="removeLiquidityToken0"
|
||||
/>
|
||||
<ColumnCenter>
|
||||
<Plus size="16" color="#888D9B"/>
|
||||
@ -732,6 +734,7 @@ export default function RemoveLiquidity({ token0, token1 }) {
|
||||
error={outputError}
|
||||
label={'Output'}
|
||||
disableTokenSelect
|
||||
inputId="removeLiquidityToken1"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
12
src/utils/index.test.ts
Normal file
12
src/utils/index.test.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { getEtherscanLink } from './index'
|
||||
|
||||
describe('utils', () => {
|
||||
describe('#getEtherscanLink', () => {
|
||||
it('correct for tx', () => {
|
||||
expect(getEtherscanLink(1, 'abc', 'transaction')).toEqual('https://etherscan.io/tx/abc')
|
||||
})
|
||||
it('correct for address', () => {
|
||||
expect(getEtherscanLink(1, 'abc', 'address')).toEqual('https://etherscan.io/address/abc')
|
||||
})
|
||||
})
|
||||
})
|
@ -34,7 +34,7 @@ const ETHERSCAN_PREFIXES = {
|
||||
42: 'kovan.'
|
||||
}
|
||||
|
||||
export function getEtherscanLink(networkId, data, type) {
|
||||
export function getEtherscanLink(networkId: 1 | 3 | 4 | 5 | 42 | any, data: string, type: 'transaction' | 'address') {
|
||||
const prefix = `https://${ETHERSCAN_PREFIXES[networkId] || ETHERSCAN_PREFIXES[1]}etherscan.io`
|
||||
|
||||
switch (type) {
|
||||
|
@ -21,7 +21,8 @@
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
"node_modules",
|
||||
"cypress"
|
||||
],
|
||||
"include": [
|
||||
"**/*.js",
|
||||
|
@ -1,9 +0,0 @@
|
||||
module.exports = {
|
||||
entry: [
|
||||
path.join(process.cwd(), 'app/app.tsx'), // or whatever the path of your root file is
|
||||
]
|
||||
module: {
|
||||
rules:[{ test: /\.tsx?$/, loader: 'awesome-typescript-loader' }], // other loader configuration goes in the array
|
||||
resolve: {extensions: ['.js', '.jsx', '.react.js', '.ts', '.tsx']}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user