diff --git a/packages/e2e-tests/src/assert/multidelegation/MultidelegationPageAssert.ts b/packages/e2e-tests/src/assert/multidelegation/MultidelegationPageAssert.ts index e2fef50b8..eddc5b525 100644 --- a/packages/e2e-tests/src/assert/multidelegation/MultidelegationPageAssert.ts +++ b/packages/e2e-tests/src/assert/multidelegation/MultidelegationPageAssert.ts @@ -6,6 +6,8 @@ import { TestnetPatterns } from '../../support/patterns'; import NetworkComponent from '../../elements/multidelegation/NetworkInfoComponent'; import { StakePoolListItem } from '../../elements/multidelegation/StakePoolListItem'; import Tooltip from '../../elements/Tooltip'; +import testContext from '../../utils/testContext'; +import { StakePoolGridCard } from '../../elements/multidelegation/StakePoolGridCard'; class MultidelegationPageAssert { assertSeeStakingOnPoolsCounter = async (poolsCount: number) => { @@ -257,6 +259,46 @@ class MultidelegationPageAssert { expect(await Tooltip.label.getText()).contains(`${currencyCode} Value`); expect(await Tooltip.value.getText()).to.match(TestnetPatterns.USD_VALUE_NO_SUFFIX_REGEX); // TODO: update when LW-8935 is resolved }; + + assertSeeStakePoolListRowSkeleton = async (shouldBeDisplayed: boolean) => { + await MultidelegationPage.stakePoolListRowSkeleton.waitForDisplayed({ reverse: !shouldBeDisplayed }); + }; + + assertSeeStakePoolGridCardSkeleton = async (shouldBeDisplayed: boolean) => { + await MultidelegationPage.stakePoolCardSkeleton.waitForDisplayed({ reverse: !shouldBeDisplayed }); + }; + + assertSeeStakePoolViewType = async (view: 'grid' | 'list') => { + const ariaChecked = 'aria-checked'; + switch (view) { + case 'grid': + await MultidelegationPage.gridViewToggle.waitForStable(); + await MultidelegationPage.gridContainer.waitForDisplayed(); + expect(await MultidelegationPage.gridViewToggle.getAttribute(ariaChecked)).to.equal('true'); + break; + case 'list': + await MultidelegationPage.listViewToggle.waitForStable(); + await MultidelegationPage.listContainer.waitForDisplayed(); + expect(await MultidelegationPage.listViewToggle.getAttribute(ariaChecked)).to.equal('true'); + break; + default: + throw new Error(`Unsupported view: ${view}`); + } + }; + + assertSeePreviouslySelectedStakePools = async (view: 'grid' | 'list') => { + await MultidelegationPage.searchLoader.waitForDisplayed({ reverse: true }); + const expectedTickers = testContext.load('selectedTickers') as string[]; + const selectedTickers = await MultidelegationPage.getTickersOfSelectedPools(view); + expect(selectedTickers).to.deep.equal(expectedTickers); + }; + + assertsSeeCardsInARow = async (expectedCardsCount: number) => { + const rowWidth = await MultidelegationPage.gridContainer.getSize('width'); + const cardWidth = await new StakePoolGridCard(0).container.getSize('width'); + const cardsInARow = Math.floor(rowWidth / cardWidth); + expect(cardsInARow).to.equal(expectedCardsCount); + }; } export default new MultidelegationPageAssert(); diff --git a/packages/e2e-tests/src/elements/multidelegation/MultidelegationPage.ts b/packages/e2e-tests/src/elements/multidelegation/MultidelegationPage.ts index b4ee47226..fcad7112d 100644 --- a/packages/e2e-tests/src/elements/multidelegation/MultidelegationPage.ts +++ b/packages/e2e-tests/src/elements/multidelegation/MultidelegationPage.ts @@ -9,6 +9,9 @@ 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'; class MultidelegationPage { private ACTIVITY_TAB = '[data-testid="activity-tab"]'; @@ -63,6 +66,12 @@ class MultidelegationPage { private MANAGE_BTN = '[data-testid="manage-btn"]'; private GRID_VIEW_TOGGLE = '[data-testid="grid-view-toggle"]'; private LIST_VIEW_TOGGLE = '[data-testid="list-view-toggle"]'; + private STAKE_POOLS_GRID_CONTAINER = '[data-testid="stake-pools-grid-container"]'; + private STAKE_POOLS_LIST_CONTAINER = '[data-testid="stake-pools-list-container"]'; + private STAKE_POOL_LIST_ROW_SKELETON = '[data-testid="stake-pool-list-row-skeleton"]'; + 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"]'; get title() { return SectionTitle.sectionTitle; @@ -88,6 +97,14 @@ class MultidelegationPage { return $(this.LIST_VIEW_TOGGLE); } + get gridContainer() { + return $(this.STAKE_POOLS_GRID_CONTAINER); + } + + get listContainer() { + return $(this.STAKE_POOLS_LIST_CONTAINER); + } + get delegationCardStatusLabel() { return $(this.DELEGATION_CARD_STATUS_LABEL); } @@ -256,6 +273,22 @@ class MultidelegationPage { return $$(this.DELEGATED_POOL_ITEM)[index].$(this.DELEGATED_POOL_LAST_REWARDS_VALUE); } + get stakePoolListRowSkeleton() { + return $(this.STAKE_POOL_LIST_ROW_SKELETON); + } + + get stakePoolCardSkeleton() { + return $(this.STAKE_POOL_CARD_SKELETON); + } + + get selectedPoolsInGridView() { + return $$(this.SELCECTED_STAKE_POOLS_IN_GRID_VIEW); + } + + get selectedPoolsInListView() { + return $$(this.SELCECTED_STAKE_POOLS_IN_LIST_VIEW); + } + async getPoolByTicker(ticker: string) { return (await this.displayedPools.find( async (item) => (await item.$(this.POOL_TICKER).getText()) === ticker @@ -297,6 +330,32 @@ class MultidelegationPage { } } + async selectPoolsForDelegation(numberOfPools: number, viewType: 'grid' | 'list') { + await this.searchLoader.waitForDisplayed({ reverse: true }); + await browser.pause(500); + switch (viewType) { + case 'grid': + for (let i = 0; i < numberOfPools; i++) { + await new StakePoolGridCard(i).click(); + if (i === 0) { + await StakePoolDetailsDrawer.selectPoolForMultiStakingButton.waitForClickable(); + await StakePoolDetailsDrawer.selectPoolForMultiStakingButton.click(); + } else { + await StakePoolDetailsDrawer.addStakingPollButton.waitForClickable(); + await StakePoolDetailsDrawer.addStakingPollButton.click(); + } + } + break; + case 'list': + for (let i = 0; i < numberOfPools; i++) { + await new StakePoolListItem(i).clickOnCheckbox(); + } + break; + default: + throw new Error(`Unsupported view: ${viewType}`); + } + } + async fillSearch(searchTerm: string) { await this.stakingPageSearchInput.waitForStable(); await this.stakingPageSearchInput.waitForClickable(); @@ -402,15 +461,49 @@ class MultidelegationPage { case 'grid': await this.gridViewToggle.waitForClickable(); await this.gridViewToggle.click(); + await this.gridViewToggle.waitForStable(); break; case 'list': await this.listViewToggle.waitForClickable(); await this.listViewToggle.click(); + await this.listViewToggle.waitForStable(); break; default: throw new Error(`Unsupported view: ${viewType}`); } } + + async getTickersOfSelectedPools(viewType: 'grid' | 'list') { + const tickers: string[] = []; + switch (viewType) { + case 'grid': + { + await this.selectedPoolsInGridView[0].waitForStable(); + const selectedPools = await this.selectedPoolsInGridView; + for (const pool of selectedPools) { + const ticker = await new StakePoolGridCard(pool.index, true).title.getText(); + tickers.push(ticker); + } + } + break; + case 'list': { + const selectedPools = await this.selectedPoolsInListView; + for (const pool of selectedPools) { + const ticker = await new StakePoolListItem(pool.index, true).ticker.getText(); + tickers.push(ticker); + } + break; + } + default: + throw new Error(`Unsupported view: ${viewType}`); + } + return tickers; + } + + async saveTickers(viewType: 'grid' | 'list') { + const selectedTickers = await this.getTickersOfSelectedPools(viewType); + testContext.save('selectedTickers', selectedTickers); + } } export default new MultidelegationPage(); diff --git a/packages/e2e-tests/src/elements/multidelegation/StakePoolDetailsDrawer.ts b/packages/e2e-tests/src/elements/multidelegation/StakePoolDetailsDrawer.ts index 2d4f7741b..cc768f259 100644 --- a/packages/e2e-tests/src/elements/multidelegation/StakePoolDetailsDrawer.ts +++ b/packages/e2e-tests/src/elements/multidelegation/StakePoolDetailsDrawer.ts @@ -40,6 +40,7 @@ class StakePoolDetailsDrawer extends CommonDrawerElements { private STAKE_ALL_ON_THIS_POOL_BUTTON = '[data-testid="stake-pool-details-stake-btn"]'; private MANAGE_DELEGATION_BUTTON = '[data-testid="stake-pool-details-manage-delegation-btn"]'; private SELECT_POOL_FOR_MULTISTAKING_BUTTON = '[data-testid="stake-pool-details-select-for-multi-staking-btn"]'; + private ADD_STAKING_POOL_BUTTON = '[data-testid="stake-pool-details-add-staking-pool-btn"]'; private TOOLTIP = '.ant-tooltip'; get container(): ChainablePromiseElement { @@ -178,6 +179,10 @@ class StakePoolDetailsDrawer extends CommonDrawerElements { return $(this.SELECT_POOL_FOR_MULTISTAKING_BUTTON); } + get addStakingPollButton(): ChainablePromiseElement { + return $(this.ADD_STAKING_POOL_BUTTON); + } + get manageDelegationButton() { return $(this.MANAGE_DELEGATION_BUTTON); } diff --git a/packages/e2e-tests/src/elements/multidelegation/StakePoolGridCard.ts b/packages/e2e-tests/src/elements/multidelegation/StakePoolGridCard.ts new file mode 100644 index 000000000..5eecd0605 --- /dev/null +++ b/packages/e2e-tests/src/elements/multidelegation/StakePoolGridCard.ts @@ -0,0 +1,29 @@ +/* eslint-disable no-undef */ +import { ChainablePromiseElement } from 'webdriverio'; + +export class StakePoolGridCard { + private SELECTED_POOLS_LIST = '[data-testid="selected-pools-list"]'; + private AVAILABLE_POOLS_LIST = '[data-testid="stake-pool-list-scroll-wrapper"]'; + private CARD = '[data-testid="stake-pool-card"]'; + private CARD_TITLE = '[data-testid="stake-pool-card-title"]'; + + protected card; + + constructor(index = 0, isOnSelectedPoolsList = false) { + this.card = $(isOnSelectedPoolsList ? this.SELECTED_POOLS_LIST : this.AVAILABLE_POOLS_LIST).$$(this.CARD)[index]; + } + + get container(): ChainablePromiseElement { + return this.card; + } + + get title(): ChainablePromiseElement { + return this.card.$(this.CARD_TITLE); + } + + async click(): Promise { + await this.card.scrollIntoView(); + await this.card.waitForClickable(); + await this.card.click(); + } +} diff --git a/packages/e2e-tests/src/elements/multidelegation/StakePoolListItem.ts b/packages/e2e-tests/src/elements/multidelegation/StakePoolListItem.ts index 7b8c6a207..7ab1ff852 100644 --- a/packages/e2e-tests/src/elements/multidelegation/StakePoolListItem.ts +++ b/packages/e2e-tests/src/elements/multidelegation/StakePoolListItem.ts @@ -2,7 +2,9 @@ import { ChainablePromiseElement } from 'webdriverio'; export class StakePoolListItem { - private LIST_ITEM = '[data-testid="stake-pool-list-scroll-wrapper"] [data-testid="stake-pool-item"]'; + 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"]'; private ROS = '[data-testid="stake-pool-list-apy"]'; @@ -15,8 +17,10 @@ export class StakePoolListItem { protected listItem; - constructor(index = 0) { - this.listItem = $$(this.LIST_ITEM)[index]; + constructor(index = 0, isOnSelectedPoolsList = false) { + this.listItem = $(isOnSelectedPoolsList ? this.SELECTED_POOLS_LIST : this.AVAILABLE_POOLS_LIST).$$(this.LIST_ITEM)[ + index + ]; } get container(): ChainablePromiseElement { @@ -58,4 +62,9 @@ export class StakePoolListItem { get liveStake(): ChainablePromiseElement { return this.listItem.$(this.LIVE_STAKE); } + + async clickOnCheckbox(): Promise { + await this.checkbox.waitForClickable(); + await this.checkbox.click(); + } } diff --git a/packages/e2e-tests/src/features/MultiDelegationPageExtended.feature b/packages/e2e-tests/src/features/MultiDelegationPageExtended.feature index 44a3bf387..b1f859604 100644 --- a/packages/e2e-tests/src/features/MultiDelegationPageExtended.feature +++ b/packages/e2e-tests/src/features/MultiDelegationPageExtended.feature @@ -145,3 +145,63 @@ Feature: Staking Page - Extended View And I switch to list view on "Browse pools" tab And I wait for stake pool list to be populated Then each stake pool list item contains: checkbox, ticker, saturation, ROS, cost, margin, blocks, pledge and live stake + + @LW-9985 @Testnet @Mainnet @skip + # TODO: enable when USE_MULTI_DELEGATION_STAKING_GRID_VIEW=true by default + Scenario: Extended View - Stake pool list - display skeleton while loading list elements + And I am on Staking extended page + And I open Browse pools tab + And I switch to list view on "Browse pools" tab + And I wait for stake pool list to be populated + When I scroll down 500 pixels + Then stake pool list row skeleton is displayed + When I wait 500 milliseconds + Then stake pool list row skeleton is not displayed + + @LW-9986 @Testnet @Mainnet @skip + # TODO: enable when USE_MULTI_DELEGATION_STAKING_GRID_VIEW=true by default + Scenario: Extended View - Stake pool grid - display skeleton while loading grid cards + And I am on Staking extended page + And I open Browse pools tab + And I switch to grid view on "Browse pools" tab + When I scroll down 500 pixels + Then stake pool grid card skeleton is displayed + When I wait 500 milliseconds + Then stake pool grid card skeleton is not displayed + + @LW-9995 @Testnet @Mainnet @skip + # TODO: enable when USE_MULTI_DELEGATION_STAKING_GRID_VIEW=true by default + Scenario Outline: Extended View - Browse pools - preserve selected pools and view type + When I am on Staking extended page + And I open Browse pools tab + And I switch to view on "Browse pools" tab + Then stake pool view is displayed + When I select 5 stake pools from view + And I save tickers of selected pools in view + When + And I open Browse pools tab + Then stake pool view is displayed + And previously selected pools are still selected in view + Examples: + | view | action | + | grid | I refresh the page | + | grid | I open Overview tab | + | list | I refresh the page | + | list | I open Overview tab | + + @LW-9996 @Testnet @Mainnet @skip + # TODO: enable when USE_MULTI_DELEGATION_STAKING_GRID_VIEW=true by default + Scenario: Extended View - Grid - display stake pool cards based on browser width + When I am on Staking extended page + And I open Browse pools tab + And I switch to grid view on "Browse pools" tab + Then stake pool grid view is displayed + Then I see 5 stake pool cards in a row + When I resize the window to a width of: 1660 and a height of: 1080 + Then I see 5 stake pool cards in a row + When I resize the window to a width of: 1659 and a height of: 1080 + Then I see 4 stake pool cards in a row + When I resize the window to a width of: 1024 and a height of: 1080 + Then I see 4 stake pool cards in a row + When I resize the window to a width of: 1023 and a height of: 1080 + Then I see 3 stake pool cards in a row diff --git a/packages/e2e-tests/src/steps/commonSteps.ts b/packages/e2e-tests/src/steps/commonSteps.ts index 6c719f89b..115ab7d90 100755 --- a/packages/e2e-tests/src/steps/commonSteps.ts +++ b/packages/e2e-tests/src/steps/commonSteps.ts @@ -316,3 +316,8 @@ Then(/^I verify there are no errors in console logs$/, async () => { Then(/^I wait (\d*) milliseconds$/, async (delay: 1000) => { await browser.pause(delay); }); + +When(/^I scroll (down|up) (\d*) pixels$/, async (direction: 'down' | 'up', pixels: number) => { + const y = direction === 'down' ? Number(pixels) : -Number(pixels); + await browser.scroll(0, y); +}); diff --git a/packages/e2e-tests/src/steps/multidelegationSteps.ts b/packages/e2e-tests/src/steps/multidelegationSteps.ts index c6f8e852a..e06f70233 100644 --- a/packages/e2e-tests/src/steps/multidelegationSteps.ts +++ b/packages/e2e-tests/src/steps/multidelegationSteps.ts @@ -463,3 +463,31 @@ When(/^I switch to (grid|list) view on "Browse pools" tab$/, async (viewType: 'g await MultidelegationPage.switchPoolsView(viewType); } }); + +Then(/^stake pool list row skeleton (is|is not) displayed$/, async (status: 'is' | 'is not') => { + await MultidelegationPageAssert.assertSeeStakePoolListRowSkeleton(status === 'is'); +}); + +Then(/^stake pool grid card skeleton (is|is not) displayed$/, async (status: 'is' | 'is not') => { + await MultidelegationPageAssert.assertSeeStakePoolGridCardSkeleton(status === 'is'); +}); + +Then(/^stake pool (grid|list) view is displayed$/, async (view: 'grid' | 'list') => { + await MultidelegationPageAssert.assertSeeStakePoolViewType(view); +}); + +When(/^I select (\d+) stake pools from (grid|list) view$/, async (numberOfPools: number, viewType: 'grid' | 'list') => { + await MultidelegationPage.selectPoolsForDelegation(Number(numberOfPools), viewType); +}); + +When(/^I save tickers of selected pools in (grid|list) view$/, async (viewType: 'grid' | 'list') => { + await MultidelegationPage.saveTickers(viewType); +}); + +Then(/^previously selected pools are still selected in (grid|list) view$/, async (viewType: 'grid' | 'list') => { + await MultidelegationPageAssert.assertSeePreviouslySelectedStakePools(viewType); +}); + +Then(/^I see (\d+) stake pool cards in a row$/, async (cardsCount: number) => { + await MultidelegationPageAssert.assertsSeeCardsInARow(Number(cardsCount)); +}); diff --git a/packages/staking/src/features/BrowsePools/StakePoolCard/PoolMetric/PoolMetric.tsx b/packages/staking/src/features/BrowsePools/StakePoolCard/PoolMetric/PoolMetric.tsx index 9ebfd2dd9..53c3b9db1 100644 --- a/packages/staking/src/features/BrowsePools/StakePoolCard/PoolMetric/PoolMetric.tsx +++ b/packages/staking/src/features/BrowsePools/StakePoolCard/PoolMetric/PoolMetric.tsx @@ -11,19 +11,25 @@ interface Props { } const iconsByType: Record = { - [MetricType.blocks]: , - [MetricType.cost]: , - [MetricType.liveStake]: LS, - [MetricType.margin]: , - [MetricType.pledge]: , + [MetricType.blocks]: , + [MetricType.cost]: , + [MetricType.liveStake]: ( + + LS + + ), + [MetricType.margin]: , + [MetricType.pledge]: , [MetricType.ticker]: null, [MetricType.saturation]: null, [MetricType.apy]: null, }; export const PoolMetric = ({ metricType, metricValue }: Props) => ( - + {iconsByType[metricType]} - {metricValue} + + {metricValue} + ); diff --git a/packages/staking/src/features/BrowsePools/StakePoolCard/SkatePoolCardProgressBar/StakePoolCardProgressBar.tsx b/packages/staking/src/features/BrowsePools/StakePoolCard/SkatePoolCardProgressBar/StakePoolCardProgressBar.tsx index 599ad89ec..04dd7dc6d 100644 --- a/packages/staking/src/features/BrowsePools/StakePoolCard/SkatePoolCardProgressBar/StakePoolCardProgressBar.tsx +++ b/packages/staking/src/features/BrowsePools/StakePoolCard/SkatePoolCardProgressBar/StakePoolCardProgressBar.tsx @@ -24,10 +24,10 @@ export const StakePoolCardProgressBar = ({ percentage, dataTestId }: Props) => { justifyContent="space-between" className={styles.wrapper} > -
+
- + {!Number.isNaN(percentageNumber) ? `${percentage}%` : t('browsePools.stakePoolGrid.notAvailable')} diff --git a/packages/staking/src/features/BrowsePools/StakePoolCard/StakePoolCard.tsx b/packages/staking/src/features/BrowsePools/StakePoolCard/StakePoolCard.tsx index f5e8ada25..c03c2bef5 100644 --- a/packages/staking/src/features/BrowsePools/StakePoolCard/StakePoolCard.tsx +++ b/packages/staking/src/features/BrowsePools/StakePoolCard/StakePoolCard.tsx @@ -22,10 +22,14 @@ export const StakePoolCard = ({ selected, onClick, }: StakePoolCardProps) => ( - + - + {title} {metricValue && } diff --git a/packages/staking/src/features/BrowsePools/StakePoolCard/StakePoolCardSkeleton.tsx b/packages/staking/src/features/BrowsePools/StakePoolCard/StakePoolCardSkeleton.tsx index 0f1dfbb6a..4b5fdf972 100644 --- a/packages/staking/src/features/BrowsePools/StakePoolCard/StakePoolCardSkeleton.tsx +++ b/packages/staking/src/features/BrowsePools/StakePoolCard/StakePoolCardSkeleton.tsx @@ -11,5 +11,8 @@ interface Props { const defaultFadeScale = 5; export const StakePoolCardSkeleton = ({ index = 0, fadeScale = defaultFadeScale }: Props) => ( - + ); diff --git a/packages/staking/src/features/BrowsePools/StakePoolsGrid/StakePoolsGrid.tsx b/packages/staking/src/features/BrowsePools/StakePoolsGrid/StakePoolsGrid.tsx index 877a0ac99..5ab16e538 100644 --- a/packages/staking/src/features/BrowsePools/StakePoolsGrid/StakePoolsGrid.tsx +++ b/packages/staking/src/features/BrowsePools/StakePoolsGrid/StakePoolsGrid.tsx @@ -89,7 +89,7 @@ export const StakePoolsGrid = ({ {t('browsePools.stakePoolGrid.selected')} - + {selectedPools.map((pool) => ( ))} diff --git a/packages/staking/src/features/BrowsePools/StakePoolsList/StakePoolsList.tsx b/packages/staking/src/features/BrowsePools/StakePoolsList/StakePoolsList.tsx index b27994a95..0a82a2ef9 100644 --- a/packages/staking/src/features/BrowsePools/StakePoolsList/StakePoolsList.tsx +++ b/packages/staking/src/features/BrowsePools/StakePoolsList/StakePoolsList.tsx @@ -44,7 +44,14 @@ export const StakePoolsList = ({ )} {selectedPools?.length > 0 && ( - + {selectedPools.map((pool) => ( ))} diff --git a/packages/staking/src/features/BrowsePools/StakePoolsList/StakePoolsListRowSkeleton/StakePoolsListRowSkeleton.tsx b/packages/staking/src/features/BrowsePools/StakePoolsList/StakePoolsListRowSkeleton/StakePoolsListRowSkeleton.tsx index 0827dcfe1..7179d2929 100644 --- a/packages/staking/src/features/BrowsePools/StakePoolsList/StakePoolsListRowSkeleton/StakePoolsListRowSkeleton.tsx +++ b/packages/staking/src/features/BrowsePools/StakePoolsList/StakePoolsListRowSkeleton/StakePoolsListRowSkeleton.tsx @@ -17,7 +17,7 @@ export const StakePoolsListRowSkeleton = ({ withSelection, }: StakePoolsListRowSkeletonProps) => (