Skip to content

Commit 6aa6964

Browse files
authored
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
1 parent c30c551 commit 6aa6964

18 files changed

+396
-416
lines changed

packages/e2e-tests/src/assert/multidelegation/MultidelegationPageAssert.ts

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import { StakePoolListItem } from '../../elements/multidelegation/StakePoolListI
88
import Tooltip from '../../elements/Tooltip';
99
import testContext from '../../utils/testContext';
1010
import { StakePoolGridCard } from '../../elements/multidelegation/StakePoolGridCard';
11+
import { StakePoolListColumnName } from '../../types/staking';
12+
import { SortingOrder } from '../../types/sortingOrder';
13+
import { mapColumnNameStringToEnum, sortColumnContent } from '../../utils/stakePoolListContent';
14+
import { StakePoolListColumn } from '../../enums/StakePoolListColumn';
1115

1216
class MultidelegationPageAssert {
1317
assertSeeStakingOnPoolsCounter = async (poolsCount: number) => {
@@ -188,36 +192,37 @@ class MultidelegationPageAssert {
188192
expect(await firstStakePool.ticker.getText()).to.equal(expectedTicker);
189193
};
190194

191-
assertSeeTooltipForColumn = async (columnName: string) => {
195+
assertSeeTooltipForColumn = async (column: StakePoolListColumn) => {
196+
await MultidelegationPage.tooltip.waitForStable();
192197
await MultidelegationPage.tooltip.waitForDisplayed();
193198
let expectedTooltipText;
194-
switch (columnName) {
195-
case 'Ticker':
199+
switch (column) {
200+
case StakePoolListColumn.Ticker:
196201
expectedTooltipText = await t('browsePools.tooltips.ticker', 'staking');
197202
break;
198-
case 'Saturation':
203+
case StakePoolListColumn.Saturation:
199204
expectedTooltipText = await t('browsePools.tooltips.saturation', 'staking');
200205
break;
201-
case 'ROS':
206+
case StakePoolListColumn.ROS:
202207
expectedTooltipText = await t('browsePools.tooltips.ros', 'staking');
203208
break;
204-
case 'Cost':
209+
case StakePoolListColumn.Cost:
205210
expectedTooltipText = await t('browsePools.tooltips.cost', 'staking');
206211
break;
207-
case 'Margin':
212+
case StakePoolListColumn.Margin:
208213
expectedTooltipText = await t('browsePools.tooltips.margin', 'staking');
209214
break;
210-
case 'Blocks':
215+
case StakePoolListColumn.Blocks:
211216
expectedTooltipText = await t('browsePools.tooltips.blocks', 'staking');
212217
break;
213-
case 'Pledge':
218+
case StakePoolListColumn.Pledge:
214219
expectedTooltipText = await t('browsePools.tooltips.pledge', 'staking');
215220
break;
216-
case 'Live Stake':
221+
case StakePoolListColumn.LiveStake:
217222
expectedTooltipText = await t('browsePools.tooltips.liveStake', 'staking');
218223
break;
219224
default:
220-
throw new Error(`Unsupported column name: ${columnName}`);
225+
throw new Error(`Unsupported column name: ${column}`);
221226
}
222227
expect(await MultidelegationPage.tooltip.getText()).to.equal(expectedTooltipText);
223228
};
@@ -300,6 +305,39 @@ class MultidelegationPageAssert {
300305
const cardsInARow = Math.floor(rowWidth / cardWidth);
301306
expect(cardsInARow).to.equal(expectedCardsCount);
302307
};
308+
309+
assertSeeColumnSortingIndicator = async (column: StakePoolListColumnName, order: 'ascending' | 'descending') => {
310+
await (
311+
await MultidelegationPage.getColumnSortingIndicator(mapColumnNameStringToEnum(column), order)
312+
).waitForDisplayed();
313+
};
314+
315+
assertSeeStakePoolsSorted = async (
316+
stakePoolsDisplayType: 'list rows' | 'cards',
317+
sortingOption: StakePoolListColumnName,
318+
order: SortingOrder,
319+
poolLimit?: number
320+
) => {
321+
await MultidelegationPage.waitForPoolsCounterToBeGreaterThanZero();
322+
poolLimit ??= await MultidelegationPage.getNumberOfPoolsFromCounter();
323+
if (stakePoolsDisplayType === 'cards') {
324+
// TODO: add code to handle grid cards - LW-10284
325+
throw new Error('Please add validation for grid cards sorting');
326+
} else {
327+
const columnContent = await MultidelegationPage.extractColumnContent(
328+
mapColumnNameStringToEnum(sortingOption),
329+
poolLimit
330+
);
331+
const sortedColumnContent = await sortColumnContent(
332+
columnContent,
333+
mapColumnNameStringToEnum(sortingOption),
334+
order
335+
);
336+
337+
expect(columnContent).to.not.be.empty;
338+
expect(columnContent).to.deep.equal(sortedColumnContent);
339+
}
340+
};
303341
}
304342

305343
export default new MultidelegationPageAssert();

packages/e2e-tests/src/assert/stakingPageAssert.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
import StakingPage from '../elements/staking/stakingPage';
22
import { TestnetPatterns } from '../support/patterns';
3-
import webTester from '../actor/webTester';
43
import StakingInfoComponent from '../elements/staking/stakingInfoComponent';
54
import { t } from '../utils/translationService';
6-
import { StakePoolListItem } from '../elements/staking/StakePoolListItem';
75
import StakingSuccessDrawer from '../elements/staking/StakingSuccessDrawer';
8-
import { Logger } from '../support/logger';
9-
import StakingExtendedPageObject from '../pageobject/stakingExtendedPageObject';
10-
import { sortColumnContent } from '../utils/stakePoolListContent';
116
import { expect } from 'chai';
127
import { StakePool } from '../data/expectedStakePoolsData';
138
import StakingPasswordDrawer from '../elements/staking/StakingPasswordDrawer';
@@ -114,18 +109,6 @@ class StakingPageAssert {
114109
});
115110
};
116111

117-
assertStakePoolItemsOrder = async (columnName: string, order: string) => {
118-
const stakePoolListItem = new StakePoolListItem();
119-
await webTester.waitUntilSeeElement(stakePoolListItem.container(), 60_000);
120-
const columnContent: string[] = await StakingExtendedPageObject.extractColumnContent(columnName);
121-
Logger.log(`EXTRACTED DATA: ${columnContent}`);
122-
const sortedColumnContent = await sortColumnContent(columnContent, columnName, order);
123-
Logger.log(`SORTED DATA: ${sortedColumnContent}`);
124-
125-
expect(columnContent).to.not.be.empty;
126-
expect(columnContent).to.deep.equal(sortedColumnContent);
127-
};
128-
129112
assertSeeStakingPasswordDrawer = async () => {
130113
await StakingPasswordDrawer.title.waitForDisplayed();
131114
expect(await StakingPasswordDrawer.title.getText()).to.equal(

packages/e2e-tests/src/elements/multidelegation/MultidelegationPage.ts

Lines changed: 130 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import StakePoolDetails from '../staking/stakePoolDetails';
88
import testContext from '../../utils/testContext';
99
import { isPopupMode } from '../../utils/pageUtils';
1010
import CommonDrawerElements from '../CommonDrawerElements';
11-
import { StakePoolListColumnType } from '../../types/staking';
1211
import { StakePoolListItem } from './StakePoolListItem';
1312
import { StakePoolGridCard } from './StakePoolGridCard';
1413
import StakePoolDetailsDrawer from './StakePoolDetailsDrawer';
1514
import MoreOptionsComponent from './MoreOptionsComponent';
15+
import { StakePoolListColumn } from '../../enums/StakePoolListColumn';
1616

1717
class MultidelegationPage {
1818
private ACTIVITY_TAB = '[data-testid="activity-tab"]';
@@ -41,6 +41,7 @@ class MultidelegationPage {
4141
private COLUMN_HEADER_BLOCKS = '[data-testid="stake-pool-list-header-blocks"]';
4242
private COLUMN_HEADER_PLEDGE = '[data-testid="stake-pool-list-header-pledge"]';
4343
private COLUMN_HEADER_LIVE_STAKE = '[data-testid="stake-pool-list-header-liveStake"]';
44+
private COLUMN_SORTING_INDICATOR_TEMPLATE = '[data-testid="stake-pool-sort-order-###"]';
4445
private MANAGE_STAKING_BTN_NEXT = '[data-testid="preferences-next-button"]';
4546
private CONFIRMATION_BTN_NEXT = '[data-testid="stake-pool-confirmation-btn"]';
4647
private DELEGATED_POOL_ITEM = '[data-testid="delegated-pool-item"]';
@@ -73,6 +74,7 @@ class MultidelegationPage {
7374
private STAKE_POOL_CARD_SKELETON = '[data-testid="stake-pool-card-skeleton"]';
7475
private SELCECTED_STAKE_POOLS_IN_GRID_VIEW = '[data-testid="selected-pools-list"] [data-testid="stake-pool-card"]';
7576
private SELCECTED_STAKE_POOLS_IN_LIST_VIEW = '[data-testid="selected-pools-list"] [data-testid="stake-pool-item"]';
77+
private POOLS_COUNTER = '[data-testid="pools-counter"]';
7678

7779
get title() {
7880
return SectionTitle.sectionTitle;
@@ -214,6 +216,10 @@ class MultidelegationPage {
214216
return $(this.MANAGE_BTN);
215217
}
216218

219+
get poolsCounter() {
220+
return $(this.POOLS_COUNTER);
221+
}
222+
217223
delegatedPoolLogo(index: number): ChainablePromiseElement<WebdriverIO.Element> {
218224
return $$(this.DELEGATED_POOL_ITEM)[index].$(this.DELEGATED_POOL_LOGO);
219225
}
@@ -300,6 +306,43 @@ class MultidelegationPage {
300306
)) as WebdriverIO.Element;
301307
}
302308

309+
async getColumnSortingIndicator(columnName: StakePoolListColumn, order: 'ascending' | 'descending') {
310+
const orderDirection = order === 'ascending' ? 'asc' : 'desc';
311+
const orderDirectionSelector = `${this.COLUMN_SORTING_INDICATOR_TEMPLATE.replace('###', orderDirection)}`;
312+
let selector = '';
313+
314+
switch (columnName) {
315+
case StakePoolListColumn.Ticker:
316+
selector = `${this.COLUMN_HEADER_TICKER} ${orderDirectionSelector}`;
317+
break;
318+
case StakePoolListColumn.Saturation:
319+
selector = `${this.COLUMN_HEADER_SATURATION} ${orderDirectionSelector}`;
320+
break;
321+
case StakePoolListColumn.ROS:
322+
selector = `${this.COLUMN_HEADER_ROS} ${orderDirectionSelector}`;
323+
break;
324+
case StakePoolListColumn.Cost:
325+
selector = `${this.COLUMN_HEADER_COST} ${orderDirectionSelector}`;
326+
break;
327+
case StakePoolListColumn.Margin:
328+
selector = `${this.COLUMN_HEADER_MARGIN} ${orderDirectionSelector}`;
329+
break;
330+
case StakePoolListColumn.Blocks:
331+
selector = `${this.COLUMN_HEADER_BLOCKS} ${orderDirectionSelector}`;
332+
break;
333+
case StakePoolListColumn.Pledge:
334+
selector = `${this.COLUMN_HEADER_PLEDGE} ${orderDirectionSelector}`;
335+
break;
336+
case StakePoolListColumn.LiveStake:
337+
selector = `${this.COLUMN_HEADER_LIVE_STAKE} ${orderDirectionSelector}`;
338+
break;
339+
default:
340+
throw new Error(`Unsupported column name: ${columnName}`);
341+
}
342+
343+
return $(selector);
344+
}
345+
303346
async clickAndGetTabStateAttribute(tab: 'Overview' | 'Browse pools') {
304347
let tabElement;
305348
switch (tab) {
@@ -418,68 +461,69 @@ class MultidelegationPage {
418461
await poolItem.click();
419462
}
420463

421-
async hoverOverColumnWithName(columnName: StakePoolListColumnType) {
464+
async hoverOverColumn(column: StakePoolListColumn) {
422465
let header;
423-
switch (columnName) {
424-
case 'Ticker':
466+
467+
switch (column) {
468+
case StakePoolListColumn.Ticker:
425469
header = await this.columnHeaderTicker;
426470
break;
427-
case 'Saturation':
471+
case StakePoolListColumn.Saturation:
428472
header = await this.columnHeaderSaturation;
429473
break;
430-
case 'ROS':
474+
case StakePoolListColumn.ROS:
431475
header = await this.columnHeaderROS;
432476
break;
433-
case 'Cost':
477+
case StakePoolListColumn.Cost:
434478
header = await this.columnHeaderCost;
435479
break;
436-
case 'Margin':
480+
case StakePoolListColumn.Margin:
437481
header = await this.columnHeaderMargin;
438482
break;
439-
case 'Blocks':
483+
case StakePoolListColumn.Blocks:
440484
header = await this.columnHeaderBlocks;
441485
break;
442-
case 'Pledge':
486+
case StakePoolListColumn.Pledge:
443487
header = await this.columnHeaderPledge;
444488
break;
445-
case 'Live Stake':
489+
case StakePoolListColumn.LiveStake:
446490
header = await this.columnHeaderLiveStake;
447491
break;
448492
default:
449-
throw new Error(`Unsupported column name: ${columnName}`);
493+
throw new Error(`Unsupported column name: ${column}`);
450494
}
451495
// make hovering over ANTD component more stable
452496
await header?.$('span span span').moveTo();
453497
}
454498

455-
async clickOnColumnWithName(columnName: StakePoolListColumnType) {
456-
switch (columnName) {
457-
case 'Ticker':
499+
async clickOnColumn(column: StakePoolListColumn) {
500+
switch (column) {
501+
case StakePoolListColumn.Ticker:
458502
await this.columnHeaderTicker.click();
459503
break;
460-
case 'Saturation':
504+
case StakePoolListColumn.Saturation:
461505
await this.columnHeaderSaturation.click();
462506
break;
463-
case 'ROS':
507+
case StakePoolListColumn.ROS:
464508
await this.columnHeaderROS.click();
465509
break;
466-
case 'Cost':
510+
case StakePoolListColumn.Cost:
467511
await this.columnHeaderCost.click();
468512
break;
469-
case 'Margin':
513+
case StakePoolListColumn.Margin:
470514
await this.columnHeaderMargin.click();
471515
break;
472-
case 'Blocks':
516+
case StakePoolListColumn.Blocks:
473517
await this.columnHeaderBlocks.click();
474518
break;
475-
case 'Pledge':
519+
case StakePoolListColumn.Pledge:
476520
await this.columnHeaderPledge.click();
477521
break;
478-
case 'Live Stake':
522+
case StakePoolListColumn.LiveStake:
479523
await this.columnHeaderLiveStake.click();
480524
break;
481525
default:
482-
throw new Error(`Unsupported column name: ${columnName}`);
526+
throw new Error(`Unsupported column name: ${column}`);
483527
}
484528
}
485529

@@ -543,6 +587,69 @@ class MultidelegationPage {
543587
const selectedTickers = await this.getTickersOfSelectedPools(viewType);
544588
testContext.save('selectedTickers', selectedTickers);
545589
}
590+
591+
async getNumberOfPoolsFromCounter(): Promise<number> {
592+
const poolsCounterText = await this.poolsCounter.getText();
593+
return Number(Number(poolsCounterText.replace(/.*\(/, '').replace(')', '').replace(',', '')));
594+
}
595+
596+
async waitForPoolsCounterToBeGreaterThanZero(): Promise<void> {
597+
await this.poolsCounter.waitForDisplayed();
598+
await browser.waitUntil(async () => (await this.getNumberOfPoolsFromCounter()) > 0, {
599+
timeoutMsg: 'No stake pools!'
600+
});
601+
}
602+
603+
async extractColumnContent(columnName: StakePoolListColumn, poolLimit = 100): Promise<string[]> {
604+
const columnContent: string[] = [];
605+
606+
await this.listContainer.waitForStable();
607+
await browser.pause(500);
608+
609+
for (let i = 0; i < poolLimit; i++) {
610+
const displayedPoolsCounter = await this.displayedPools.length;
611+
const listItem = new StakePoolListItem(i);
612+
// Load more pools if all visible ones were processed
613+
if (i % (displayedPoolsCounter - 1) === 0) {
614+
await listItem.container.scrollIntoView();
615+
await this.stakePoolListRowSkeleton.waitForExist({
616+
reverse: true,
617+
interval: 100,
618+
timeout: 30_000
619+
});
620+
}
621+
switch (columnName) {
622+
case StakePoolListColumn.Ticker:
623+
columnContent.push(await listItem.ticker.getText());
624+
break;
625+
case StakePoolListColumn.Saturation:
626+
columnContent.push(await listItem.saturation.getText());
627+
break;
628+
case StakePoolListColumn.ROS:
629+
columnContent.push(await listItem.ros.getText());
630+
break;
631+
case StakePoolListColumn.Cost:
632+
columnContent.push(await listItem.cost.getText());
633+
break;
634+
case StakePoolListColumn.Margin:
635+
columnContent.push(await listItem.margin.getText());
636+
break;
637+
case StakePoolListColumn.Blocks:
638+
columnContent.push(await listItem.blocks.getText());
639+
break;
640+
case StakePoolListColumn.Pledge:
641+
columnContent.push(await listItem.pledge.getText());
642+
break;
643+
case StakePoolListColumn.LiveStake:
644+
columnContent.push(await listItem.liveStake.getText());
645+
break;
646+
default:
647+
throw new Error(`Not supported column name: ${columnName}`);
648+
}
649+
}
650+
651+
return columnContent;
652+
}
546653
}
547654

548655
export default new MultidelegationPage();

packages/e2e-tests/src/elements/multidelegation/StakePoolListItem.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { ChainablePromiseElement } from 'webdriverio';
33

44
export class StakePoolListItem {
55
private SELECTED_POOLS_LIST = '[data-testid="selected-pools-list"]';
6-
private AVAILABLE_POOLS_LIST = '[data-testid="stake-pool-list-scroll-wrapper"]';
76
private LIST_ITEM = '[data-testid="stake-pool-item"]';
87
private CHECKBOX = '[data-testid="stake-pool-list-checkbox"]';
98
private TICKER = '[data-testid="stake-pool-list-ticker"]';
@@ -18,9 +17,9 @@ export class StakePoolListItem {
1817
protected listItem;
1918

2019
constructor(index = 0, isOnSelectedPoolsList = false) {
21-
this.listItem = $(isOnSelectedPoolsList ? this.SELECTED_POOLS_LIST : this.AVAILABLE_POOLS_LIST).$$(this.LIST_ITEM)[
22-
index
23-
];
20+
this.listItem = $(
21+
isOnSelectedPoolsList ? `${this.SELECTED_POOLS_LIST} ${this.LIST_ITEM}` : `[data-item-index="${index}"]`
22+
);
2423
}
2524

2625
get container(): ChainablePromiseElement<WebdriverIO.Element | undefined> {

0 commit comments

Comments
 (0)