diff --git a/.github/actions/setup-nodejs/action.yml b/.github/actions/setup-nodejs/action.yml index 78069873..15b1c0ad 100644 --- a/.github/actions/setup-nodejs/action.yml +++ b/.github/actions/setup-nodejs/action.yml @@ -27,6 +27,6 @@ runs: node-version: ${{ inputs.node-version }} cache: 'pnpm' - - name: Npm install + - name: pnpm install run: pnpm i ${{ inputs.pnpm-install-options }} shell: bash diff --git a/.github/workflows/bridge-ui-e2e-tests.yml b/.github/workflows/bridge-ui-e2e-tests.yml index 42c502cc..b2fd5e49 100644 --- a/.github/workflows/bridge-ui-e2e-tests.yml +++ b/.github/workflows/bridge-ui-e2e-tests.yml @@ -24,28 +24,41 @@ jobs: - name: Checkout uses: actions/checkout@v4 + # Use for testing workflow only (and not publish to Docker) + - uses: actions/cache@v4.2.0 + with: + path: | + ~/.npm + ~/.cache/ms-playwright + ~/_work/.pnpm-store/v3 + ${{ github.workspace }}/bridge-ui/.next/cache + ${{ github.workspace }}/bridge-ui/.cache-synpress + key: ${{ runner.os }}-bridge-ui-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ hashFiles('**/bridge-ui/src/**/*.js', '**/bridge-ui/src/**/*.ts', '**/bridge-ui/src/**/*.tsx') }} + restore-keys: | + ${{ runner.os }}-bridge-ui-${{ hashFiles('**/pnpm-lock.yaml') }}- + - name: Setup nodejs environment uses: ./.github/actions/setup-nodejs with: - node-version: 18.17.0 + node-version: 20.17.0 pnpm-install-options: '--frozen-lockfile --prefer-offline' - name: Install Playwright - run: pnpm dlx playwright@1.45.3 install --with-deps + run: pnpm dlx playwright@1.51.1 install --with-deps chromium - name: Build Bridge UI - run: pnpm run -F bridge-ui build; + run: pnpm run -F bridge-ui build env: NEXT_PUBLIC_WALLET_CONNECT_ID: ${{ secrets.PUBLIC_WALLET_CONNECT_ID }} NEXT_PUBLIC_INFURA_ID: ${{ secrets.PUBLIC_BRIDGE_UI_INFURA_ID }} - NEXT_PUBLIC_DYNAMIC_ENVIRONMENT_ID: ${{ secrets.PUBLIC_DYNAMIC_ENVIRONMENT_ID }} + NEXT_PUBLIC_DYNAMIC_ENVIRONMENT_ID: ${{ secrets.PUBLIC_DYNAMIC_SANDBOX_ENVIRONMENT_ID }} NEXT_PUBLIC_LIFI_API_KEY: ${{ secrets.PUBLIC_LIFI_API_KEY }} - name: Install linux dependencies run: | sudo apt-get install --no-install-recommends -y xvfb - - name: Build synpress cache + - name: Initialize Metamask testing fixture run: xvfb-run pnpm run -F bridge-ui build:cache env: E2E_TEST_PRIVATE_KEY: ${{ secrets.BRIDGE_UI_E2E_TESTS_PRIVATE_KEY }} @@ -53,9 +66,21 @@ jobs: E2E_TEST_WALLET_PASSWORD: "TestPassword!" NEXT_PUBLIC_INFURA_ID: ${{ secrets.PUBLIC_BRIDGE_UI_INFURA_ID }} - - name: Run tests + - name: Run unit tests + run: DOTENV_CONFIG_PATH=.env.production pnpm run -F bridge-ui test:unit + env: + # Can run unit tests in parallel + CI: "false" + NEXT_PUBLIC_INFURA_ID: ${{ secrets.PUBLIC_BRIDGE_UI_INFURA_ID }} + NEXT_PUBLIC_LIFI_API_KEY: "placeholder" + NEXT_PUBLIC_WALLET_CONNECT_ID: "placeholder" + NEXT_PUBLIC_DYNAMIC_ENVIRONMENT_ID: "placeholder" + + # Prerequisite - Testing wallet must have >0 ETH and USDC on Sepolia + - name: Run E2E tests run: xvfb-run pnpm run -F bridge-ui test:e2e:headful env: + # Do not run E2E tests in parallel. Especially blockchain tx where nonces can collide. CI: "true" E2E_TEST_PRIVATE_KEY: ${{ secrets.BRIDGE_UI_E2E_TESTS_PRIVATE_KEY }} E2E_TEST_SEED_PHRASE: "test test test test test test test test test test test junk" diff --git a/bridge-ui/package.json b/bridge-ui/package.json index faaeeb08..265e7446 100644 --- a/bridge-ui/package.json +++ b/bridge-ui/package.json @@ -7,17 +7,20 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint", - "lint:fix": "pnpm run lint:ts:fix", + "lint": "next lint && pnpm run lint:test", + "lint:test": "npx eslint 'test/**/*.{js,ts}'", + "lint:fix": "pnpm run lint:ts:fix && pnpm run lint:test:ts:fix", "lint:ts:fix": "next lint --fix", + "lint:test:ts:fix": "npx eslint --fix 'test/**/*.{js,ts}'", "clean": "rimraf node_modules .next .next-env.d.ts", "install:playwright": "playwright install --with-deps", "build:cache": "synpress", "build:cache:force": "synpress --force", "build:cache:headless": "synpress --headless", - "test:e2e:headful": "playwright test", - "test:e2e:headless": "HEADLESS=true playwright test", - "test:e2e:headless:ui": "HEADLESS=true playwright test --ui" + "test:unit": "HEADLESS=true playwright test src", + "test:e2e:headful": "playwright test test/e2e", + "test:e2e:headless": "HEADLESS=true playwright test test/e2e", + "test:e2e:headless:ui": "HEADLESS=true playwright test test/e2e --ui" }, "dependencies": { "@consensys/linea-sdk": "0.3.0", @@ -48,15 +51,16 @@ "zustand": "4.5.4" }, "devDependencies": { - "@playwright/test": "1.45.3", + "@playwright/test": "1.51.1", "@svgr/webpack": "8.1.0", - "@synthetixio/synpress": "4.0.0-alpha.7", + "@synthetixio/synpress": "4.0.10", "@types/fs-extra": "11.0.4", "@types/react": "18.3.11", "@types/react-dom": "18.3.0", "autoprefixer": "10.4.21", "dotenv": "16.4.7", "eslint-config-next": "14.2.15", + "nock": "14.0.1", "postcss": "8.5.3" } } diff --git a/bridge-ui/playwright.config.ts b/bridge-ui/playwright.config.ts index 001f5384..93530d0f 100644 --- a/bridge-ui/playwright.config.ts +++ b/bridge-ui/playwright.config.ts @@ -1,14 +1,21 @@ import { defineConfig, devices } from "@playwright/test"; +import "dotenv/config"; export default defineConfig({ - testDir: "./test/e2e", - timeout: 60_000, + testDir: ".", + testMatch: '**/*.spec.ts', + // Timeout for tests that don't involve blockchain transactions + timeout: 40_000, fullyParallel: true, maxFailures: process.env.CI ? 1 : 0, + // To consider - cannot really run E2E tests involving blockchain tx in parallel. There is a high risk of reusing the same tx nonce -> leading to dropped transactions workers: process.env.CI ? 1 : undefined, reporter: process.env.CI - ? [["html", { open: "never", outputFolder: `playwright-report-${process.env.HEADLESS ? "headless" : "headful"}` }]] - : "html", + ? [ + ["html", { open: "never", outputFolder: `playwright-report-${process.env.HEADLESS ? "headless" : "headful"}` }], + ["list"] + ] + : [["html"],["list"]], use: { baseURL: "http://localhost:3000", trace: process.env.CI ? "on" : "retain-on-failure", diff --git a/bridge-ui/src/components/bridge/claiming/received-amount/index.tsx b/bridge-ui/src/components/bridge/claiming/received-amount/index.tsx index facab70e..cedbf194 100644 --- a/bridge-ui/src/components/bridge/claiming/received-amount/index.tsx +++ b/bridge-ui/src/components/bridge/claiming/received-amount/index.tsx @@ -42,7 +42,7 @@ export default function ReceivedAmount() { return (
-

+

{formatBalance(receivedAmount, 6)} {token.symbol}

{tokenPrices?.[token[fromChain.layer].toLowerCase()] && diff --git a/bridge-ui/src/components/bridge/form/index.tsx b/bridge-ui/src/components/bridge/form/index.tsx index 7f87221b..726eb1cf 100644 --- a/bridge-ui/src/components/bridge/form/index.tsx +++ b/bridge-ui/src/components/bridge/form/index.tsx @@ -58,10 +58,11 @@ export default function BridgeForm() { setIsBridgeOpen(false); setIsTransactionHistoryOpen(true); }} + data-testid="native-bridge-transaction-history-icon" > - +
diff --git a/bridge-ui/src/components/bridge/modal/confirm-destination-address/index.tsx b/bridge-ui/src/components/bridge/modal/confirm-destination-address/index.tsx index 3b948f51..efaf8045 100644 --- a/bridge-ui/src/components/bridge/modal/confirm-destination-address/index.tsx +++ b/bridge-ui/src/components/bridge/modal/confirm-destination-address/index.tsx @@ -32,7 +32,7 @@ export default function ConfirmDestinationAddress({ isModalOpen, recipient, onCl {formatAddress(recipient)} -
diff --git a/bridge-ui/src/components/bridge/modal/token-modal/token-details/index.tsx b/bridge-ui/src/components/bridge/modal/token-modal/token-details/index.tsx index 0baeef63..0def74d8 100644 --- a/bridge-ui/src/components/bridge/modal/token-modal/token-details/index.tsx +++ b/bridge-ui/src/components/bridge/modal/token-modal/token-details/index.tsx @@ -46,6 +46,7 @@ export default function TokenDetails({ isConnected, token, onTokenClick, tokenPr return ( @@ -51,6 +52,7 @@ export default function TransactionHistory() { setIsTransactionHistoryOpen(false); setIsBridgeOpen(true); }} + data-testid="transaction-history-close-btn" > diff --git a/bridge-ui/src/components/bridge/transaction-history/list-transaction/index.tsx b/bridge-ui/src/components/bridge/transaction-history/list-transaction/index.tsx index d2e071e5..4e6e6e40 100644 --- a/bridge-ui/src/components/bridge/transaction-history/list-transaction/index.tsx +++ b/bridge-ui/src/components/bridge/transaction-history/list-transaction/index.tsx @@ -21,7 +21,7 @@ export default function ListTransaction({ transactions }: Props) { }; return ( <> -