From c30c5510804cd2fe29a30bf2d8405a3d63b3bf90 Mon Sep 17 00:00:00 2001 From: bslabiak <112852128+bslabiak@users.noreply.github.com> Date: Fri, 19 Apr 2024 14:19:51 +0200 Subject: [PATCH 1/2] test(extension): disable broken smoke tests (#1079) --- packages/e2e-tests/src/features/e2e/SendNftExtendedE2E.feature | 3 ++- .../e2e-tests/src/features/e2e/SendTransactionDappE2E.feature | 3 ++- .../e2e-tests/src/features/e2e/StakingInitialFundsE2E.feature | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/e2e-tests/src/features/e2e/SendNftExtendedE2E.feature b/packages/e2e-tests/src/features/e2e/SendNftExtendedE2E.feature index 5a05ab44f..3abefd644 100644 --- a/packages/e2e-tests/src/features/e2e/SendNftExtendedE2E.feature +++ b/packages/e2e-tests/src/features/e2e/SendNftExtendedE2E.feature @@ -6,7 +6,8 @@ Feature: Send NFT - Extended Browser View - E2E And I am on NFTs extended page And I use a single wallet with "Ibilecoin" NFT in extended mode - @LW-2502 @Smoke + @LW-2502 @Smoke @Pending + @issue=LW-10306 Scenario: Extended-view - Send NFT E2E And I'm sending the NFT with name: "Ibilecoin" in extended mode When I enter correct password and confirm the transaction diff --git a/packages/e2e-tests/src/features/e2e/SendTransactionDappE2E.feature b/packages/e2e-tests/src/features/e2e/SendTransactionDappE2E.feature index d54705a36..ba3fceb66 100644 --- a/packages/e2e-tests/src/features/e2e/SendTransactionDappE2E.feature +++ b/packages/e2e-tests/src/features/e2e/SendTransactionDappE2E.feature @@ -4,7 +4,8 @@ Feature: Send Transactions from Dapp - E2E Background: Given Wallet is synced - @LW-3761 @Testnet @Smoke + @LW-3761 @Testnet @Smoke @Pending + @issue=LW-10306 Scenario: Send ADA from DApp E2E And I save token: "Cardano" balance And I open and authorize test DApp with "Only once" setting diff --git a/packages/e2e-tests/src/features/e2e/StakingInitialFundsE2E.feature b/packages/e2e-tests/src/features/e2e/StakingInitialFundsE2E.feature index a0b538118..69d27b640 100644 --- a/packages/e2e-tests/src/features/e2e/StakingInitialFundsE2E.feature +++ b/packages/e2e-tests/src/features/e2e/StakingInitialFundsE2E.feature @@ -1,7 +1,8 @@ @Staking-initial-E2E @E2E @Testnet Feature: Delegating funds to new pool E2E - @LW-2685 @Smoke + @LW-2685 @Smoke @Pending + @issue=LW-10306 Scenario: Extended view - Staking - Delegating funds to new pool (if not staked yet) E2E. Given I create new wallet and save wallet information And Wallet is synced From 6aa696470950b45d8f1d9a26b33ecd3853d8da0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojtek=20K=C5=82os?= <114915819+wklos-iohk@users.noreply.github.com> Date: Fri, 19 Apr 2024 14:55:56 +0200 Subject: [PATCH 2/2] test(extension): coverage for new stake pool sorting (#1067) * test(extension): automate tests LW-10139 and LW-10141 * test(extension): speed up LW-8499 * test(extension): automate LW-10142 * test(extension): split feature file * test(extension): minor cleanup * test(extension): update after code review --- .../MultidelegationPageAssert.ts | 60 +++++-- .../e2e-tests/src/assert/stakingPageAssert.ts | 17 -- .../multidelegation/MultidelegationPage.ts | 153 +++++++++++++--- .../multidelegation/StakePoolListItem.ts | 7 +- .../src/elements/staking/StakePoolListItem.ts | 103 ----------- .../src/elements/staking/stakingPage.ts | 35 ---- .../src/enums/StakePoolListColumn.ts | 11 ++ ...MultiDelegationPageExtended.part1.feature} | 37 ++-- .../MultiDelegationPageExtended.part2.feature | 51 ++++++ .../src/features/StakingPageExtended.feature | 41 ----- .../StakingSwitchingPoolsExtendedE2E.feature | 4 +- .../e2e/StakingSwitchingPoolsPopupE2E.feature | 4 +- .../pageobject/stakingExtendedPageObject.ts | 60 ------- .../src/steps/multidelegationSteps.ts | 35 +++- packages/e2e-tests/src/steps/stakingSteps.ts | 25 --- packages/e2e-tests/src/types/sortingOrder.ts | 1 + packages/e2e-tests/src/types/staking.ts | 2 +- .../src/utils/stakePoolListContent.ts | 166 +++++++++++------- 18 files changed, 396 insertions(+), 416 deletions(-) delete mode 100644 packages/e2e-tests/src/elements/staking/StakePoolListItem.ts create mode 100644 packages/e2e-tests/src/enums/StakePoolListColumn.ts rename packages/e2e-tests/src/features/{MultiDelegationPageExtended.feature => MultiDelegationPageExtended.part1.feature} (89%) create mode 100644 packages/e2e-tests/src/features/MultiDelegationPageExtended.part2.feature delete mode 100644 packages/e2e-tests/src/features/StakingPageExtended.feature delete mode 100644 packages/e2e-tests/src/pageobject/stakingExtendedPageObject.ts create mode 100644 packages/e2e-tests/src/types/sortingOrder.ts diff --git a/packages/e2e-tests/src/assert/multidelegation/MultidelegationPageAssert.ts b/packages/e2e-tests/src/assert/multidelegation/MultidelegationPageAssert.ts index 3fe3f6ffb..e38af3f71 100644 --- a/packages/e2e-tests/src/assert/multidelegation/MultidelegationPageAssert.ts +++ b/packages/e2e-tests/src/assert/multidelegation/MultidelegationPageAssert.ts @@ -8,6 +8,10 @@ import { StakePoolListItem } from '../../elements/multidelegation/StakePoolListI import Tooltip from '../../elements/Tooltip'; import testContext from '../../utils/testContext'; import { StakePoolGridCard } from '../../elements/multidelegation/StakePoolGridCard'; +import { StakePoolListColumnName } from '../../types/staking'; +import { SortingOrder } from '../../types/sortingOrder'; +import { mapColumnNameStringToEnum, sortColumnContent } from '../../utils/stakePoolListContent'; +import { StakePoolListColumn } from '../../enums/StakePoolListColumn'; class MultidelegationPageAssert { assertSeeStakingOnPoolsCounter = async (poolsCount: number) => { @@ -188,36 +192,37 @@ class MultidelegationPageAssert { expect(await firstStakePool.ticker.getText()).to.equal(expectedTicker); }; - assertSeeTooltipForColumn = async (columnName: string) => { + assertSeeTooltipForColumn = async (column: StakePoolListColumn) => { + await MultidelegationPage.tooltip.waitForStable(); await MultidelegationPage.tooltip.waitForDisplayed(); let expectedTooltipText; - switch (columnName) { - case 'Ticker': + switch (column) { + case StakePoolListColumn.Ticker: expectedTooltipText = await t('browsePools.tooltips.ticker', 'staking'); break; - case 'Saturation': + case StakePoolListColumn.Saturation: expectedTooltipText = await t('browsePools.tooltips.saturation', 'staking'); break; - case 'ROS': + case StakePoolListColumn.ROS: expectedTooltipText = await t('browsePools.tooltips.ros', 'staking'); break; - case 'Cost': + case StakePoolListColumn.Cost: expectedTooltipText = await t('browsePools.tooltips.cost', 'staking'); break; - case 'Margin': + case StakePoolListColumn.Margin: expectedTooltipText = await t('browsePools.tooltips.margin', 'staking'); break; - case 'Blocks': + case StakePoolListColumn.Blocks: expectedTooltipText = await t('browsePools.tooltips.blocks', 'staking'); break; - case 'Pledge': + case StakePoolListColumn.Pledge: expectedTooltipText = await t('browsePools.tooltips.pledge', 'staking'); break; - case 'Live Stake': + case StakePoolListColumn.LiveStake: expectedTooltipText = await t('browsePools.tooltips.liveStake', 'staking'); break; default: - throw new Error(`Unsupported column name: ${columnName}`); + throw new Error(`Unsupported column name: ${column}`); } expect(await MultidelegationPage.tooltip.getText()).to.equal(expectedTooltipText); }; @@ -300,6 +305,39 @@ class MultidelegationPageAssert { const cardsInARow = Math.floor(rowWidth / cardWidth); expect(cardsInARow).to.equal(expectedCardsCount); }; + + assertSeeColumnSortingIndicator = async (column: StakePoolListColumnName, order: 'ascending' | 'descending') => { + await ( + await MultidelegationPage.getColumnSortingIndicator(mapColumnNameStringToEnum(column), order) + ).waitForDisplayed(); + }; + + assertSeeStakePoolsSorted = async ( + stakePoolsDisplayType: 'list rows' | 'cards', + sortingOption: StakePoolListColumnName, + order: SortingOrder, + poolLimit?: number + ) => { + await MultidelegationPage.waitForPoolsCounterToBeGreaterThanZero(); + poolLimit ??= await MultidelegationPage.getNumberOfPoolsFromCounter(); + if (stakePoolsDisplayType === 'cards') { + // TODO: add code to handle grid cards - LW-10284 + throw new Error('Please add validation for grid cards sorting'); + } else { + const columnContent = await MultidelegationPage.extractColumnContent( + mapColumnNameStringToEnum(sortingOption), + poolLimit + ); + const sortedColumnContent = await sortColumnContent( + columnContent, + mapColumnNameStringToEnum(sortingOption), + order + ); + + expect(columnContent).to.not.be.empty; + expect(columnContent).to.deep.equal(sortedColumnContent); + } + }; } export default new MultidelegationPageAssert(); diff --git a/packages/e2e-tests/src/assert/stakingPageAssert.ts b/packages/e2e-tests/src/assert/stakingPageAssert.ts index d35d8e577..a296741be 100644 --- a/packages/e2e-tests/src/assert/stakingPageAssert.ts +++ b/packages/e2e-tests/src/assert/stakingPageAssert.ts @@ -1,13 +1,8 @@ import StakingPage from '../elements/staking/stakingPage'; import { TestnetPatterns } from '../support/patterns'; -import webTester from '../actor/webTester'; import StakingInfoComponent from '../elements/staking/stakingInfoComponent'; import { t } from '../utils/translationService'; -import { StakePoolListItem } from '../elements/staking/StakePoolListItem'; import StakingSuccessDrawer from '../elements/staking/StakingSuccessDrawer'; -import { Logger } from '../support/logger'; -import StakingExtendedPageObject from '../pageobject/stakingExtendedPageObject'; -import { sortColumnContent } from '../utils/stakePoolListContent'; import { expect } from 'chai'; import { StakePool } from '../data/expectedStakePoolsData'; import StakingPasswordDrawer from '../elements/staking/StakingPasswordDrawer'; @@ -114,18 +109,6 @@ class StakingPageAssert { }); }; - assertStakePoolItemsOrder = async (columnName: string, order: string) => { - const stakePoolListItem = new StakePoolListItem(); - await webTester.waitUntilSeeElement(stakePoolListItem.container(), 60_000); - const columnContent: string[] = await StakingExtendedPageObject.extractColumnContent(columnName); - Logger.log(`EXTRACTED DATA: ${columnContent}`); - const sortedColumnContent = await sortColumnContent(columnContent, columnName, order); - Logger.log(`SORTED DATA: ${sortedColumnContent}`); - - expect(columnContent).to.not.be.empty; - expect(columnContent).to.deep.equal(sortedColumnContent); - }; - assertSeeStakingPasswordDrawer = async () => { await StakingPasswordDrawer.title.waitForDisplayed(); expect(await StakingPasswordDrawer.title.getText()).to.equal( diff --git a/packages/e2e-tests/src/elements/multidelegation/MultidelegationPage.ts b/packages/e2e-tests/src/elements/multidelegation/MultidelegationPage.ts index d6311743d..7c738530d 100644 --- a/packages/e2e-tests/src/elements/multidelegation/MultidelegationPage.ts +++ b/packages/e2e-tests/src/elements/multidelegation/MultidelegationPage.ts @@ -8,11 +8,11 @@ import StakePoolDetails from '../staking/stakePoolDetails'; import testContext from '../../utils/testContext'; import { isPopupMode } from '../../utils/pageUtils'; import CommonDrawerElements from '../CommonDrawerElements'; -import { StakePoolListColumnType } from '../../types/staking'; import { StakePoolListItem } from './StakePoolListItem'; import { StakePoolGridCard } from './StakePoolGridCard'; import StakePoolDetailsDrawer from './StakePoolDetailsDrawer'; import MoreOptionsComponent from './MoreOptionsComponent'; +import { StakePoolListColumn } from '../../enums/StakePoolListColumn'; class MultidelegationPage { private ACTIVITY_TAB = '[data-testid="activity-tab"]'; @@ -41,6 +41,7 @@ class MultidelegationPage { private COLUMN_HEADER_BLOCKS = '[data-testid="stake-pool-list-header-blocks"]'; private COLUMN_HEADER_PLEDGE = '[data-testid="stake-pool-list-header-pledge"]'; private COLUMN_HEADER_LIVE_STAKE = '[data-testid="stake-pool-list-header-liveStake"]'; + private COLUMN_SORTING_INDICATOR_TEMPLATE = '[data-testid="stake-pool-sort-order-###"]'; private MANAGE_STAKING_BTN_NEXT = '[data-testid="preferences-next-button"]'; private CONFIRMATION_BTN_NEXT = '[data-testid="stake-pool-confirmation-btn"]'; private DELEGATED_POOL_ITEM = '[data-testid="delegated-pool-item"]'; @@ -73,6 +74,7 @@ class MultidelegationPage { private STAKE_POOL_CARD_SKELETON = '[data-testid="stake-pool-card-skeleton"]'; private SELCECTED_STAKE_POOLS_IN_GRID_VIEW = '[data-testid="selected-pools-list"] [data-testid="stake-pool-card"]'; private SELCECTED_STAKE_POOLS_IN_LIST_VIEW = '[data-testid="selected-pools-list"] [data-testid="stake-pool-item"]'; + private POOLS_COUNTER = '[data-testid="pools-counter"]'; get title() { return SectionTitle.sectionTitle; @@ -214,6 +216,10 @@ class MultidelegationPage { return $(this.MANAGE_BTN); } + get poolsCounter() { + return $(this.POOLS_COUNTER); + } + delegatedPoolLogo(index: number): ChainablePromiseElement { return $$(this.DELEGATED_POOL_ITEM)[index].$(this.DELEGATED_POOL_LOGO); } @@ -300,6 +306,43 @@ class MultidelegationPage { )) as WebdriverIO.Element; } + async getColumnSortingIndicator(columnName: StakePoolListColumn, order: 'ascending' | 'descending') { + const orderDirection = order === 'ascending' ? 'asc' : 'desc'; + const orderDirectionSelector = `${this.COLUMN_SORTING_INDICATOR_TEMPLATE.replace('###', orderDirection)}`; + let selector = ''; + + switch (columnName) { + case StakePoolListColumn.Ticker: + selector = `${this.COLUMN_HEADER_TICKER} ${orderDirectionSelector}`; + break; + case StakePoolListColumn.Saturation: + selector = `${this.COLUMN_HEADER_SATURATION} ${orderDirectionSelector}`; + break; + case StakePoolListColumn.ROS: + selector = `${this.COLUMN_HEADER_ROS} ${orderDirectionSelector}`; + break; + case StakePoolListColumn.Cost: + selector = `${this.COLUMN_HEADER_COST} ${orderDirectionSelector}`; + break; + case StakePoolListColumn.Margin: + selector = `${this.COLUMN_HEADER_MARGIN} ${orderDirectionSelector}`; + break; + case StakePoolListColumn.Blocks: + selector = `${this.COLUMN_HEADER_BLOCKS} ${orderDirectionSelector}`; + break; + case StakePoolListColumn.Pledge: + selector = `${this.COLUMN_HEADER_PLEDGE} ${orderDirectionSelector}`; + break; + case StakePoolListColumn.LiveStake: + selector = `${this.COLUMN_HEADER_LIVE_STAKE} ${orderDirectionSelector}`; + break; + default: + throw new Error(`Unsupported column name: ${columnName}`); + } + + return $(selector); + } + async clickAndGetTabStateAttribute(tab: 'Overview' | 'Browse pools') { let tabElement; switch (tab) { @@ -418,68 +461,69 @@ class MultidelegationPage { await poolItem.click(); } - async hoverOverColumnWithName(columnName: StakePoolListColumnType) { + async hoverOverColumn(column: StakePoolListColumn) { let header; - switch (columnName) { - case 'Ticker': + + switch (column) { + case StakePoolListColumn.Ticker: header = await this.columnHeaderTicker; break; - case 'Saturation': + case StakePoolListColumn.Saturation: header = await this.columnHeaderSaturation; break; - case 'ROS': + case StakePoolListColumn.ROS: header = await this.columnHeaderROS; break; - case 'Cost': + case StakePoolListColumn.Cost: header = await this.columnHeaderCost; break; - case 'Margin': + case StakePoolListColumn.Margin: header = await this.columnHeaderMargin; break; - case 'Blocks': + case StakePoolListColumn.Blocks: header = await this.columnHeaderBlocks; break; - case 'Pledge': + case StakePoolListColumn.Pledge: header = await this.columnHeaderPledge; break; - case 'Live Stake': + case StakePoolListColumn.LiveStake: header = await this.columnHeaderLiveStake; break; default: - throw new Error(`Unsupported column name: ${columnName}`); + throw new Error(`Unsupported column name: ${column}`); } // make hovering over ANTD component more stable await header?.$('span span span').moveTo(); } - async clickOnColumnWithName(columnName: StakePoolListColumnType) { - switch (columnName) { - case 'Ticker': + async clickOnColumn(column: StakePoolListColumn) { + switch (column) { + case StakePoolListColumn.Ticker: await this.columnHeaderTicker.click(); break; - case 'Saturation': + case StakePoolListColumn.Saturation: await this.columnHeaderSaturation.click(); break; - case 'ROS': + case StakePoolListColumn.ROS: await this.columnHeaderROS.click(); break; - case 'Cost': + case StakePoolListColumn.Cost: await this.columnHeaderCost.click(); break; - case 'Margin': + case StakePoolListColumn.Margin: await this.columnHeaderMargin.click(); break; - case 'Blocks': + case StakePoolListColumn.Blocks: await this.columnHeaderBlocks.click(); break; - case 'Pledge': + case StakePoolListColumn.Pledge: await this.columnHeaderPledge.click(); break; - case 'Live Stake': + case StakePoolListColumn.LiveStake: await this.columnHeaderLiveStake.click(); break; default: - throw new Error(`Unsupported column name: ${columnName}`); + throw new Error(`Unsupported column name: ${column}`); } } @@ -543,6 +587,69 @@ class MultidelegationPage { const selectedTickers = await this.getTickersOfSelectedPools(viewType); testContext.save('selectedTickers', selectedTickers); } + + async getNumberOfPoolsFromCounter(): Promise { + const poolsCounterText = await this.poolsCounter.getText(); + return Number(Number(poolsCounterText.replace(/.*\(/, '').replace(')', '').replace(',', ''))); + } + + async waitForPoolsCounterToBeGreaterThanZero(): Promise { + await this.poolsCounter.waitForDisplayed(); + await browser.waitUntil(async () => (await this.getNumberOfPoolsFromCounter()) > 0, { + timeoutMsg: 'No stake pools!' + }); + } + + async extractColumnContent(columnName: StakePoolListColumn, poolLimit = 100): Promise { + const columnContent: string[] = []; + + await this.listContainer.waitForStable(); + await browser.pause(500); + + for (let i = 0; i < poolLimit; i++) { + const displayedPoolsCounter = await this.displayedPools.length; + const listItem = new StakePoolListItem(i); + // Load more pools if all visible ones were processed + if (i % (displayedPoolsCounter - 1) === 0) { + await listItem.container.scrollIntoView(); + await this.stakePoolListRowSkeleton.waitForExist({ + reverse: true, + interval: 100, + timeout: 30_000 + }); + } + switch (columnName) { + case StakePoolListColumn.Ticker: + columnContent.push(await listItem.ticker.getText()); + break; + case StakePoolListColumn.Saturation: + columnContent.push(await listItem.saturation.getText()); + break; + case StakePoolListColumn.ROS: + columnContent.push(await listItem.ros.getText()); + break; + case StakePoolListColumn.Cost: + columnContent.push(await listItem.cost.getText()); + break; + case StakePoolListColumn.Margin: + columnContent.push(await listItem.margin.getText()); + break; + case StakePoolListColumn.Blocks: + columnContent.push(await listItem.blocks.getText()); + break; + case StakePoolListColumn.Pledge: + columnContent.push(await listItem.pledge.getText()); + break; + case StakePoolListColumn.LiveStake: + columnContent.push(await listItem.liveStake.getText()); + break; + default: + throw new Error(`Not supported column name: ${columnName}`); + } + } + + return columnContent; + } } export default new MultidelegationPage(); diff --git a/packages/e2e-tests/src/elements/multidelegation/StakePoolListItem.ts b/packages/e2e-tests/src/elements/multidelegation/StakePoolListItem.ts index 3543d5846..bfe82ddb4 100644 --- a/packages/e2e-tests/src/elements/multidelegation/StakePoolListItem.ts +++ b/packages/e2e-tests/src/elements/multidelegation/StakePoolListItem.ts @@ -3,7 +3,6 @@ import { ChainablePromiseElement } from 'webdriverio'; export class StakePoolListItem { private SELECTED_POOLS_LIST = '[data-testid="selected-pools-list"]'; - private AVAILABLE_POOLS_LIST = '[data-testid="stake-pool-list-scroll-wrapper"]'; private LIST_ITEM = '[data-testid="stake-pool-item"]'; private CHECKBOX = '[data-testid="stake-pool-list-checkbox"]'; private TICKER = '[data-testid="stake-pool-list-ticker"]'; @@ -18,9 +17,9 @@ export class StakePoolListItem { protected listItem; constructor(index = 0, isOnSelectedPoolsList = false) { - this.listItem = $(isOnSelectedPoolsList ? this.SELECTED_POOLS_LIST : this.AVAILABLE_POOLS_LIST).$$(this.LIST_ITEM)[ - index - ]; + this.listItem = $( + isOnSelectedPoolsList ? `${this.SELECTED_POOLS_LIST} ${this.LIST_ITEM}` : `[data-item-index="${index}"]` + ); } get container(): ChainablePromiseElement { diff --git a/packages/e2e-tests/src/elements/staking/StakePoolListItem.ts b/packages/e2e-tests/src/elements/staking/StakePoolListItem.ts deleted file mode 100644 index ef31ac490..000000000 --- a/packages/e2e-tests/src/elements/staking/StakePoolListItem.ts +++ /dev/null @@ -1,103 +0,0 @@ -/* eslint-disable no-undef */ -import webTester, { LocatorStrategy } from '../../actor/webTester'; -import { WebElement, WebElementFactory as Factory } from './../webElement'; - -export class StakePoolListItem extends WebElement { - protected TABLE_ROW = '//div[@data-testid="stake-pool-table-item"]'; - private LOGO = '//img[@data-testid="stake-pool-list-logo"]'; - private NAME = '//h6[@data-testid="stake-pool-list-name"]'; - private TICKER = '//p[@data-testid="stake-pool-list-ticker"]'; - private ROS = '//p[@data-testid="stake-pool-list-ros"]'; - private COST = '//p[@data-testid="stake-pool-list-cost"]'; - private SATURATION = '//p[@data-testid="stake-pool-list-saturation"]'; - - constructor(index?: number) { - super(); - this.TABLE_ROW = - typeof index === 'undefined' || index.toString() === '' ? this.TABLE_ROW : `(${this.TABLE_ROW})[${index}]`; - } - - container(): WebElement { - return Factory.fromSelector(`${this.TABLE_ROW}`, 'xpath'); - } - - tableRowWithName(poolName: string): WebElement { - return Factory.fromSelector(`${this.TABLE_ROW}[.//h6[contains(text(), '${poolName}')]]`, 'xpath'); - } - - async getRows(): Promise { - return $$(`${this.TABLE_ROW}`); - } - - logo(): WebElement { - return Factory.fromSelector(`${this.TABLE_ROW}${this.LOGO}`, 'xpath'); - } - - logoWithIndex(index: number): WebElement { - return Factory.fromSelector(`(${this.LOGO})[${index}]`, 'xpath'); - } - - name(): WebElement { - return Factory.fromSelector(`${this.TABLE_ROW}${this.NAME}`, 'xpath'); - } - - nameWithIndex(index: number): WebElement { - return Factory.fromSelector(`(${this.NAME})[${index}]`, 'xpath'); - } - - ticker(): WebElement { - return Factory.fromSelector(`${this.TABLE_ROW}${this.TICKER}`, 'xpath'); - } - - tickerWithIndex(index: number): WebElement { - return Factory.fromSelector(`(${this.TICKER})[${index}]`, 'xpath'); - } - - ros(): WebElement { - return Factory.fromSelector(`${this.TABLE_ROW}${this.ROS}`, 'xpath'); - } - - cost(): WebElement { - return Factory.fromSelector(`${this.TABLE_ROW}${this.COST}`, 'xpath'); - } - - saturation(): WebElement { - return Factory.fromSelector(`${this.TABLE_ROW}${this.SATURATION}`, 'xpath'); - } - - async getName(): Promise { - return await webTester.getTextValueFromElement(this.name()); - } - - async getTicker(): Promise { - return await webTester.getTextValueFromElement(this.ticker()); - } - - async getRos(): Promise { - return await webTester.getTextValueFromElement(this.ros()); - } - - async getCost(): Promise { - return await webTester.getTextValueFromElement(this.cost()); - } - - async getSaturation(): Promise { - return await webTester.getTextValueFromElement(this.saturation()); - } - - async getNameWithIndex(index: number): Promise { - return await webTester.getTextValueFromElement(this.nameWithIndex(index)); - } - - async getTickerWithIndex(index: number): Promise { - return await webTester.getTextValueFromElement(this.tickerWithIndex(index)); - } - - toJSLocator(): string { - return this.TABLE_ROW; - } - - locatorStrategy(): LocatorStrategy { - return 'xpath'; - } -} diff --git a/packages/e2e-tests/src/elements/staking/stakingPage.ts b/packages/e2e-tests/src/elements/staking/stakingPage.ts index 12f702cd7..1793d9bcb 100644 --- a/packages/e2e-tests/src/elements/staking/stakingPage.ts +++ b/packages/e2e-tests/src/elements/staking/stakingPage.ts @@ -2,17 +2,11 @@ import SectionTitle from '../sectionTitle'; class StakingPage { - private SEARCH_ICON = '[data-testid="search-icon"]'; private SEARCH_INPUT = '.ant-select-selection-search input'; - private SEARCH_INPUT_PLACEHOLDER_IN_POPUP = '.ant-select-selection-placeholder'; - private STAKE_POOL_LIST_HEADER_TEMPLATE = '[data-testid="stake-pool-list-header-###COLUMN_NAME###"]'; - private EMPTY_SEARCH_RESULTS_IMAGE = '[data-testid="stake-pool-table-empty-image"]'; - private EMPTY_SEARCH_RESULTS_MESSAGE = '[data-testid="stake-pool-table-empty-message"]'; private SEARCH_LOADER = '[data-testid="search-loader"]'; private STAKE_POOL_LIST_COST = '[data-testid="stake-pool-list-cost"]'; private STATS_TITLE = '[data-testid="stats-title"]'; private STATS_VALUE = '[data-testid="stats-value"]'; - private STAKE_POOL_TABLE_ROW = '[data-testid="stake-pool-table-item"]'; get title() { return SectionTitle.sectionTitle; @@ -22,10 +16,6 @@ class StakingPage { return SectionTitle.sectionCounter; } - get stakingPageSearchIcon() { - return $(this.SEARCH_ICON); - } - get statsTitle() { return $$(this.STATS_TITLE); } @@ -34,14 +24,6 @@ class StakingPage { return $(this.SEARCH_INPUT); } - get searchInputPlaceholderInPopup() { - return $(this.SEARCH_INPUT_PLACEHOLDER_IN_POPUP); - } - - get rows() { - return $$(this.STAKE_POOL_TABLE_ROW); - } - get statsValues() { return $$(this.STATS_VALUE); } @@ -62,27 +44,10 @@ class StakingPage { return $$(this.STAKE_POOL_LIST_COST); } - get statsValue() { - return $$(this.STATS_VALUE); - } - - get emptySearchResultsImage() { - return $(this.EMPTY_SEARCH_RESULTS_IMAGE); - } - - get emptySearchResultsMessage() { - return $(this.EMPTY_SEARCH_RESULTS_MESSAGE); - } - get searchLoader() { return $(this.SEARCH_LOADER); } - stakingPoolListColumnHeader(listHeader: string) { - const headerColumnSelector = this.STAKE_POOL_LIST_HEADER_TEMPLATE.replace('###COLUMN_NAME###', listHeader); - return $(headerColumnSelector); - } - stakingPoolWithName(poolName: string) { return $(`h6=${poolName}`); } diff --git a/packages/e2e-tests/src/enums/StakePoolListColumn.ts b/packages/e2e-tests/src/enums/StakePoolListColumn.ts new file mode 100644 index 000000000..1c90d58b6 --- /dev/null +++ b/packages/e2e-tests/src/enums/StakePoolListColumn.ts @@ -0,0 +1,11 @@ +/* eslint-disable no-unused-vars */ +export enum StakePoolListColumn { + Ticker = 'Ticker', + Saturation = 'Saturation', + ROS = 'ROS', + Cost = 'Cost', + Margin = 'Margin', + Blocks = 'Blocks', + Pledge = 'Pledge', + LiveStake = 'Live Stake' +} diff --git a/packages/e2e-tests/src/features/MultiDelegationPageExtended.feature b/packages/e2e-tests/src/features/MultiDelegationPageExtended.part1.feature similarity index 89% rename from packages/e2e-tests/src/features/MultiDelegationPageExtended.feature rename to packages/e2e-tests/src/features/MultiDelegationPageExtended.part1.feature index 91e855d6e..335fc1244 100644 --- a/packages/e2e-tests/src/features/MultiDelegationPageExtended.feature +++ b/packages/e2e-tests/src/features/MultiDelegationPageExtended.part1.feature @@ -88,22 +88,27 @@ Feature: Staking Page - Extended View Then I see the Network Info component with the expected content @LW-8499 @Testnet @Mainnet - Scenario Outline: Extended View - Staking - Show tooltip for column in browse pools section + Scenario: Extended View - Staking - Show tooltip for columns in browse pools section When I navigate to Staking extended page And I open Browse pools tab And I switch to list view on "Browse pools" tab - When I hover over "" column name in stake pool list - Then tooltip for "" column is displayed - Examples: - | column_name | - | Ticker | - | Saturation | -# | ROS | #TODO: Uncomment when USE_ROS_STAKING_COLUMN=true - | Cost | - | Margin | - | Blocks | - | Pledge | - | Live Stake | + When I hover over "Ticker" column name in stake pool list + Then tooltip for "Ticker" column is displayed + When I hover over "Saturation" column name in stake pool list + Then tooltip for "Saturation" column is displayed + #TODO: Uncomment when USE_ROS_STAKING_COLUMN=true + #When I hover over "ROS" column name in stake pool list + #Then tooltip for "ROS" column is displayed + When I hover over "Cost" column name in stake pool list + Then tooltip for "Cost" column is displayed + When I hover over "Margin" column name in stake pool list + Then tooltip for "Margin" column is displayed + When I hover over "Blocks" column name in stake pool list + Then tooltip for "Blocks" column is displayed + When I hover over "Pledge" column name in stake pool list + Then tooltip for "Pledge" column is displayed + When I hover over "Live Stake" column name in stake pool list + Then tooltip for "Live Stake" column is displayed @LW-8637 @Testnet @Mainnet Scenario: Extended View - Staking password screen details @@ -186,12 +191,6 @@ Feature: Staking Page - Extended View | list | I refresh the page | | list | I open Overview tab | - @LW-10143 @Testnet @Mainnet - Scenario: Extended View - Staking - More options - Sorting options are displayed - When I am on Staking extended page - And I open Browse pools tab - Then "More options" component with stake pool sorting options is displayed - @LW-9996 @Testnet @Mainnet Scenario: Extended View - Grid - display stake pool cards based on browser width When I am on Staking extended page diff --git a/packages/e2e-tests/src/features/MultiDelegationPageExtended.part2.feature b/packages/e2e-tests/src/features/MultiDelegationPageExtended.part2.feature new file mode 100644 index 000000000..b1975ca61 --- /dev/null +++ b/packages/e2e-tests/src/features/MultiDelegationPageExtended.part2.feature @@ -0,0 +1,51 @@ +@Staking-NonDelegatedFunds-Extended +Feature: Staking Page - Extended View + + Background: + Given Lace is ready for test + + @LW-10143 @Testnet @Mainnet + Scenario: Extended View - Staking - More options - Sorting options are displayed + When I am on Staking extended page + And I open Browse pools tab + Then "More options" component with stake pool sorting options is displayed + + @LW-10139 @LW-10141 @LW-10142 @Testnet @Mainnet + Scenario: Extended View - Staking - List View - Stake pool list sorting by ticker (default) + When I am on Staking extended page + And I open Browse pools tab + And I switch to list view on "Browse pools" tab + Then stake pool list view is displayed + And ascending sorting indicator is displayed for "Ticker" column + And stake pool list rows are sorted by "Ticker" in ascending order + When I click on stake pools table "Ticker" column header + Then descending sorting indicator is displayed for "Ticker" column + And stake pool list rows are sorted by "Ticker" in descending order + When I click on stake pools table "Ticker" column header + Then ascending sorting indicator is displayed for "Ticker" column + And stake pool list rows are sorted by "Ticker" in ascending order + + @LW-10141 @LW-10142 @Testnet @Mainnet + Scenario Outline: Extended View - Staking - List View - sorting by column - + When I am on Staking extended page + And I open Browse pools tab + And I switch to list view on "Browse pools" tab + Then stake pool list view is displayed + When I click on stake pools table "" column header + Then sorting indicator is displayed for "" column + And stake pool list rows are sorted by "" in order + When I click on stake pools table "" column header + Then sorting indicator is displayed for "" column + And stake pool list rows are sorted by "" in order + When I click on stake pools table "" column header + Then sorting indicator is displayed for "" column + And stake pool list rows are sorted by "" in order + Examples: + | column | default_order | modified_order | + | Saturation | descending | ascending | +# | ROS | descending | ascending |# TODO: Uncomment when USE_ROS_STAKING_COLUMN=true + | Cost | ascending | descending | + | Margin | ascending | descending | + | Blocks | descending | ascending | + | Pledge | descending | ascending | + | Live Stake | descending | ascending | diff --git a/packages/e2e-tests/src/features/StakingPageExtended.feature b/packages/e2e-tests/src/features/StakingPageExtended.feature deleted file mode 100644 index 4cd6d3f21..000000000 --- a/packages/e2e-tests/src/features/StakingPageExtended.feature +++ /dev/null @@ -1,41 +0,0 @@ -@Staking-NonDelegatedFunds-Extended @Pending -Feature: Staking Page - Extended Browser View - - Background: - Given Wallet is synced - - @LW-4024 @Pending @Testnet @Mainnet - @issue=ADP-2344 - Scenario: Extended View - Stake pool list default sorting by ROS - When I navigate to Staking extended page - And I reveal all stake pools - Then the results are in descending order according to "ros" column - - @LW-2706 @Pending @Testnet @Mainnet - @issue=ADP-2344 - Scenario Outline: Extended View - Sort lists ascending - column: - When I navigate to Staking extended page - And I click on the "" column header - And I reveal all stake pools - Then the results are in ascending order according to "" column - Examples: - | column | - | name | - | ros | - | cost | - | saturation | - - @LW-2706 @Pending @Testnet @Mainnet - @issue=ADP-2344 - Scenario Outline: Extended View - Sort lists descending - column - When I navigate to Staking extended page - And I click on the "" column header - And I click on the "" column header - And I reveal all stake pools - Then the results are in descending order according to "" column - Examples: - | column | - | name | - | ros | - | cost | - | saturation | diff --git a/packages/e2e-tests/src/features/e2e/StakingSwitchingPoolsExtendedE2E.feature b/packages/e2e-tests/src/features/e2e/StakingSwitchingPoolsExtendedE2E.feature index ba9e1a07e..8b3c3bb02 100644 --- a/packages/e2e-tests/src/features/e2e/StakingSwitchingPoolsExtendedE2E.feature +++ b/packages/e2e-tests/src/features/e2e/StakingSwitchingPoolsExtendedE2E.feature @@ -13,7 +13,7 @@ Feature: Staking Page - Switching pools - Extended Browser View - E2E And I wait for single search result And I click stake pool with name "OtherStakePool" Then I see drawer with "OtherStakePool" stake pool details and a button available for staking - And I save stake pool info + And I save stake pool details When I click "Stake on this pool" button on stake pool details drawer And I click "Fine by me" button on "Switching pool?" modal Then I see drawer with stakepool: "OtherStakePool" confirmation screen in extended mode @@ -37,7 +37,7 @@ Feature: Staking Page - Switching pools - Extended Browser View - E2E And I wait for single search result And I click stake pool with name "-" Then I see drawer with stake pool details without metadata and a button available for staking - And I save stake pool info + And I save stake pool details When I click "Stake on this pool" button on stake pool details drawer And I click "Fine by me" button on "Switching pool?" modal And I click "Next" button on staking confirmation drawer diff --git a/packages/e2e-tests/src/features/e2e/StakingSwitchingPoolsPopupE2E.feature b/packages/e2e-tests/src/features/e2e/StakingSwitchingPoolsPopupE2E.feature index f61f7b43f..553979ca9 100644 --- a/packages/e2e-tests/src/features/e2e/StakingSwitchingPoolsPopupE2E.feature +++ b/packages/e2e-tests/src/features/e2e/StakingSwitchingPoolsPopupE2E.feature @@ -13,7 +13,7 @@ Feature: Staking Page - Switching pools - Popup View - E2E And I wait for single search result And I click stake pool with name "OtherStakePool" Then I see drawer with "OtherStakePool" stake pool details and a button available for staking - And I save stake pool info + And I save stake pool details When I click "Stake on this pool" button on stake pool details drawer And I click "Fine by me" button on "Switching pool?" modal Then I see drawer with stakepool: "OtherStakePool" confirmation screen in popup mode @@ -36,7 +36,7 @@ Feature: Staking Page - Switching pools - Popup View - E2E And I wait for single search result And I click stake pool with name "-" Then I see drawer with stake pool details without metadata and a button available for staking - When I save stake pool info + When I save stake pool details And I click "Stake on this pool" button on stake pool details drawer And I click "Fine by me" button on "Switching pool?" modal And I click "Next" button on staking confirmation drawer diff --git a/packages/e2e-tests/src/pageobject/stakingExtendedPageObject.ts b/packages/e2e-tests/src/pageobject/stakingExtendedPageObject.ts deleted file mode 100644 index 414ad5568..000000000 --- a/packages/e2e-tests/src/pageobject/stakingExtendedPageObject.ts +++ /dev/null @@ -1,60 +0,0 @@ -import webTester from '../actor/webTester'; -import StakingPage from '../elements/staking/stakingPage'; -import { StakePoolListItem } from '../elements/staking/StakePoolListItem'; -import testContext from '../utils/testContext'; -import StakePoolDetails from '../elements/staking/stakePoolDetails'; - -class StakingExtendedPageObject { - async clickStakePoolListHeader(listHeader: string) { - await StakingPage.stakingPoolListColumnHeader(listHeader).scrollIntoView(); - await StakingPage.stakingPoolListColumnHeader(listHeader).click(); - } - - async revealAllStakePools(): Promise { - const stakePoolListItem = new StakePoolListItem(); - await webTester.waitUntilSeeElement(stakePoolListItem.container(), 6000); - - const expectedTotalRows = Number((await StakingPage.counter.getText()).replace(/\D/g, '')); - let displayedRows = (await stakePoolListItem.getRows()).length; - - while (displayedRows < expectedTotalRows) { - await $(new StakePoolListItem(displayedRows).toJSLocator()).scrollIntoView(); - displayedRows = (await stakePoolListItem.getRows()).length; - } - } - - async extractColumnContent(columnName: string): Promise { - const rowsNumber = (await new StakePoolListItem().getRows()).length; - const columnContent: string[] = []; - for (let i = 1; i <= rowsNumber; i++) { - const listItem = new StakePoolListItem(i); - switch (columnName) { - case 'name': - columnContent.push((await listItem.getName()) as string); - break; - case 'ros': - columnContent.push((await listItem.getRos()) as string); - break; - case 'cost': - columnContent.push((await listItem.getCost()) as string); - break; - case 'saturation': - columnContent.push((await listItem.getSaturation()) as string); - break; - } - } - - return columnContent; - } - - saveStakePoolInfo = async () => { - const poolName = (await StakePoolDetails.poolName.getText()) as string; - testContext.save('poolName', poolName); - const poolTicker = (await StakePoolDetails.poolTicker.getText()) as string; - testContext.save('poolTicker', poolTicker); - const poolID = (await StakePoolDetails.poolId.getText()) as string; - testContext.save('poolID', poolID); - }; -} - -export default new StakingExtendedPageObject(); diff --git a/packages/e2e-tests/src/steps/multidelegationSteps.ts b/packages/e2e-tests/src/steps/multidelegationSteps.ts index 8bbe8713c..8fa11fa1f 100644 --- a/packages/e2e-tests/src/steps/multidelegationSteps.ts +++ b/packages/e2e-tests/src/steps/multidelegationSteps.ts @@ -27,9 +27,10 @@ import StartStakingPage from '../elements/multidelegation/StartStakingPage'; import PortfolioBar from '../elements/multidelegation/PortfolioBar'; import PortfolioBarAssert from '../assert/multidelegation/PortfolioBarAssert'; import ChangingStakingPreferencesModalAssert from '../assert/multidelegation/ChangingStakingPreferencesModalAssert'; -import { StakePoolListColumnType, StakePoolSortingOptionType } from '../types/staking'; +import { StakePoolListColumnName, StakePoolSortingOptionType } from '../types/staking'; import SwitchingStakePoolModal from '../elements/staking/SwitchingStakePoolModal'; import MoreOptionsComponentAssert from '../assert/multidelegation/MoreOptionsComponentAssert'; +import { mapColumnNameStringToEnum } from '../utils/stakePoolListContent'; const validPassword = 'N_8J@bne87A'; @@ -235,15 +236,15 @@ Then(/^\(if applicable\) first stake pool search result has "([^"]*)" ticker$/, When( /^I hover over "(Ticker|Saturation|ROS|Cost|Margin|Blocks|Pledge|Live Stake)" column name in stake pool list$/, - async (columnName: StakePoolListColumnType) => { - await MultidelegationPage.hoverOverColumnWithName(columnName); + async (columnName: StakePoolListColumnName) => { + await MultidelegationPage.hoverOverColumn(mapColumnNameStringToEnum(columnName)); } ); Then( /^tooltip for "(Ticker|Saturation|ROS|Cost|Margin|Blocks|Pledge|Live Stake)" column is displayed$/, - async (columnName: StakePoolListColumnType) => { - await MultidelegationPageAssert.assertSeeTooltipForColumn(columnName); + async (columnName: StakePoolListColumnName) => { + await MultidelegationPageAssert.assertSeeTooltipForColumn(mapColumnNameStringToEnum(columnName)); } ); @@ -493,8 +494,8 @@ Then(/^I see (\d+) stake pool cards in a row$/, async (cardsCount: number) => { When( /^I click on stake pools table "(Ticker|Saturation|ROS|Cost|Margin|Blocks|Pledge|Live Stake)" column header$/, - async (headerName: StakePoolListColumnType) => { - await MultidelegationPage.clickOnColumnWithName(headerName); + async (headerName: StakePoolListColumnName) => { + await MultidelegationPage.clickOnColumn(mapColumnNameStringToEnum(headerName)); } ); @@ -504,9 +505,29 @@ When( await MultidelegationPage.moreOptionsComponent.selectSortingOption(sortingOption); } ); + Then( /^"More options" component with stake pool (sorting|filtering) options is displayed$/, async (tab: 'sorting' | 'filtering') => { await MoreOptionsComponentAssert.assertSeeMoreOptionsComponent(tab); } ); + +Then( + /^(ascending|descending) sorting indicator is displayed for "(Ticker|Saturation|ROS|Cost|Margin|Blocks|Pledge|Live Stake)" column$/, + async (order: 'ascending' | 'descending', sortingOption: StakePoolListColumnName) => { + await MultidelegationPageAssert.assertSeeColumnSortingIndicator(sortingOption, order); + } +); + +Then( + /^stake pool (list rows|cards) are sorted by "(Ticker|Saturation|ROS|Cost|Margin|Blocks|Pledge|Live Stake)" in (ascending|descending) order$/, + async ( + stakePoolsDisplayType: 'list rows' | 'cards', + sortingOption: StakePoolListColumnName, + order: 'ascending' | 'descending' + ) => { + const poolLimit = 100; // Limit verification to 100 stake pools due to time constraints + await MultidelegationPageAssert.assertSeeStakePoolsSorted(stakePoolsDisplayType, sortingOption, order, poolLimit); + } +); diff --git a/packages/e2e-tests/src/steps/stakingSteps.ts b/packages/e2e-tests/src/steps/stakingSteps.ts index f89e4f049..ba2382abc 100644 --- a/packages/e2e-tests/src/steps/stakingSteps.ts +++ b/packages/e2e-tests/src/steps/stakingSteps.ts @@ -1,13 +1,10 @@ import { Then, When } from '@cucumber/cucumber'; import stakingPageAssert from '../assert/stakingPageAssert'; import stakePoolDetailsAssert from '../assert/stakePoolDetailsAssert'; -import stakingExtendedPageObject from '../pageobject/stakingExtendedPageObject'; import drawerCommonExtendedAssert from '../assert/drawerCommonExtendedAssert'; import { getStakePoolById, getStakePoolByName, StakePoolsData } from '../data/expectedStakePoolsData'; import testContext from '../utils/testContext'; import transactionDetailsAssert, { ExpectedActivityDetails } from '../assert/transactionDetailsAssert'; -import { StakePoolListItem } from '../elements/staking/StakePoolListItem'; -import webTester from '../actor/webTester'; import StakingExitModalAssert from '../assert/stakingExitModalAssert'; import extensionUtils from '../utils/utils'; import stakingConfirmationScreenAssert from '../assert/stakingConfirmationScreenAssert'; @@ -125,12 +122,6 @@ Then(/^the stakepool drawer is opened with "([^"]*)" stake pool information$/, a await drawerCommonExtendedAssert.assertSeeDrawerWithTitle(poolName); }); -When(/^I click on the "(.*)" column header$/, async (listHeader: string) => { - const stakePoolListItem = new StakePoolListItem(); - await webTester.waitUntilSeeElement(stakePoolListItem.container(), 60_000); - await stakingExtendedPageObject.clickStakePoolListHeader(listHeader); -}); - // eslint-disable-next-line no-unused-vars,@typescript-eslint/no-unused-vars Then(/^The Tx details are displayed for Staking (with|without) metadata$/, async (_ignored: 'with' | 'without') => { // no need to distinguish between pools with/without metadata @@ -144,22 +135,6 @@ Then(/^The Tx details are displayed for Staking (with|without) metadata$/, async await transactionDetailsAssert.assertSeeActivityDetails(expectedActivityDetails); }); -Then( - /^the results are in (ascending|descending) order according to "([^"]*)" column$/, - async (order: 'ascending' | 'descending', column: string) => { - await stakingPageAssert.assertStakePoolItemsOrder(column, order); - } -); - -When(/^I reveal all stake pools$/, async () => { - await webTester.waitUntilSeeElement(new StakePoolListItem().container(), 60_000); - await stakingExtendedPageObject.revealAllStakePools(); -}); - -When(/^I save stake pool info$/, async () => { - await stakingExtendedPageObject.saveStakePoolInfo(); -}); - Then(/^Staking password screen is displayed$/, async () => { await stakingPageAssert.assertSeeStakingPasswordDrawer(); }); diff --git a/packages/e2e-tests/src/types/sortingOrder.ts b/packages/e2e-tests/src/types/sortingOrder.ts new file mode 100644 index 000000000..22b91c4cd --- /dev/null +++ b/packages/e2e-tests/src/types/sortingOrder.ts @@ -0,0 +1 @@ +export type SortingOrder = 'ascending' | 'descending'; diff --git a/packages/e2e-tests/src/types/staking.ts b/packages/e2e-tests/src/types/staking.ts index be72dc088..d8edd320b 100644 --- a/packages/e2e-tests/src/types/staking.ts +++ b/packages/e2e-tests/src/types/staking.ts @@ -1,4 +1,4 @@ -export type StakePoolListColumnType = +export type StakePoolListColumnName = | 'Ticker' | 'Saturation' | 'ROS' diff --git a/packages/e2e-tests/src/utils/stakePoolListContent.ts b/packages/e2e-tests/src/utils/stakePoolListContent.ts index 4151e756c..24738e188 100644 --- a/packages/e2e-tests/src/utils/stakePoolListContent.ts +++ b/packages/e2e-tests/src/utils/stakePoolListContent.ts @@ -1,104 +1,138 @@ -import { Asset } from '../data/Asset'; +import type { SortingOrder } from '../types/sortingOrder'; +import type { StakePoolListColumnName } from '../types/staking'; +import { StakePoolListColumn } from '../enums/StakePoolListColumn'; -interface Cost { - percentage: number; - ada: number; +interface AbbreviatedValue { + value: number; + suffix: '-' | 'K' | 'M'; } +const suffixOrderPriority = { + '-': 0, + K: 1, + M: 2 +}; + const emojiRegex = - // eslint-disable-next-line max-len /([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g; -const parseCostStringToObject = (cost: string): Cost => { - let parsedItem: Cost = { percentage: 0, ada: 0 }; - if (cost.includes('%') && cost.includes('ADA')) { - const splitItem = cost.split('+'); - parsedItem = { - percentage: Number.parseFloat(splitItem[0].replace(/%/, '')), - ada: Number.parseFloat(splitItem[1].replace(/ADA/, '')) - }; - } +const sortTickerColumnContent = (columnContent: string[], order: SortingOrder): string[] => { + const itemsWithNoTicker = columnContent.filter((item) => item === '-'); + const itemsWithTicker = columnContent.filter((item) => item !== '-'); - if (cost.includes('%') && !cost.includes(Asset.CARDANO.ticker)) { - parsedItem = { - percentage: Number.parseFloat(cost.replace(/%/, '')), - ada: 0 - }; - } + const sortedItems = [...itemsWithTicker].sort((a, b) => { + const nameA = a.replace(emojiRegex, '').replace(' ', '').trim(); + const nameB = b.replace(emojiRegex, '').replace(' ', '').trim(); + return nameA.localeCompare(nameB); + }); - if (!cost.includes('%') && cost.includes(Asset.CARDANO.ticker)) { - parsedItem = { - percentage: 0, - ada: Number.parseFloat(cost.replace(/ADA/, '')) - }; + if (order === 'descending') { + sortedItems.reverse(); } - return parsedItem; + sortedItems.push(...itemsWithNoTicker); + + return sortedItems; }; -const parseCostObjectToString = (cost: Cost): string => { - let parsedItem = `${Number(cost.percentage).toFixed(2)}%`; +const sortBlocksColumnContent = (columnContent: string[], order: SortingOrder): string[] => { + const parsedColumnContent = columnContent.map((item) => Number(item.replace(',', ''))); + const sortedColumnContent = [...parsedColumnContent].sort((a, b) => a - b); - if (cost.ada > 0) { - parsedItem = `${parsedItem} + ${Number(cost.ada)}${Asset.CARDANO.ticker}`; + if (order === 'descending') { + sortedColumnContent.reverse(); } - return parsedItem; + return sortedColumnContent.map((item) => item.toLocaleString()); }; -export const sortNameColumn = (columnContent: string[], order: string): string[] => { - const itemsWithNoName = columnContent.filter((item) => item === '-'); - const itemsWithName = columnContent.filter((item) => item !== '-'); - - const sortedItems = [...itemsWithName].sort((a, b) => { - const nameA = a.replace(emojiRegex, '').replace(' ', '').trim(); - const nameB = b.replace(emojiRegex, '').replace(' ', '').trim(); - return nameA.localeCompare(nameB); - }); - if (order === 'descending') { - sortedItems.reverse(); +const parseValueFromColumnIntoAbbreviatedValueObject = (valueFromColumn: string): AbbreviatedValue => { + if (valueFromColumn.endsWith('K')) { + return { + value: Number(valueFromColumn.slice(0, -1)), + suffix: 'K' + }; + } + if (valueFromColumn.endsWith('M')) { + return { + value: Number(valueFromColumn.slice(0, -1)), + suffix: 'M' + }; } - sortedItems.push(...itemsWithNoName); + return { + value: Number(valueFromColumn), + suffix: '-' + }; +}; - return sortedItems; +const parseAbbreviatedValueObjectIntoString = (abbreviatedValueObject: AbbreviatedValue): string => + `${abbreviatedValueObject.value}${ + ['K', 'M'].includes(abbreviatedValueObject.suffix) ? abbreviatedValueObject.suffix : '' + }`; + +const compareAbbreviatedValues = (abbreviatedValue1: AbbreviatedValue, abbreviatedValue2: AbbreviatedValue): number => { + if (suffixOrderPriority[abbreviatedValue1.suffix] - suffixOrderPriority[abbreviatedValue2.suffix] === 0) { + return abbreviatedValue1.value - abbreviatedValue2.value; + } + return suffixOrderPriority[abbreviatedValue1.suffix] - suffixOrderPriority[abbreviatedValue2.suffix]; }; -export const sortCostColumn = (columnContent: string[], order: string): string[] => { - const parsedColumnContent = columnContent.map((item) => parseCostStringToObject(item)); - const costSorted = [...parsedColumnContent].sort((a, b) => a.ada - b.ada || a.percentage - b.percentage); +const sortColumnWithPercentageValues = (columnContent: string[], order: string): string[] => { + const parsedColumnContent = columnContent.map((item) => Number(item.replace(/%/, '')).toFixed(2)); + const sortedColumnContent = [...parsedColumnContent].sort((a, b) => Number(a) - Number(b)); + if (order === 'descending') { - costSorted.reverse(); + sortedColumnContent.reverse(); } - return costSorted.map((item) => parseCostObjectToString(item)); + + return sortedColumnContent.map((item) => String(`${item}%`)); }; -export const sortColumnWithPercentageValues = (columnContent: string[], order: string): string[] => { - const columnContentWithNumbers = columnContent.map((item) => Number.parseFloat(item.replace(/%/, ''))); - const sortedColumnContentWithNumbers = [...columnContentWithNumbers].sort((a, b) => a - b); +const sortColumnWithAbbreviatedNumbers = (columnContent: string[], order: string): string[] => { + const parsedColumnContent: AbbreviatedValue[] = columnContent.map((item) => + parseValueFromColumnIntoAbbreviatedValueObject(item) + ); + const sortedColumnContent = [...parsedColumnContent].sort((a, b) => compareAbbreviatedValues(a, b)); + if (order === 'descending') { - sortedColumnContentWithNumbers.reverse(); + sortedColumnContent.reverse(); } - return sortedColumnContentWithNumbers.map((item) => String(`${item}%`)); + + return sortedColumnContent.map((item) => parseAbbreviatedValueObjectIntoString(item)); }; export const sortColumnContent = async ( columnContent: string[], - columnName: string, - order: string + sortingOption: StakePoolListColumn, + order: SortingOrder ): Promise => { let sortedColumnContent: string[] = []; - if (columnName === 'name') { - sortedColumnContent = sortNameColumn(columnContent, order); - } - - if (['ros', 'saturation'].includes(columnName)) { - sortedColumnContent = sortColumnWithPercentageValues(columnContent, order); - } - - if (columnName === 'cost') { - sortedColumnContent = sortCostColumn(columnContent, order); + switch (sortingOption) { + case StakePoolListColumn.Ticker: + sortedColumnContent = sortTickerColumnContent(columnContent, order); + break; + case StakePoolListColumn.Saturation: + case StakePoolListColumn.ROS: + case StakePoolListColumn.Margin: + sortedColumnContent = sortColumnWithPercentageValues(columnContent, order); + break; + case StakePoolListColumn.Blocks: + sortedColumnContent = sortBlocksColumnContent(columnContent, order); + break; + case StakePoolListColumn.Cost: + case StakePoolListColumn.Pledge: + case StakePoolListColumn.LiveStake: + sortedColumnContent = sortColumnWithAbbreviatedNumbers(columnContent, order); + break; + default: + throw new Error(`Unsupported sorting option: ${sortingOption}`); } return sortedColumnContent; }; + +export const mapColumnNameStringToEnum = (columnName: StakePoolListColumnName): StakePoolListColumn => + columnName === 'Live Stake' + ? StakePoolListColumn.LiveStake + : StakePoolListColumn[columnName as keyof typeof StakePoolListColumn];