Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why move this to the root of the project?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried moving it back, but to run cypress locally you need it at the root, or perhaps in apps/cowswap-frontend-e2e.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#######################################
# End To End Test
#######################################
# ⚠️ Required for E2E tests to run

# Cypress Integration Tests
CYPRESS_INTEGRATION_TEST_PRIVATE_KEY=
CYPRESS_INTEGRATION_TESTS_ALCHEMY_KEY=
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ jobs:
working-directory: apps/cowswap-frontend-e2e
env:
CYPRESS_INTEGRATION_TEST_PRIVATE_KEY: ${{ secrets.CYPRESS_INTEGRATION_TEST_PRIVATE_KEY }}
CYPRESS_INTEGRATION_TESTS_INFURA_KEY: ${{ secrets.CYPRESS_INTEGRATION_TESTS_INFURA_KEY }}
CYPRESS_INTEGRATION_TESTS_ALCHEMY_KEY: ${{ secrets.CYPRESS_INTEGRATION_TESTS_ALCHEMY_KEY }}

# - uses: actions/upload-artifact@v3
# if: always()
Expand Down
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,24 +113,27 @@ yarn run cosmos

## Integration test

> ⚠️ To run the tests. Make sure you add the required environment varianbles to
> your `.env.local` file with:
> ⚠️ To run the tests. Make sure you add the required environment variables to
> your root `.env.local` file with:
>
> - `INTEGRATION_TEST_PRIVATE_KEY=<your-private-key>`: Private key
> - `INTEGRATION_TESTS_INFURA_KEY=<your-infura-key>`: Infura key
> - `CYPRESS_INTEGRATION_TEST_PRIVATE_KEY=<your-private-key>`: Private key
> - `CYPRESS_INTEGRATION_TESTS_ALCHEMY_KEY=<your-alchemy-key>`: Alchemy key

To launch it with our development server (so you have live-reloading):

```bash
# Terminal 1
yarn start
# Terminal 2
yarn e2e
```

If we want to use the Cypress UI:
If we want to use the Cypress UI, with the production build:

```bash
yarn build
yarn serve
# Terminal 1
npx nx run cowswap-frontend:serve-static --port 3000
# Terminal 2
yarn e2e:open
```

Expand Down Expand Up @@ -168,7 +171,7 @@ REACT_APP_NETWORK_URL_43114: https://...
Additionally, if you plan to run the integration tests locally you must define:

```ini
INTEGRATION_TESTS_INFURA_KEY: YOUR_INFURA_KEY
INTEGRATION_TESTS_ALCHEMY_KEY: YOUR_ALCHEMY_KEY
INTEGRATION_TESTS_PRIVATE_KEY: YOUR_TEST_WALLET_PRIVATE_KEY
```

Expand Down
22 changes: 21 additions & 1 deletion apps/cowswap-frontend-e2e/cypress.config.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset'
import { defineConfig } from 'cypress'
import macrosPlugin from 'vite-plugin-babel-macros'
import { nodePolyfills } from 'vite-plugin-node-polyfills'
import viteTsConfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
e2e: {
...nxE2EPreset(__dirname, {
bundler: 'vite',
viteConfigOverrides: {
plugins: [
nodePolyfills({
globals: {
Buffer: true,
global: true,
process: true,
},
protocolImports: true,
}),
viteTsConfigPaths({
root: '../../',
}),
macrosPlugin(),
],
},
}),
specPattern: ['src/**/*.test.{js,jsx,ts,tsx}'],
baseUrl: 'http://localhost:3000',
supportFile: 'src/support/index.ts',
video: false,
screenshotOnRunFailure: false,
defaultCommandTimeout: 15_000
defaultCommandTimeout: 5_000,
pageLoadTimeout: 15_000,
},
})
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ describe('Fee endpoint', () => {
})
})

// TODO: disable this test because it's not working - needs to be fixed
describe.skip('Fee: Complex fetch and persist fee', () => {
describe('Fee: Complex fetch and persist fee', () => {
const INPUT_AMOUNT = '0.1'

// Needs to run first to pass because of Cypress async issues between tests
Expand All @@ -96,6 +95,9 @@ describe.skip('Fee: Complex fetch and persist fee', () => {
// GIVEN: user visits app, selects 0.1 WETH as sell, COW as buy
// and goes AFK
cy.visit('/#/11155111/swap')
cy.unlockCrossChainSwap()
cy.swapSelectInput(USDC)
cy.wait(1000)
cy.swapSelectOutput(COW)
cy.swapEnterInputAmount(DEFAULT_SELL_TOKEN, INPUT_AMOUNT)

Expand All @@ -121,8 +123,7 @@ describe.skip('Fee: Complex fetch and persist fee', () => {
})
})

// TODO: disable this test because it's not working - needs to be fixed
describe.skip('Fee: simple checks it exists', () => {
describe('Fee: simple checks it exists', () => {
const INPUT_AMOUNT = '0.1'
const QUOTE_RESP = {
...mockQuoteResponse,
Expand All @@ -141,6 +142,9 @@ describe.skip('Fee: simple checks it exists', () => {
// GIVEN: A user loads the swap page
// WHEN: Select COW token as output and sells 0.1 WETH
cy.visit('/#/11155111/swap')
cy.unlockCrossChainSwap()
cy.swapSelectInput(DEFAULT_SELL_TOKEN)
cy.wait(1000)
cy.swapSelectOutput(COW)
cy.swapEnterInputAmount(DEFAULT_SELL_TOKEN, INPUT_AMOUNT)

Expand All @@ -155,7 +159,7 @@ describe('Swap: Considering fee', () => {
cy.visit('/#/11155111/swap')
})

it("Uses Uniswap price, if there's no tip", () => {
it.skip("Uses Uniswap price, if there's no tip", () => {
// GIVEN: Swap WETH-COW
// TODO: Create command for easy setting up a case (setup current selection)
//
Expand All @@ -167,7 +171,7 @@ describe('Swap: Considering fee', () => {
// THEN: He gets uniswap price
})

it("User can't trade when amount is smaller than minimumFee", () => {
it.skip("User can't trade when amount is smaller than minimumFee", () => {
// GIVEN: Swap WETH-COW
//
// GIVEN: amount is smaller than minimumFee
Expand All @@ -177,7 +181,7 @@ describe('Swap: Considering fee', () => {
// THEN: He cannot trade
})

it('User pays minimumFee for small trades', () => {
it.skip('User pays minimumFee for small trades', () => {
// GIVEN: Swap WETH-COW
//
// GIVEN: amount is bigger than minimumFee, but trade is still small
Expand All @@ -187,7 +191,7 @@ describe('Swap: Considering fee', () => {
// THEN: He gets Uniswap price minus minimal-trade
})

it('User pays more than minimumFee for big trades', () => {
it.skip('User pays more than minimumFee for big trades', () => {
// GIVEN: Swap WETH-COW
//
// GIVEN: amount * "fee factor" is bigger than minimumFee
Expand Down
12 changes: 4 additions & 8 deletions apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
// TODO: Add proper return type annotation
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function getInputFiatAmount() {
function getInputFiatAmount(): Cypress.Chainable {
return cy.get('#input-currency-input .fiat-amount').invoke('text')
}

// TODO: Add proper return type annotation
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function getInputToken() {
function getInputToken(): Cypress.Chainable {
return cy.get('#input-currency-input .token-amount-input').should('be.enabled')
}

Expand All @@ -19,8 +15,8 @@ describe('Fiat amounts', () => {
cy.visit('/#/11155111/swap/WETH/COW')
})

// TODO: disable this test because it's not working - needs to be fixed
it.skip('Should change fiat amount after changing currency amount', () => {
it('Should change fiat amount after changing currency amount', () => {
cy.unlockCrossChainSwap()
getInputToken().type('1')

// Get fiat amount for 1 WETH
Expand Down
25 changes: 8 additions & 17 deletions apps/cowswap-frontend-e2e/src/e2e/limit-orders.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,29 @@ const CHAIN_ID = 11155111
const SELL_TOKEN = 'WETH'
const BUY_TOKEN = 'COW'

// TODO: Add proper return type annotation
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function unlock() {
function unlock(): void {
cy.get('#unlock-limit-orders-btn', { timeout: 10000 }).click()
}

// TODO: Add proper return type annotation
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function navigate(path = '', unlockLimitOrders = true) {
function navigate(path = '', unlockLimitOrders = true): void {
cy.visit(`/#/${CHAIN_ID}/limit${path}`)

if (unlockLimitOrders) {
unlock()
}
}

// TODO: Add proper return type annotation
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function getInputToken() {
function getInputToken(): Cypress.Chainable {
return cy.get('#input-currency-input .token-amount-input').should('be.enabled')
}

// TODO: Add proper return type annotation
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function getOutputToken() {
function getOutputToken(): Cypress.Chainable {
return cy.get('#output-currency-input .token-amount-input').should('be.enabled')
}

// TODO: disable this test because it's not working - needs to be fixed
describe.skip('Limit orders', () => {
it('Confirmation modal must contains values that were entered while creating', () => {
describe('Limit orders', () => {
// TODO: disable this test because it's not working - needs to be fixed
it.skip('Confirmation modal must contains values that were entered while creating', () => {
const inputAmount = 0.1
const rate = 2000000000000
const outputAmount = inputAmount * rate
Expand All @@ -49,7 +41,7 @@ describe.skip('Limit orders', () => {
cy.get('#output-currency-preview .token-amount-input').should('contain.text', '200B')
})

describe.skip('url params', () => {
describe('url params', () => {
it('should accept sellAmount url param', () => {
navigate(`/${SELL_TOKEN}?sellAmount=0.1`)
getInputToken().should('have.value', '0.1')
Expand Down Expand Up @@ -79,7 +71,6 @@ describe.skip('Limit orders', () => {
it('sell amount should be 1 by default', () => {
navigate(`/${SELL_TOKEN}/${BUY_TOKEN}`)
getInputToken().should('have.value', '1')
getOutputToken().should('have.value', '')
})
})
})
Expand Down
4 changes: 2 additions & 2 deletions apps/cowswap-frontend-e2e/src/e2e/lists.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ describe('Lists', () => {
cy.visit('/#/11155111/swap/')
})

// TODO: disable this test because it's not working - needs to be fixed
it.skip('change list', () => {
it('change list', () => {
cy.unlockCrossChainSwap()
cy.get('#output-currency-input .open-currency-select-button', { timeout: 20_000 }).should('be.enabled').click()
cy.get('#list-token-manage-button').click()
cy.get('#tokens-lists-table > div').should('have.length.greaterThan', 0)
Expand Down
18 changes: 11 additions & 7 deletions apps/cowswap-frontend-e2e/src/e2e/search.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// TODO: Add proper return type annotation
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function openTokenSelector() {
function openTokenSelector(): void {
cy.get('.open-currency-select-button').first({ timeout: 20_000 }).should('be.enabled').click()
}

Expand All @@ -9,71 +7,77 @@ it('should be true', () => {
expect(true).to.be.true
})

// TODO: disable this test because it's not working - needs to be fixed
// TODO: Break down this large function into smaller functions

describe.skip('Search', () => {
describe('Search', () => {
beforeEach(() => {
cy.visit('/#/11155111/swap/')
})

it('should be able to find a token by its name', () => {
cy.unlockCrossChainSwap()
openTokenSelector()
cy.get('#token-search-input').type('COW')
cy.get('#currency-list').contains('COW')
cy.get('#currency-list').should('not.contain.text', 'GNO')
})

it('should be able to find a token by its address', () => {
cy.unlockCrossChainSwap()
openTokenSelector()
cy.get('#token-search-input').type('0x0625aFB445C3B6B7B929342a04A22599fd5dBB59')
cy.get('#currency-list').contains('COW')
cy.get('#currency-list').should('not.contain.text', 'GNO')
})

it('should be able to find a token by its address with case errors at the beginning', () => {
cy.unlockCrossChainSwap()
openTokenSelector()
cy.get('#token-search-input').type('0x0625aFB445C3B6B7B929342a04A22599fd5dBB59')
cy.get('#currency-list').contains('COW')
cy.get('#currency-list').should('not.contain.text', 'GNO')
})

it('should be able to find a token by its address with case errors in the address', () => {
cy.unlockCrossChainSwap()
openTokenSelector()
cy.get('#token-search-input').type('0x0625aFB445C3B6B7B929342a04A22599fd5dBB59')
cy.get('#currency-list').contains('COW')
cy.get('#currency-list').should('not.contain.text', 'GNO')
})

it('should be able to find a token by its address without 0x at the start', () => {
cy.unlockCrossChainSwap()
openTokenSelector()
cy.get('#token-search-input').type('0625aFB445C3B6B7B929342a04A22599fd5dBB59')
cy.get('#currency-list').contains('COW')
cy.get('#currency-list').should('not.contain.text', 'GNO')
})

it('should be able to find a token by its address when there is a trailing or leading space', () => {
cy.unlockCrossChainSwap()
openTokenSelector()
cy.get('#token-search-input').type(' 0x0625aFB445C3B6B7B929342a04A22599fd5dBB59 ')
cy.get('#currency-list').contains('COW')
cy.get('#currency-list').should('not.contain.text', 'GNO')
})

it('should be able to find a token by its name when there is a trailing or leading space', () => {
cy.unlockCrossChainSwap()
openTokenSelector()
cy.get('#token-search-input').type(' COW ')
cy.get('#currency-list').contains('COW')
cy.get('#currency-list').should('not.contain.text', 'GNO')
})

it('should not show import when token is in our lists', () => {
cy.unlockCrossChainSwap()
openTokenSelector()
cy.get('#token-search-input').type('0x0625aFB445C3B6B7B929342a04A22599fd5dBB59')
cy.get('#currency-list').contains('COW')
cy.get('#currency-list').should('not.contain.text', 'Import')
})

it('should show import when token is unknown to us', () => {
cy.unlockCrossChainSwap()
openTokenSelector()
cy.get('#token-search-input').type('0x779877A7B0D9E8603169DdbD7836e478b4624789')
cy.get('#currency-import').contains('LINK')
Expand Down
19 changes: 0 additions & 19 deletions apps/cowswap-frontend-e2e/src/e2e/send.test.ts

This file was deleted.

Loading
Loading