diff --git a/.github/workflows/frontend-e2e-tests.yml b/.github/workflows/frontend-e2e-tests.yml index 03d63fc535..99f8ccccad 100644 --- a/.github/workflows/frontend-e2e-tests.yml +++ b/.github/workflows/frontend-e2e-tests.yml @@ -57,7 +57,7 @@ jobs: run: | echo "$GITHUB_OUTPUT" yarn --cwd packages/web install --frozen-lockfile && npx playwright install --with-deps chromium - - name: Run Swap Pair tests on Stage + - name: Run Swap Pair tests env: BASE_URL: "https://${{ needs.wait-for-deployment.outputs.environment_url }}" PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }} @@ -94,7 +94,7 @@ jobs: - name: Install Playwright run: | yarn --cwd packages/web install --frozen-lockfile && npx playwright install --with-deps chromium - - name: Run Portfolio tests on Stage + - name: Run Portfolio tests env: BASE_URL: "https://${{ needs.wait-for-deployment.outputs.environment_url }}" PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }} @@ -108,3 +108,38 @@ jobs: with: name: preview-portfolio-test-results path: packages/web/playwright-report + + preview-pools-tests: + needs: wait-for-deployment + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20.x + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: "**/node_modules" + key: ${{ runner.OS }}-20.x-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.OS }}-20.x- + - name: Install Playwright + run: | + yarn --cwd packages/web install --frozen-lockfile && npx playwright install --with-deps chromium + - name: Run Pools tests + env: + BASE_URL: "https://${{ needs.wait-for-deployment.outputs.environment_url }}" + PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }} + run: | + cd packages/web + npx playwright test -g "Test Select Pool feature" + - name: upload pools test results + if: always() + id: pools-test-results + uses: actions/upload-artifact@v4 + with: + name: preview-pools-test-results + path: packages/web/playwright-report diff --git a/packages/web/e2e/pages/base-page.ts b/packages/web/e2e/pages/base-page.ts index 17cdfac4c5..e123ee56d0 100644 --- a/packages/web/e2e/pages/base-page.ts +++ b/packages/web/e2e/pages/base-page.ts @@ -6,6 +6,7 @@ export class BasePage { readonly connectWalletBtn: Locator; readonly kepltWalletBtn: Locator; readonly portfolioLink: Locator; + readonly poolsLink: Locator; constructor(page: Page) { this.page = page; @@ -14,6 +15,7 @@ export class BasePage { .first(); this.kepltWalletBtn = page.locator("button").filter({ hasText: /^Keplr$/ }); this.portfolioLink = page.getByText("Portfolio"); + this.poolsLink = page.getByText("Pools"); } async connectWallet() { @@ -41,4 +43,13 @@ export class BasePage { async gotoPortfolio() { await this.portfolioLink.click(); } + + async gotoPools() { + await this.poolsLink.click(); + } + + async printUrl() { + const currentUrl = this.page.url(); + console.log("FE opened at: " + currentUrl); + } } diff --git a/packages/web/e2e/pages/pool-page.ts b/packages/web/e2e/pages/pool-page.ts new file mode 100644 index 0000000000..6bc158e6d4 --- /dev/null +++ b/packages/web/e2e/pages/pool-page.ts @@ -0,0 +1,36 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { Locator, Page } from "@playwright/test"; + +import { BasePage } from "~/e2e/pages/base-page"; + +import { SwapPage } from "./swap-page"; + +export class PoolPage extends BasePage { + readonly page: Page; + readonly viewMore: Locator; + readonly poolsLink: Locator; + readonly balance: Locator; + readonly tradeBtn: Locator; + + constructor(page: Page) { + super(page); + this.page = page; + this.viewMore = page.getByText("View more"); + this.poolsLink = page.locator('//a//div[contains(text(), "Pools")]'); + this.balance = page.locator( + '//span[.="Total balance"]/..//h4[contains(@class, "text-osmoverse-100")]' + ); + this.tradeBtn = page.locator('//button/span[.="Trade Pair"]'); + } + + async getBalance() { + let totalBalance: string = await this.balance.innerText(); + console.log(`Total Balance for a Pool [${totalBalance}]`); + return totalBalance; + } + + async getTradeModal() { + await this.tradeBtn.click(); + return new SwapPage(this.page); + } +} diff --git a/packages/web/e2e/pages/pools-page.ts b/packages/web/e2e/pages/pools-page.ts new file mode 100644 index 0000000000..0a17791fd4 --- /dev/null +++ b/packages/web/e2e/pages/pools-page.ts @@ -0,0 +1,42 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { Locator, Page } from "@playwright/test"; + +import { BasePage } from "~/e2e/pages/base-page"; + +import { PoolPage } from "./pool-page"; + +export class PoolsPage extends BasePage { + readonly page: Page; + readonly viewMore: Locator; + readonly poolsLink: Locator; + readonly balance: Locator; + + constructor(page: Page) { + super(page); + this.page = page; + this.viewMore = page.getByText("View more"); + this.poolsLink = page.locator('//a//div[contains(text(), "Pools")]'); + this.balance = page.locator( + '//span[.="Total balance"]/..//h4[contains(@class, "text-osmoverse-100")]' + ); + } + + async goto() { + await this.page.goto("/"); + await this.page.waitForTimeout(2000); + await this.poolsLink.click(); + // we expect that after 4 seconds tokens are loaded and any failure after this point should be considered a bug. + await this.page.waitForTimeout(4000); + await super.printUrl(); + } + + async viewPool(id: number, pair: string) { + await this.page + .locator(`//table//td/a[@href="/pool/${id}"]//span[.="${pair}"]`) + .click(); + // we expect that after 2 seconds tokens are loaded and any failure after this point should be considered a bug. + await this.page.waitForTimeout(2000); + await super.printUrl(); + return new PoolPage(this.page); + } +} diff --git a/packages/web/e2e/pages/swap-page.ts b/packages/web/e2e/pages/swap-page.ts index eaecd87a3c..c1c3b291d8 100644 --- a/packages/web/e2e/pages/swap-page.ts +++ b/packages/web/e2e/pages/swap-page.ts @@ -201,4 +201,16 @@ export class SwapPage extends BasePage { fullPage: true, }); } + + async getSelectedPair() { + const tokenLocator = + '//img[@alt="token icon"]/../..//h5 | //img[@alt="token icon"]/../..//span[@class="subtitle1"]'; + const fromToken = this.page.locator(tokenLocator).nth(0); + const toToken = this.page.locator(tokenLocator).nth(1); + + let fromTokenText = await fromToken.innerText(); + let toTokenText = await toToken.innerText(); + console.log("Current pair: " + `${fromTokenText}/${toTokenText}`); + return `${fromTokenText}/${toTokenText}`; + } } diff --git a/packages/web/e2e/tests/pools.spec.ts b/packages/web/e2e/tests/pools.spec.ts new file mode 100644 index 0000000000..37621d0507 --- /dev/null +++ b/packages/web/e2e/tests/pools.spec.ts @@ -0,0 +1,45 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { BrowserContext, chromium, expect, test } from "@playwright/test"; + +import { PoolsPage } from "../pages/pools-page"; + +test.describe("Test Select Pool feature", () => { + let context: BrowserContext; + let poolsPage: PoolsPage; + + test.beforeAll(async () => { + context = await chromium.launchPersistentContext("", { + headless: true, + viewport: { width: 1280, height: 1024 }, + }); + poolsPage = new PoolsPage(context.pages()[0]); + }); + + test.afterAll(async () => { + await context.close(); + }); + + test("User should be able to select ATOM/USDC", async () => { + await poolsPage.goto(); + const poolPage = await poolsPage.viewPool(1282, "ATOM/USDC"); + const balance = await poolPage.getBalance(); + expect(balance).toEqual("$0"); + const tradeModal = await poolPage.getTradeModal(); + const pair = await tradeModal.getSelectedPair(); + expect(pair).toEqual("ATOM/USDC"); + await tradeModal.enterAmount("1"); + await tradeModal.showSwapInfo(); + }); + + test("User should be able to select OSMO/USDC Pool", async () => { + await poolsPage.goto(); + const poolPage = await poolsPage.viewPool(1464, "OSMO/USDC"); + const balance = await poolPage.getBalance(); + expect(balance).toEqual("$0"); + const tradeModal = await poolPage.getTradeModal(); + const pair = await tradeModal.getSelectedPair(); + expect(pair).toEqual("OSMO/USDC"); + await tradeModal.enterAmount("1"); + await tradeModal.showSwapInfo(); + }); +});