diff --git a/packages/app/src/features/actions/ActionsContainer.PageObject.ts b/packages/app/src/features/actions/ActionsContainer.PageObject.ts index c153359a6..0cd3c5e25 100644 --- a/packages/app/src/features/actions/ActionsContainer.PageObject.ts +++ b/packages/app/src/features/actions/ActionsContainer.PageObject.ts @@ -1,19 +1,17 @@ -import { Locator, Page, expect } from '@playwright/test' +import { Locator, expect } from '@playwright/test' import { formatPercentage } from '@/domain/common/format' import { BasePageObject } from '@/test/e2e/BasePageObject' -import { isPage } from '@/test/e2e/utils' +import { TestContext } from '@/test/e2e/setup' import { testIds } from '@/ui/utils/testIds' import { Percentage } from '@marsfoundation/common-universal' import { ActionType } from './logic/types' export class ActionsPageObject extends BasePageObject { - constructor(pageOrLocator: Page | Locator) { - if (isPage(pageOrLocator)) { - super(pageOrLocator) + constructor(testContext: TestContext, locator?: Locator) { + super(testContext, locator) + if (!locator) { this.region = this.locatePanelByHeader('Actions') - } else { - super(pageOrLocator) } } @@ -26,29 +24,23 @@ export class ActionsPageObject extends BasePageObject { } // #region actions - async acceptAllActionsAction( - expectedNumberOfActions: number, - updateBrowserAndNextBlockTime: (seconds: number) => Promise, - ): Promise { + async acceptAllActionsAction(expectedNumberOfActions: number): Promise { for (let index = 0; index < expectedNumberOfActions; index++) { const row = this.region.getByTestId(testIds.actions.row(index)) await row.getByRole('button', { name: actionButtonRegex }).click() await expect(row.getByRole('button', { name: actionButtonRegex })).not.toBeVisible() // @note: we are setting block timestamp of the next tx (especially after executing all txs) - await updateBrowserAndNextBlockTime(5) + await this.testContext.testnetController.progressSimulation(5) } } - async acceptActionAtIndex( - index: number, - updateBrowserAndNextBlockTime: (seconds: number) => Promise, - ): Promise { + async acceptActionAtIndex(index: number): Promise { const row = this.region.getByTestId(testIds.actions.row(index)) await row.getByRole('button', { name: actionButtonRegex }).click() await expect(row.getByRole('button', { name: actionButtonRegex })).not.toBeVisible() // @note: we are setting block timestamp of the next tx (especially after executing all txs) - await updateBrowserAndNextBlockTime(5) + await this.testContext.testnetController.progressSimulation(5) } async switchPreferPermitsAction(): Promise { diff --git a/packages/app/src/features/dialogs/claim-rewards/ClaimRewardsDialog.PageObject.ts b/packages/app/src/features/dialogs/claim-rewards/ClaimRewardsDialog.PageObject.ts index 86f024bd9..ca66a4daf 100644 --- a/packages/app/src/features/dialogs/claim-rewards/ClaimRewardsDialog.PageObject.ts +++ b/packages/app/src/features/dialogs/claim-rewards/ClaimRewardsDialog.PageObject.ts @@ -1,41 +1,41 @@ -import { Locator, Page, expect } from '@playwright/test' +// import { Locator, Page, expect } from '@playwright/test' -import { testIds } from '@/ui/utils/testIds' +// import { testIds } from '@/ui/utils/testIds' -import { DialogPageObject } from '../common/Dialog.PageObject' +// import { DialogPageObject } from '../common/Dialog.PageObject' -export class ClaimRewardsDialogPageObject extends DialogPageObject { - constructor(page: Page) { - super(page, /.*/) - this.region = this.locateDialogByHeader('Claim rewards') - } +// export class ClaimRewardsDialogPageObject extends DialogPageObject { +// constructor(page: Page) { +// super(page, /.*/) +// this.region = this.locateDialogByHeader('Claim rewards') +// } - // #region assertions - async expectRewards(rows: Reward[], locator?: Locator): Promise { - if (!locator) { - locator = this.region - } +// // #region assertions +// async expectRewards(rows: Reward[], locator?: Locator): Promise { +// if (!locator) { +// locator = this.region +// } - for (const [index, row] of rows.entries()) { - const rowLocator = this.page.getByTestId(testIds.dialog.claimRewards.transactionOverview.row(index)).first() - await expect(rowLocator.getByTestId(testIds.dialog.claimRewards.transactionOverview.amount)).toHaveText( - `${row.amount} ${row.tokenSymbol}`, - ) - await expect(rowLocator.getByTestId(testIds.dialog.claimRewards.transactionOverview.amountUSD)).toHaveText( - row.amountUSD, - ) - } - } +// for (const [index, row] of rows.entries()) { +// const rowLocator = this.page.getByTestId(testIds.dialog.claimRewards.transactionOverview.row(index)).first() +// await expect(rowLocator.getByTestId(testIds.dialog.claimRewards.transactionOverview.amount)).toHaveText( +// `${row.amount} ${row.tokenSymbol}`, +// ) +// await expect(rowLocator.getByTestId(testIds.dialog.claimRewards.transactionOverview.amountUSD)).toHaveText( +// row.amountUSD, +// ) +// } +// } - async expectClaimRewardsSuccessPage(rows: Reward[]): Promise { - await expect(this.page.getByRole('heading', { name: 'Congrats, all done!' })).toBeVisible() - await this.expectRewards(rows, this.page.getByTestId(testIds.dialog.success)) - } - // #endregion assertions -} +// async expectClaimRewardsSuccessPage(rows: Reward[]): Promise { +// await expect(this.page.getByRole('heading', { name: 'Congrats, all done!' })).toBeVisible() +// await this.expectRewards(rows, this.page.getByTestId(testIds.dialog.success)) +// } +// // #endregion assertions +// } -interface Reward { - tokenSymbol: string - amount: string - amountUSD: string -} +// interface Reward { +// tokenSymbol: string +// amount: string +// amountUSD: string +// } diff --git a/packages/app/src/features/dialogs/collateral/CollateralDialog.PageObject.ts b/packages/app/src/features/dialogs/collateral/CollateralDialog.PageObject.ts index 001997a65..a85392026 100644 --- a/packages/app/src/features/dialogs/collateral/CollateralDialog.PageObject.ts +++ b/packages/app/src/features/dialogs/collateral/CollateralDialog.PageObject.ts @@ -1,44 +1,44 @@ -import { Page, expect } from '@playwright/test' +// import { Page, expect } from '@playwright/test' -import { ActionsPageObject } from '@/features/actions/ActionsContainer.PageObject' -import { testIds } from '@/ui/utils/testIds' +// import { ActionsPageObject } from '@/features/actions/ActionsContainer.PageObject' +// import { testIds } from '@/ui/utils/testIds' -import { CollateralSetting } from '../collateral/types' -import { DialogPageObject } from '../common/Dialog.PageObject' +// import { CollateralSetting } from '../collateral/types' +// import { DialogPageObject } from '../common/Dialog.PageObject' -export class CollateralDialogPageObject extends DialogPageObject { - constructor(page: Page) { - super(page, /.*/) - this.region = this.locateDialogByHeader('Collateral') - } +// export class CollateralDialogPageObject extends DialogPageObject { +// constructor(page: Page) { +// super(page, /.*/) +// this.region = this.locateDialogByHeader('Collateral') +// } - // #region actions - async setUseAsCollateralAction({ - assetName, - setting, - updateBrowserAndNextBlockTime, - }: { - assetName: string - setting: CollateralSetting - updateBrowserAndNextBlockTime: () => Promise - }): Promise { - const actionsContainer = new ActionsPageObject(this.locatePanelByHeader('Actions')) - await actionsContainer.acceptAllActionsAction(1, updateBrowserAndNextBlockTime) +// // #region actions +// async setUseAsCollateralAction({ +// assetName, +// setting, +// updateBrowserAndNextBlockTime, +// }: { +// assetName: string +// setting: CollateralSetting +// updateBrowserAndNextBlockTime: () => Promise +// }): Promise { +// const actionsContainer = new ActionsPageObject(this.locatePanelByHeader('Actions')) +// await actionsContainer.acceptAllActionsAction(1, updateBrowserAndNextBlockTime) - // assertion used for waiting - if (setting === 'enabled') { - await this.expectSetUseAsCollateralSuccessPage(assetName, 'enabled') - } else { - await this.expectSetUseAsCollateralSuccessPage(assetName, 'disabled') - } - } - // #endregion actions +// // assertion used for waiting +// if (setting === 'enabled') { +// await this.expectSetUseAsCollateralSuccessPage(assetName, 'enabled') +// } else { +// await this.expectSetUseAsCollateralSuccessPage(assetName, 'disabled') +// } +// } +// // #endregion actions - // #region assertions - async expectSetUseAsCollateralSuccessPage(assetName: string, setting: CollateralSetting): Promise { - await expect(this.region.getByRole('heading', { name: 'Congrats, all done!' })).toBeVisible() - await expect(this.region.getByTestId(testIds.dialog.success)).toContainText(assetName) - await expect(this.region.getByTestId(testIds.dialog.success)).toContainText(`Collateral ${setting}`) - } - // #endregion assertions -} +// // #region assertions +// async expectSetUseAsCollateralSuccessPage(assetName: string, setting: CollateralSetting): Promise { +// await expect(this.region.getByRole('heading', { name: 'Congrats, all done!' })).toBeVisible() +// await expect(this.region.getByTestId(testIds.dialog.success)).toContainText(assetName) +// await expect(this.region.getByTestId(testIds.dialog.success)).toContainText(`Collateral ${setting}`) +// } +// // #endregion assertions +// } diff --git a/packages/app/src/features/dialogs/common/Dialog.PageObject.ts b/packages/app/src/features/dialogs/common/Dialog.PageObject.ts index ce5749236..2f74c63b3 100644 --- a/packages/app/src/features/dialogs/common/Dialog.PageObject.ts +++ b/packages/app/src/features/dialogs/common/Dialog.PageObject.ts @@ -1,22 +1,24 @@ -import { Locator, Page, expect } from '@playwright/test' +import { Locator, expect } from '@playwright/test' import { ActionsPageObject } from '@/features/actions/ActionsContainer.PageObject' import { BasePageObject } from '@/test/e2e/BasePageObject' import { TestTokenWithValue, expectAssets } from '@/test/e2e/assertions' -import { calculateAssetsWorth, isPage } from '@/test/e2e/utils' +import { TestContext } from '@/test/e2e/setup' +import { calculateAssetsWorth } from '@/test/e2e/utils' import { testIds } from '@/ui/utils/testIds' import { TestnetClient, getUrlFromClient } from '@marsfoundation/common-testnets' +export interface DialogPageObjectParams { + testContext: TestContext + header: RegExp +} + export class DialogPageObject extends BasePageObject { public readonly actionsContainer: ActionsPageObject - constructor(pageOrLocator: Page | Locator, header: RegExp) { - if (isPage(pageOrLocator)) { - super(pageOrLocator) - this.region = this.locateDialogByHeader(header) - } else { - super(pageOrLocator) - } - this.actionsContainer = new ActionsPageObject(this.locatePanelByHeader('Actions')) + constructor({ testContext, header }: DialogPageObjectParams) { + super(testContext) + this.region = this.locateDialogByHeader(header) + this.actionsContainer = new ActionsPageObject(testContext, this.locatePanelByHeader('Actions')) } getDialog(): Locator { diff --git a/packages/app/src/features/dialogs/convert-stables/ConvertStablesDialog.PageObject.ts b/packages/app/src/features/dialogs/convert-stables/ConvertStablesDialog.PageObject.ts index 7441df320..24e7bab72 100644 --- a/packages/app/src/features/dialogs/convert-stables/ConvertStablesDialog.PageObject.ts +++ b/packages/app/src/features/dialogs/convert-stables/ConvertStablesDialog.PageObject.ts @@ -1,123 +1,123 @@ -import { DialogPageObject, TxOverviewWithRoute } from '@/features/dialogs/common/Dialog.PageObject' -import { testIds } from '@/ui/utils/testIds' -import { Locator, Page, expect } from '@playwright/test' - -export class ConvertStablesDialogPageObject extends DialogPageObject { - constructor(page: Page) { - super(page, /Convert Tokens/) - } - - // # region locators - locateAssetInSelector(): Locator { - return this.region.getByTestId(testIds.component.AssetSelector.trigger).first() - } - - locateAssetOutSelector(): Locator { - return this.region.getByTestId(testIds.component.AssetSelector.trigger).last() - } - - locateAssetInInput(): Locator { - return this.region.getByTestId(testIds.component.AssetInput.input).first() - } - - locateAssetOutInput(): Locator { - return this.region.getByTestId(testIds.component.AssetInput.input).last() - } - - locateAssetInMaxButton(): Locator { - return this.region.getByTestId(testIds.component.AssetInput.maxButton).first() - } - - locateAssetOutMaxButton(): Locator { - return this.region.getByTestId(testIds.component.AssetInput.maxButton).last() - } - // #endregion locators - - // #region actions - async selectAssetInAction(asset: string): Promise { - const selector = this.locateAssetInSelector() - await this.selectOptionByLabelAction(selector, asset) - } - - async selectAssetOutAction(asset: string): Promise { - const selector = this.locateAssetOutSelector() - await this.selectOptionByLabelAction(selector, asset) - } - - async openAssetInSelectorAction(): Promise { - await this.locateAssetInSelector().click() - } - - async openAssetOutSelectorAction(): Promise { - await this.locateAssetOutSelector().click() - } - - async fillAmountInAction(amount: number): Promise { - await this.locateAssetInInput().fill(amount.toString()) - } - - async fillAmountOutAction(amount: number): Promise { - await this.locateAssetOutInput().fill(amount.toString()) - } - - async clickMaxAmountInAction(): Promise { - await this.locateAssetInMaxButton().click() - } - - async clickMaxAmountOutAction(): Promise { - await this.locateAssetOutMaxButton().click() - } - - async clickBackToSavingsButton(): Promise { - await this.page.getByRole('button', { name: 'Back to Savings' }).click() - await this.region.waitFor({ - state: 'detached', - }) - } - // #endregion actions - - // #region assertions - async expectSuccessPage(): Promise { - await expect(this.page.getByText('Congrats, all done!')).toBeVisible() - } - - async expectTransactionOverview(transactionOverview: TxOverviewWithRoute): Promise { - await this.expectTransactionOverviewRoute(transactionOverview.routeItems) - await this.expectOutcomeText(transactionOverview.outcome) - if (transactionOverview.outcomeUsd) { - await this.expectOutcomeUsdText(transactionOverview.outcomeUsd) - } - } - - async expectAssetInSelectorSelectedOption(option: string): Promise { - await expect(this.locateAssetInSelector()).toHaveText(option) - } - - async expectAssetOutSelectorSelectedOption(option: string): Promise { - await expect(this.locateAssetOutSelector()).toHaveText(option) - } - - async expectSelectorOptions(options: string[]): Promise { - const selectorOptions = await this.page.getByTestId(testIds.component.AssetSelector.option).all() - expect(selectorOptions).toHaveLength(options.length) - - for (const [index, option] of selectorOptions.entries()) { - await expect(option).toContainText(options[index]!) - } - } - - async expectAssetInInputValue(value: string): Promise { - await expect(this.locateAssetInInput()).toHaveValue(value) - } - - async expectAssetOutInputValue(value: string): Promise { - await expect(this.locateAssetOutInput()).toHaveValue(value) - } - - async expectSingleInputError(error: string): Promise { - const inputError = this.page.getByTestId(testIds.component.AssetInput.error) - await expect(inputError).toHaveCount(1) - await expect(inputError).toHaveText(error) - } - // #endregion assertions -} +// import { DialogPageObject, TxOverviewWithRoute } from '@/features/dialogs/common/Dialog.PageObject' +// import { testIds } from '@/ui/utils/testIds' +// import { Locator, Page, expect } from '@playwright/test' + +// export class ConvertStablesDialogPageObject extends DialogPageObject { +// constructor(page: Page) { +// super(page, /Convert Tokens/) +// } + +// // # region locators +// locateAssetInSelector(): Locator { +// return this.region.getByTestId(testIds.component.AssetSelector.trigger).first() +// } + +// locateAssetOutSelector(): Locator { +// return this.region.getByTestId(testIds.component.AssetSelector.trigger).last() +// } + +// locateAssetInInput(): Locator { +// return this.region.getByTestId(testIds.component.AssetInput.input).first() +// } + +// locateAssetOutInput(): Locator { +// return this.region.getByTestId(testIds.component.AssetInput.input).last() +// } + +// locateAssetInMaxButton(): Locator { +// return this.region.getByTestId(testIds.component.AssetInput.maxButton).first() +// } + +// locateAssetOutMaxButton(): Locator { +// return this.region.getByTestId(testIds.component.AssetInput.maxButton).last() +// } +// // #endregion locators + +// // #region actions +// async selectAssetInAction(asset: string): Promise { +// const selector = this.locateAssetInSelector() +// await this.selectOptionByLabelAction(selector, asset) +// } + +// async selectAssetOutAction(asset: string): Promise { +// const selector = this.locateAssetOutSelector() +// await this.selectOptionByLabelAction(selector, asset) +// } + +// async openAssetInSelectorAction(): Promise { +// await this.locateAssetInSelector().click() +// } + +// async openAssetOutSelectorAction(): Promise { +// await this.locateAssetOutSelector().click() +// } + +// async fillAmountInAction(amount: number): Promise { +// await this.locateAssetInInput().fill(amount.toString()) +// } + +// async fillAmountOutAction(amount: number): Promise { +// await this.locateAssetOutInput().fill(amount.toString()) +// } + +// async clickMaxAmountInAction(): Promise { +// await this.locateAssetInMaxButton().click() +// } + +// async clickMaxAmountOutAction(): Promise { +// await this.locateAssetOutMaxButton().click() +// } + +// async clickBackToSavingsButton(): Promise { +// await this.page.getByRole('button', { name: 'Back to Savings' }).click() +// await this.region.waitFor({ +// state: 'detached', +// }) +// } +// // #endregion actions + +// // #region assertions +// async expectSuccessPage(): Promise { +// await expect(this.page.getByText('Congrats, all done!')).toBeVisible() +// } + +// async expectTransactionOverview(transactionOverview: TxOverviewWithRoute): Promise { +// await this.expectTransactionOverviewRoute(transactionOverview.routeItems) +// await this.expectOutcomeText(transactionOverview.outcome) +// if (transactionOverview.outcomeUsd) { +// await this.expectOutcomeUsdText(transactionOverview.outcomeUsd) +// } +// } + +// async expectAssetInSelectorSelectedOption(option: string): Promise { +// await expect(this.locateAssetInSelector()).toHaveText(option) +// } + +// async expectAssetOutSelectorSelectedOption(option: string): Promise { +// await expect(this.locateAssetOutSelector()).toHaveText(option) +// } + +// async expectSelectorOptions(options: string[]): Promise { +// const selectorOptions = await this.page.getByTestId(testIds.component.AssetSelector.option).all() +// expect(selectorOptions).toHaveLength(options.length) + +// for (const [index, option] of selectorOptions.entries()) { +// await expect(option).toContainText(options[index]!) +// } +// } + +// async expectAssetInInputValue(value: string): Promise { +// await expect(this.locateAssetInInput()).toHaveValue(value) +// } + +// async expectAssetOutInputValue(value: string): Promise { +// await expect(this.locateAssetOutInput()).toHaveValue(value) +// } + +// async expectSingleInputError(error: string): Promise { +// const inputError = this.page.getByTestId(testIds.component.AssetInput.error) +// await expect(inputError).toHaveCount(1) +// await expect(inputError).toHaveText(error) +// } +// // #endregion assertions +// } diff --git a/packages/app/src/features/dialogs/e-mode/EModeDialog.PageObject.ts b/packages/app/src/features/dialogs/e-mode/EModeDialog.PageObject.ts index f6d3cd130..49bdd937f 100644 --- a/packages/app/src/features/dialogs/e-mode/EModeDialog.PageObject.ts +++ b/packages/app/src/features/dialogs/e-mode/EModeDialog.PageObject.ts @@ -1,122 +1,122 @@ -import { EModeCategoryName } from '@/domain/e-mode/types' -import { testIds } from '@/ui/utils/testIds' -import { Locator, Page, expect } from '@playwright/test' -import { DialogPageObject } from '../common/Dialog.PageObject' +// import { EModeCategoryName } from '@/domain/e-mode/types' +// import { testIds } from '@/ui/utils/testIds' +// import { Locator, Page, expect } from '@playwright/test' +// import { DialogPageObject } from '../common/Dialog.PageObject' -export class EModeDialogPageObject extends DialogPageObject { - constructor(page: Page) { - super(page, /.*/) - this.region = this.locateDialogByHeader('Set E-Mode Category') - } +// export class EModeDialogPageObject extends DialogPageObject { +// constructor(page: Page) { +// super(page, /.*/) +// this.region = this.locateDialogByHeader('Set E-Mode Category') +// } - // #region locators - locateEModeCategoryTile(eModeCategoryName: EModeCategoryName): Locator { - return this.region.getByRole('button', { name: eModeCategoryName }) - } - // #endregion locators +// // #region locators +// locateEModeCategoryTile(eModeCategoryName: EModeCategoryName): Locator { +// return this.region.getByRole('button', { name: eModeCategoryName }) +// } +// // #endregion locators - // #region actions - async clickEModeCategoryTileAction(eModeCategoryName: EModeCategoryName): Promise { - await this.locateEModeCategoryTile(eModeCategoryName).click() - } +// // #region actions +// async clickEModeCategoryTileAction(eModeCategoryName: EModeCategoryName): Promise { +// await this.locateEModeCategoryTile(eModeCategoryName).click() +// } - async setEModeAction({ - eModeCategoryName, - updateBrowserAndNextBlockTime, - }: { eModeCategoryName: EModeCategoryName; updateBrowserAndNextBlockTime: () => Promise }): Promise { - await this.clickEModeCategoryTileAction(eModeCategoryName) - await this.acknowledgeIfRiskIsPresent() - await this.actionsContainer.acceptAllActionsAction(1, updateBrowserAndNextBlockTime) - await this.expectEModeSuccessPage(eModeCategoryName) - await this.viewInMyPortfolioAction() - } - // #endregion actions +// async setEModeAction({ +// eModeCategoryName, +// updateBrowserAndNextBlockTime, +// }: { eModeCategoryName: EModeCategoryName; updateBrowserAndNextBlockTime: () => Promise }): Promise { +// await this.clickEModeCategoryTileAction(eModeCategoryName) +// await this.acknowledgeIfRiskIsPresent() +// await this.actionsContainer.acceptAllActionsAction(1, updateBrowserAndNextBlockTime) +// await this.expectEModeSuccessPage(eModeCategoryName) +// await this.viewInMyPortfolioAction() +// } +// // #endregion actions - // #region assertions - async expectEModeCategoryTileStatus( - eModeCategoryName: EModeCategoryName, - status: 'Active' | 'Inactive', - ): Promise { - const tile = this.locateEModeCategoryTile(eModeCategoryName) - await expect(tile).toContainText(status) - } - async expectEModeSuccessPage(eModeCategoryName: EModeCategoryName): Promise { - await expect(this.page.getByTestId(testIds.component.SuccessViewContent)).toContainText('Congrats, all done!') - await expect(this.page.getByTestId(testIds.dialog.success)).toContainText(eModeCategoryName) - await expect(this.page.getByTestId(testIds.dialog.success)).toContainText('Option activated') - } +// // #region assertions +// async expectEModeCategoryTileStatus( +// eModeCategoryName: EModeCategoryName, +// status: 'Active' | 'Inactive', +// ): Promise { +// const tile = this.locateEModeCategoryTile(eModeCategoryName) +// await expect(tile).toContainText(status) +// } +// async expectEModeSuccessPage(eModeCategoryName: EModeCategoryName): Promise { +// await expect(this.page.getByTestId(testIds.component.SuccessViewContent)).toContainText('Congrats, all done!') +// await expect(this.page.getByTestId(testIds.dialog.success)).toContainText(eModeCategoryName) +// await expect(this.page.getByTestId(testIds.dialog.success)).toContainText('Option activated') +// } - async expectEModeTransactionOverview(txOverview: EModeTransactionOverview): Promise { - const overviewPanel = this.locatePanelByHeader('Transaction overview') - await expect(overviewPanel).toBeVisible() - const ids = testIds.dialog.eMode.transactionOverview - const { availableAssets, maxLtv, variant } = txOverview +// async expectEModeTransactionOverview(txOverview: EModeTransactionOverview): Promise { +// const overviewPanel = this.locatePanelByHeader('Transaction overview') +// await expect(overviewPanel).toBeVisible() +// const ids = testIds.dialog.eMode.transactionOverview +// const { availableAssets, maxLtv, variant } = txOverview - if (variant === 'e-mode-no-change') { - if (availableAssets.category) { - await expect(this.page.getByTestId(ids.availableAssets.category)).toHaveText(availableAssets.category) - } - await expect(this.page.getByTestId(ids.availableAssets.assets)).toHaveText(availableAssets.assets) - await expect(this.page.getByTestId(ids.maxLtv.before)).toHaveText(maxLtv) - await expect(this.page.getByTestId(testIds.dialog.healthFactor.before)).toContainText(txOverview.hf) - } +// if (variant === 'e-mode-no-change') { +// if (availableAssets.category) { +// await expect(this.page.getByTestId(ids.availableAssets.category)).toHaveText(availableAssets.category) +// } +// await expect(this.page.getByTestId(ids.availableAssets.assets)).toHaveText(availableAssets.assets) +// await expect(this.page.getByTestId(ids.maxLtv.before)).toHaveText(maxLtv) +// await expect(this.page.getByTestId(testIds.dialog.healthFactor.before)).toContainText(txOverview.hf) +// } - if (variant === 'e-mode-change') { - if (availableAssets.category) { - await expect(this.page.getByTestId(ids.availableAssets.category)).toHaveText(availableAssets.category) - } - await expect(this.page.getByTestId(ids.availableAssets.assets)).toHaveText(availableAssets.assets) - await expect(this.page.getByTestId(ids.maxLtv.before)).toHaveText(maxLtv.before) - await expect(this.page.getByTestId(ids.maxLtv.after)).toHaveText(maxLtv.after) - await expect(this.page.getByTestId(testIds.dialog.healthFactor.before)).toContainText(txOverview.hf.before) - await expect(this.page.getByTestId(testIds.dialog.healthFactor.after)).toContainText(txOverview.hf.after) - } +// if (variant === 'e-mode-change') { +// if (availableAssets.category) { +// await expect(this.page.getByTestId(ids.availableAssets.category)).toHaveText(availableAssets.category) +// } +// await expect(this.page.getByTestId(ids.availableAssets.assets)).toHaveText(availableAssets.assets) +// await expect(this.page.getByTestId(ids.maxLtv.before)).toHaveText(maxLtv.before) +// await expect(this.page.getByTestId(ids.maxLtv.after)).toHaveText(maxLtv.after) +// await expect(this.page.getByTestId(testIds.dialog.healthFactor.before)).toContainText(txOverview.hf.before) +// await expect(this.page.getByTestId(testIds.dialog.healthFactor.after)).toContainText(txOverview.hf.after) +// } - if (variant === 'no-borrow') { - if (availableAssets.category) { - await expect(this.page.getByTestId(ids.availableAssets.category)).toHaveText(availableAssets.category) - } - await expect(this.page.getByTestId(ids.availableAssets.assets)).toHaveText(availableAssets.assets) - await expect(this.page.getByTestId(ids.maxLtv.before)).toHaveText(maxLtv.before) - await expect(this.page.getByTestId(ids.maxLtv.after)).toHaveText(maxLtv.after) - } - } - // #endregion assertions -} +// if (variant === 'no-borrow') { +// if (availableAssets.category) { +// await expect(this.page.getByTestId(ids.availableAssets.category)).toHaveText(availableAssets.category) +// } +// await expect(this.page.getByTestId(ids.availableAssets.assets)).toHaveText(availableAssets.assets) +// await expect(this.page.getByTestId(ids.maxLtv.before)).toHaveText(maxLtv.before) +// await expect(this.page.getByTestId(ids.maxLtv.after)).toHaveText(maxLtv.after) +// } +// } +// // #endregion assertions +// } -type EModeTransactionOverview = - | { - variant: 'e-mode-change' - availableAssets: { - category?: string - assets: string - } - maxLtv: { - before: string - after: string - } - hf: { - before: string - after: string - } - } - | { - variant: 'e-mode-no-change' - availableAssets: { - category?: string - assets: string - } - maxLtv: string - hf: string - } - | { - variant: 'no-borrow' - availableAssets: { - category?: string - assets: string - } - maxLtv: { - before: string - after: string - } - } +// type EModeTransactionOverview = +// | { +// variant: 'e-mode-change' +// availableAssets: { +// category?: string +// assets: string +// } +// maxLtv: { +// before: string +// after: string +// } +// hf: { +// before: string +// after: string +// } +// } +// | { +// variant: 'e-mode-no-change' +// availableAssets: { +// category?: string +// assets: string +// } +// maxLtv: string +// hf: string +// } +// | { +// variant: 'no-borrow' +// availableAssets: { +// category?: string +// assets: string +// } +// maxLtv: { +// before: string +// after: string +// } +// } diff --git a/packages/app/src/features/dialogs/savings/common/e2e/SavingsDialog.PageObject.ts b/packages/app/src/features/dialogs/savings/common/e2e/SavingsDialog.PageObject.ts index 83363a605..8575aec90 100644 --- a/packages/app/src/features/dialogs/savings/common/e2e/SavingsDialog.PageObject.ts +++ b/packages/app/src/features/dialogs/savings/common/e2e/SavingsDialog.PageObject.ts @@ -1,151 +1,151 @@ -import { getBalance, getTokenBalance } from '@/test/e2e/utils' -import { testIds } from '@/ui/utils/testIds' -import { Locator, Page, expect } from '@playwright/test' -import { Address } from 'viem' -import { DialogPageObject, TxOverviewWithRoute } from '../../../common/Dialog.PageObject' - -export class SavingsDialogPageObject extends DialogPageObject { - private readonly type: 'deposit' | 'withdraw' | 'send' - - constructor({ page, type }: { page: Page; type: 'deposit' | 'withdraw' | 'send' }) { - super( - page, - new RegExp(`${type === 'deposit' ? 'Deposit to' : type === 'send' ? 'Send from' : 'Withdraw from'} Savings`), - ) - this.type = type - } - - // # region locators - locateUpgradeSwitch(): Locator { - return this.page.getByTestId(testIds.dialog.savings.upgradeSwitch) - } - // #endregion locators - - // #region actions - async clickBackToSavingsButton(): Promise { - await this.page.getByRole('button', { name: 'Back to Savings' }).click() - await this.region.waitFor({ - state: 'detached', - }) - } - - async fillReceiverAction(receiver: string): Promise { - await this.region.getByTestId(testIds.component.AddressInput.input).fill(receiver) - } - - // #endregion actions - - // #region assertions - async expectDiscrepancyWarning(discrepancy: string): Promise { - const explanation = - this.type === 'deposit' - ? 'The final amount received may be less than the deposit amount by up to' - : 'You may be charged more than the withdraw amount by up to' - await expect( - this.region.getByText(`Market fluctuations can impact your transaction value. ${explanation} ${discrepancy}`), - ).toBeVisible() - } - - async expectTransactionOverviewToBeVisible(): Promise { - await expect(this.locatePanelByHeader('Transaction overview')).toBeVisible() - } - - async expectAssetSelectorOptions(options: string[]): Promise { - const selectorOptions = await this.page.getByTestId(testIds.component.AssetSelector.option).all() - expect(selectorOptions).toHaveLength(options.length) - - for (const [index, option] of selectorOptions.entries()) { - await expect(option).toContainText(options[index]!) - } - } - - async expectTransactionOverview(transactionOverview: TransactionOverview): Promise { - const panel = this.locatePanelByHeader('Transaction overview') - await expect(panel).toBeVisible() - - for (const [index, [label, value]] of transactionOverview.entries()) { - const row = panel.getByTestId(testIds.dialog.depositSavings.transactionDetailsRow(index)) - await expect(row).toBeVisible() - await expect(row).toContainText(label) - await expect(row).toContainText(value) - } - } - - async expectNativeRouteTransactionOverview(transactionOverview: NativeRouteTransactionOverview): Promise { - const panel = this.locatePanelByHeader('Transaction overview') - await expect(panel).toBeVisible() - const savingsTxOverviewTestIds = testIds.dialog.savings.transactionOverview - - if (transactionOverview.apy) { - const apyValue = panel.getByTestId(savingsTxOverviewTestIds.apy.value) - const apyDescription = panel.getByTestId(savingsTxOverviewTestIds.apy.description) - await expect(apyValue).toContainText(transactionOverview.apy.value) - await expect(apyDescription).toContainText(transactionOverview.apy.description) - } - - await this.expectTransactionOverviewRoute(transactionOverview.routeItems) - if (transactionOverview.badgeTokens) { - await this.expectSkyBadgeForTokens(transactionOverview.badgeTokens) - } - await this.expectOutcomeText(transactionOverview.outcome) - } - - async expectSuccessPage(): Promise { - // for now we only check if the success message is visible - await expect(this.page.getByText('Congrats, all done!')).toBeVisible() - } - - async expectAddressInputError(error: string): Promise { - await expect(this.page.getByTestId(testIds.component.AddressInput.error)).toHaveText(error) - } - - async expectReceiverIsSmartContractWarning(): Promise { - await expect(this.page.getByTestId(testIds.dialog.savings.send.addressIsSmartContractWarning)).toBeVisible() - } - - async expectReceiverBalance({ - forkUrl, - receiver, - expectedBalance, - }: { - forkUrl: string - receiver: Address - expectedBalance: number - }): Promise { - const currentBalance = await getBalance({ forkUrl, address: receiver }) - expect(currentBalance.isEqualTo(expectedBalance)).toBe(true) - } - - async expectReceiverTokenBalance({ - forkUrl, - receiver, - token, - expectedBalance, - }: { - forkUrl: string - receiver: Address - token: { address: Address; decimals: number } - expectedBalance: number - }): Promise { - const currentTokenBalance = await getTokenBalance({ forkUrl, address: receiver, token }) - expect(currentTokenBalance.isEqualTo(expectedBalance)).toBe(true) - } - - expectUpgradeSwitchToBeHidden(): Promise { - return expect(this.locateUpgradeSwitch()).toBeHidden() - } - - clickUpgradeSwitch(): Promise { - return this.locateUpgradeSwitch().click() - } - // #endregion assertions -} - -type TransactionOverview = [string, string][] - -interface NativeRouteTransactionOverview extends TxOverviewWithRoute { - apy?: { - value: string - description: string - } -} +// import { getBalance, getTokenBalance } from '@/test/e2e/utils' +// import { testIds } from '@/ui/utils/testIds' +// import { Locator, Page, expect } from '@playwright/test' +// import { Address } from 'viem' +// import { DialogPageObject, TxOverviewWithRoute } from '../../../common/Dialog.PageObject' + +// export class SavingsDialogPageObject extends DialogPageObject { +// private readonly type: 'deposit' | 'withdraw' | 'send' + +// constructor({ page, type }: { page: Page; type: 'deposit' | 'withdraw' | 'send' }) { +// super( +// page, +// new RegExp(`${type === 'deposit' ? 'Deposit to' : type === 'send' ? 'Send from' : 'Withdraw from'} Savings`), +// ) +// this.type = type +// } + +// // # region locators +// locateUpgradeSwitch(): Locator { +// return this.page.getByTestId(testIds.dialog.savings.upgradeSwitch) +// } +// // #endregion locators + +// // #region actions +// async clickBackToSavingsButton(): Promise { +// await this.page.getByRole('button', { name: 'Back to Savings' }).click() +// await this.region.waitFor({ +// state: 'detached', +// }) +// } + +// async fillReceiverAction(receiver: string): Promise { +// await this.region.getByTestId(testIds.component.AddressInput.input).fill(receiver) +// } + +// // #endregion actions + +// // #region assertions +// async expectDiscrepancyWarning(discrepancy: string): Promise { +// const explanation = +// this.type === 'deposit' +// ? 'The final amount received may be less than the deposit amount by up to' +// : 'You may be charged more than the withdraw amount by up to' +// await expect( +// this.region.getByText(`Market fluctuations can impact your transaction value. ${explanation} ${discrepancy}`), +// ).toBeVisible() +// } + +// async expectTransactionOverviewToBeVisible(): Promise { +// await expect(this.locatePanelByHeader('Transaction overview')).toBeVisible() +// } + +// async expectAssetSelectorOptions(options: string[]): Promise { +// const selectorOptions = await this.page.getByTestId(testIds.component.AssetSelector.option).all() +// expect(selectorOptions).toHaveLength(options.length) + +// for (const [index, option] of selectorOptions.entries()) { +// await expect(option).toContainText(options[index]!) +// } +// } + +// async expectTransactionOverview(transactionOverview: TransactionOverview): Promise { +// const panel = this.locatePanelByHeader('Transaction overview') +// await expect(panel).toBeVisible() + +// for (const [index, [label, value]] of transactionOverview.entries()) { +// const row = panel.getByTestId(testIds.dialog.depositSavings.transactionDetailsRow(index)) +// await expect(row).toBeVisible() +// await expect(row).toContainText(label) +// await expect(row).toContainText(value) +// } +// } + +// async expectNativeRouteTransactionOverview(transactionOverview: NativeRouteTransactionOverview): Promise { +// const panel = this.locatePanelByHeader('Transaction overview') +// await expect(panel).toBeVisible() +// const savingsTxOverviewTestIds = testIds.dialog.savings.transactionOverview + +// if (transactionOverview.apy) { +// const apyValue = panel.getByTestId(savingsTxOverviewTestIds.apy.value) +// const apyDescription = panel.getByTestId(savingsTxOverviewTestIds.apy.description) +// await expect(apyValue).toContainText(transactionOverview.apy.value) +// await expect(apyDescription).toContainText(transactionOverview.apy.description) +// } + +// await this.expectTransactionOverviewRoute(transactionOverview.routeItems) +// if (transactionOverview.badgeTokens) { +// await this.expectSkyBadgeForTokens(transactionOverview.badgeTokens) +// } +// await this.expectOutcomeText(transactionOverview.outcome) +// } + +// async expectSuccessPage(): Promise { +// // for now we only check if the success message is visible +// await expect(this.page.getByText('Congrats, all done!')).toBeVisible() +// } + +// async expectAddressInputError(error: string): Promise { +// await expect(this.page.getByTestId(testIds.component.AddressInput.error)).toHaveText(error) +// } + +// async expectReceiverIsSmartContractWarning(): Promise { +// await expect(this.page.getByTestId(testIds.dialog.savings.send.addressIsSmartContractWarning)).toBeVisible() +// } + +// async expectReceiverBalance({ +// forkUrl, +// receiver, +// expectedBalance, +// }: { +// forkUrl: string +// receiver: Address +// expectedBalance: number +// }): Promise { +// const currentBalance = await getBalance({ forkUrl, address: receiver }) +// expect(currentBalance.isEqualTo(expectedBalance)).toBe(true) +// } + +// async expectReceiverTokenBalance({ +// forkUrl, +// receiver, +// token, +// expectedBalance, +// }: { +// forkUrl: string +// receiver: Address +// token: { address: Address; decimals: number } +// expectedBalance: number +// }): Promise { +// const currentTokenBalance = await getTokenBalance({ forkUrl, address: receiver, token }) +// expect(currentTokenBalance.isEqualTo(expectedBalance)).toBe(true) +// } + +// expectUpgradeSwitchToBeHidden(): Promise { +// return expect(this.locateUpgradeSwitch()).toBeHidden() +// } + +// clickUpgradeSwitch(): Promise { +// return this.locateUpgradeSwitch().click() +// } +// // #endregion assertions +// } + +// type TransactionOverview = [string, string][] + +// interface NativeRouteTransactionOverview extends TxOverviewWithRoute { +// apy?: { +// value: string +// description: string +// } +// } diff --git a/packages/app/src/features/dialogs/savings/migrate/downgrade/DowngradeDialog.PageObject.ts b/packages/app/src/features/dialogs/savings/migrate/downgrade/DowngradeDialog.PageObject.ts index 2cca555d3..98640b5db 100644 --- a/packages/app/src/features/dialogs/savings/migrate/downgrade/DowngradeDialog.PageObject.ts +++ b/packages/app/src/features/dialogs/savings/migrate/downgrade/DowngradeDialog.PageObject.ts @@ -1,38 +1,38 @@ -import { DialogPageObject, TxOverviewWithRoute } from '@/features/dialogs/common/Dialog.PageObject' -import { testIds } from '@/ui/utils/testIds' -import { Page, expect } from '@playwright/test' +// import { DialogPageObject, TxOverviewWithRoute } from '@/features/dialogs/common/Dialog.PageObject' +// import { testIds } from '@/ui/utils/testIds' +// import { Page, expect } from '@playwright/test' -export class DowngradeDialogPageObject extends DialogPageObject { - constructor(page: Page) { - super(page, /Downgrade/) - } +// export class DowngradeDialogPageObject extends DialogPageObject { +// constructor(page: Page) { +// super(page, /Downgrade/) +// } - // #region actions - async clickBackToSavingsButton(): Promise { - await this.page.getByRole('button', { name: 'Back to Savings' }).click() - await this.region.waitFor({ - state: 'detached', - }) - } - // #endregion actions +// // #region actions +// async clickBackToSavingsButton(): Promise { +// await this.page.getByRole('button', { name: 'Back to Savings' }).click() +// await this.region.waitFor({ +// state: 'detached', +// }) +// } +// // #endregion actions - // #region assertions - async expectTransactionOverview(transactionOverview: TxOverviewWithRoute): Promise { - await this.expectTransactionOverviewRoute(transactionOverview.routeItems) - if (transactionOverview.badgeTokens) { - await this.expectSkyBadgeForTokens(transactionOverview.badgeTokens) - } - await this.expectOutcomeText(transactionOverview.outcome) - } +// // #region assertions +// async expectTransactionOverview(transactionOverview: TxOverviewWithRoute): Promise { +// await this.expectTransactionOverviewRoute(transactionOverview.routeItems) +// if (transactionOverview.badgeTokens) { +// await this.expectSkyBadgeForTokens(transactionOverview.badgeTokens) +// } +// await this.expectOutcomeText(transactionOverview.outcome) +// } - async expectDowngradeSuccessPage({ - token, - amount, - usdValue, - }: { token: string; amount: string; usdValue: string }): Promise { - await expect(this.region.getByText('Congrats, all done!')).toBeVisible() - const summary = await this.region.getByTestId(testIds.dialog.success).textContent() - await expect(summary).toMatch(`${token}${amount} ${usdValue}`) - } - // #endregion assertions -} +// async expectDowngradeSuccessPage({ +// token, +// amount, +// usdValue, +// }: { token: string; amount: string; usdValue: string }): Promise { +// await expect(this.region.getByText('Congrats, all done!')).toBeVisible() +// const summary = await this.region.getByTestId(testIds.dialog.success).textContent() +// await expect(summary).toMatch(`${token}${amount} ${usdValue}`) +// } +// // #endregion assertions +// } diff --git a/packages/app/src/features/dialogs/savings/migrate/upgrade/UpgradeDialog.PageObject.ts b/packages/app/src/features/dialogs/savings/migrate/upgrade/UpgradeDialog.PageObject.ts index 3fcb75986..3e59932a2 100644 --- a/packages/app/src/features/dialogs/savings/migrate/upgrade/UpgradeDialog.PageObject.ts +++ b/packages/app/src/features/dialogs/savings/migrate/upgrade/UpgradeDialog.PageObject.ts @@ -1,56 +1,56 @@ -import { DialogPageObject, TxOverviewWithRoute } from '@/features/dialogs/common/Dialog.PageObject' -import { testIds } from '@/ui/utils/testIds' -import { Page, expect } from '@playwright/test' +// import { DialogPageObject, TxOverviewWithRoute } from '@/features/dialogs/common/Dialog.PageObject' +// import { testIds } from '@/ui/utils/testIds' +// import { Page, expect } from '@playwright/test' -export class UpgradeDialogPageObject extends DialogPageObject { - constructor(page: Page) { - super(page, /Upgrade/) - } +// export class UpgradeDialogPageObject extends DialogPageObject { +// constructor(page: Page) { +// super(page, /Upgrade/) +// } - // #region actions - async clickBackToSavingsButton(): Promise { - await this.page.getByRole('button', { name: 'Back to Savings' }).click() - await this.region.waitFor({ - state: 'detached', - }) - } - // #endregion actions +// // #region actions +// async clickBackToSavingsButton(): Promise { +// await this.page.getByRole('button', { name: 'Back to Savings' }).click() +// await this.region.waitFor({ +// state: 'detached', +// }) +// } +// // #endregion actions - // #region assertions - async expectTransactionOverview(transactionOverview: UpgradeTxOverview): Promise { - const panel = this.locatePanelByHeader('Transaction overview') - await expect(panel).toBeVisible() - const savingsTxOverviewTestIds = testIds.dialog.savings.transactionOverview +// // #region assertions +// async expectTransactionOverview(transactionOverview: UpgradeTxOverview): Promise { +// const panel = this.locatePanelByHeader('Transaction overview') +// await expect(panel).toBeVisible() +// const savingsTxOverviewTestIds = testIds.dialog.savings.transactionOverview - if (transactionOverview.apyChange) { - const currentApyValue = panel.getByTestId(savingsTxOverviewTestIds.apyChange.before) - const updatedApyValue = panel.getByTestId(savingsTxOverviewTestIds.apyChange.after) - await expect(currentApyValue).toContainText(transactionOverview.apyChange.current) - await expect(updatedApyValue).toContainText(transactionOverview.apyChange.updated) - } +// if (transactionOverview.apyChange) { +// const currentApyValue = panel.getByTestId(savingsTxOverviewTestIds.apyChange.before) +// const updatedApyValue = panel.getByTestId(savingsTxOverviewTestIds.apyChange.after) +// await expect(currentApyValue).toContainText(transactionOverview.apyChange.current) +// await expect(updatedApyValue).toContainText(transactionOverview.apyChange.updated) +// } - await this.expectTransactionOverviewRoute(transactionOverview.routeItems) - if (transactionOverview.badgeTokens) { - await this.expectSkyBadgeForTokens(transactionOverview.badgeTokens) - } - await this.expectOutcomeText(transactionOverview.outcome) - } +// await this.expectTransactionOverviewRoute(transactionOverview.routeItems) +// if (transactionOverview.badgeTokens) { +// await this.expectSkyBadgeForTokens(transactionOverview.badgeTokens) +// } +// await this.expectOutcomeText(transactionOverview.outcome) +// } - async expectUpgradeSuccessPage({ - token, - amount, - usdValue, - }: { token: string; amount: string; usdValue: string }): Promise { - await expect(this.region.getByText('Congrats, all done!')).toBeVisible() - const summary = await this.region.getByTestId(testIds.dialog.success).textContent() - await expect(summary).toMatch(`${token}${amount} ${usdValue}`) - } - // #endregion assertions -} +// async expectUpgradeSuccessPage({ +// token, +// amount, +// usdValue, +// }: { token: string; amount: string; usdValue: string }): Promise { +// await expect(this.region.getByText('Congrats, all done!')).toBeVisible() +// const summary = await this.region.getByTestId(testIds.dialog.success).textContent() +// await expect(summary).toMatch(`${token}${amount} ${usdValue}`) +// } +// // #endregion assertions +// } -interface UpgradeTxOverview extends TxOverviewWithRoute { - apyChange?: { - current: string - updated: string - } -} +// interface UpgradeTxOverview extends TxOverviewWithRoute { +// apyChange?: { +// current: string +// updated: string +// } +// } diff --git a/packages/app/src/features/farm-details/FarmDetails.PageObject.ts b/packages/app/src/features/farm-details/FarmDetails.PageObject.ts index 6bed8c3a3..57f5925c9 100644 --- a/packages/app/src/features/farm-details/FarmDetails.PageObject.ts +++ b/packages/app/src/features/farm-details/FarmDetails.PageObject.ts @@ -2,7 +2,7 @@ import { BasePageObject } from '@/test/e2e/BasePageObject' import { AssetsInTests, TOKENS_ON_FORK } from '@/test/e2e/constants' import { getTokenBalance } from '@/test/e2e/utils' import { testIds } from '@/ui/utils/testIds' -import { TestnetClient, getUrlFromClient } from '@marsfoundation/common-testnets' +import { getUrlFromClient } from '@marsfoundation/common-testnets' import { NormalizedUnitNumber } from '@marsfoundation/common-universal' import { Locator, expect } from '@playwright/test' import { Address } from 'viem' @@ -55,21 +55,19 @@ export class FarmDetailsPageObject extends BasePageObject { } async expectTokenBalance({ - testnetClient, symbol, balance, address, }: { - testnetClient: TestnetClient symbol: AssetsInTests balance: NormalizedUnitNumber address: Address }): Promise { - const chainId = await testnetClient.getChainId() + const chainId = await this.testContext.testnetController.client.getChainId() const token: { address: Address; decimals: number } = (TOKENS_ON_FORK as any)[chainId][symbol] const actualBalance = await getTokenBalance({ address, - forkUrl: getUrlFromClient(testnetClient), + forkUrl: getUrlFromClient(this.testContext.testnetController.client), token, }) expect(balance.eq(actualBalance)).toBe(true) diff --git a/packages/app/src/features/farm-details/dialogs/claim/ClaimDialog.PageObject.ts b/packages/app/src/features/farm-details/dialogs/claim/ClaimDialog.PageObject.ts index 1bfcedfb6..4ef286f78 100644 --- a/packages/app/src/features/farm-details/dialogs/claim/ClaimDialog.PageObject.ts +++ b/packages/app/src/features/farm-details/dialogs/claim/ClaimDialog.PageObject.ts @@ -1,10 +1,14 @@ import { DialogPageObject } from '@/features/dialogs/common/Dialog.PageObject' +import { TestContext } from '@/test/e2e/setup' import { testIds } from '@/ui/utils/testIds' -import { Page, expect } from '@playwright/test' +import { expect } from '@playwright/test' export class ClaimDialogPageObject extends DialogPageObject { - constructor(page: Page) { - super(page, /Claim/) + constructor(testContext: TestContext) { + super({ + testContext, + header: /Claim/, + }) } // #region actions diff --git a/packages/app/src/features/farm-details/dialogs/claim/e2e/mainnet/ClaimSKY.test-e2e.ts b/packages/app/src/features/farm-details/dialogs/claim/e2e/mainnet/ClaimSKY.test-e2e.ts index 2b8f5f4b5..bb17be487 100644 --- a/packages/app/src/features/farm-details/dialogs/claim/e2e/mainnet/ClaimSKY.test-e2e.ts +++ b/packages/app/src/features/farm-details/dialogs/claim/e2e/mainnet/ClaimSKY.test-e2e.ts @@ -3,7 +3,6 @@ import { StakeDialogPageObject } from '@/features/farm-details/dialogs/stake/Sta import { USDS_ACTIVATED_BLOCK_NUMBER } from '@/test/e2e/constants' import { overrideInfoSkyRouteWithHAR } from '@/test/e2e/info-sky' import { setup } from '@/test/e2e/setup' -import { TestnetClient } from '@marsfoundation/common-testnets' import { NormalizedUnitNumber } from '@marsfoundation/common-universal' import { test } from '@playwright/test' import { Address } from 'viem' @@ -14,12 +13,9 @@ test.describe('Claim SKY rewards', () => { let farmDetailsPage: FarmDetailsPageObject let claimDialog: ClaimDialogPageObject let account: Address - let updateBrowserAndNextBlockTime: (seconds: number) => Promise - let incrementTime: (seconds: number) => Promise - let testnetClient: TestnetClient test.beforeEach(async ({ page }) => { - ;({ account, testnetClient, updateBrowserAndNextBlockTime, incrementTime } = await setup(page, { + const testContext = await setup(page, { blockchain: { chainId: mainnet.id, blockNumber: USDS_ACTIVATED_BLOCK_NUMBER, @@ -36,20 +32,22 @@ test.describe('Claim SKY rewards', () => { USDS: 10_000, }, }, - })) + }) + account = testContext.account + await overrideInfoSkyRouteWithHAR({ page, key: '1-sky-farm-with-8_51-apy' }) - farmDetailsPage = new FarmDetailsPageObject(page) + farmDetailsPage = new FarmDetailsPageObject(testContext) await farmDetailsPage.clickInfoPanelStakeButtonAction() - const stakeDialog = new StakeDialogPageObject(page) + const stakeDialog = new StakeDialogPageObject(testContext) await stakeDialog.fillAmountAction(10_000) - await stakeDialog.actionsContainer.acceptAllActionsAction(2, updateBrowserAndNextBlockTime) + await stakeDialog.actionsContainer.acceptAllActionsAction(2) await stakeDialog.clickBackToFarmAction() - await incrementTime(24 * 60 * 60) // 24 hours + await testContext.testnetController.progressSimulationAndMine(24 * 60 * 60) // 24 hours await page.reload() await farmDetailsPage.clickInfoPanelClaimButtonAction() - claimDialog = new ClaimDialogPageObject(page) + claimDialog = new ClaimDialogPageObject(testContext) }) test('has correct action plan', async () => { @@ -67,7 +65,7 @@ test.describe('Claim SKY rewards', () => { }) test('executes transaction', async () => { - await claimDialog.actionsContainer.acceptAllActionsAction(1, updateBrowserAndNextBlockTime) + await claimDialog.actionsContainer.acceptAllActionsAction(1) await claimDialog.expectSuccessPage() await claimDialog.clickBackToFarmAction() @@ -79,9 +77,8 @@ test.describe('Claim SKY rewards', () => { }) await farmDetailsPage.expectTokenBalance({ address: account, - testnetClient, symbol: 'SKY', - balance: NormalizedUnitNumber('3539.85599931941984'), + balance: NormalizedUnitNumber('3539.69212658060522'), }) await farmDetailsPage.expectStaked({ amount: '10,000.00', asset: 'USDS' }) }) diff --git a/packages/app/src/features/farm-details/dialogs/stake/StakeDialog.PageObject.ts b/packages/app/src/features/farm-details/dialogs/stake/StakeDialog.PageObject.ts index 546a238af..dc39e160e 100644 --- a/packages/app/src/features/farm-details/dialogs/stake/StakeDialog.PageObject.ts +++ b/packages/app/src/features/farm-details/dialogs/stake/StakeDialog.PageObject.ts @@ -1,10 +1,14 @@ import { DialogPageObject } from '@/features/dialogs/common/Dialog.PageObject' +import { TestContext } from '@/test/e2e/setup' import { testIds } from '@/ui/utils/testIds' -import { Page, expect } from '@playwright/test' +import { expect } from '@playwright/test' export class StakeDialogPageObject extends DialogPageObject { - constructor(page: Page) { - super(page, /Deposit/) + constructor(testContext: TestContext) { + super({ + testContext, + header: /Deposit/, + }) } // #region actions diff --git a/packages/app/src/features/farm-details/dialogs/unstake/UnstakeDialog.PageObject.ts b/packages/app/src/features/farm-details/dialogs/unstake/UnstakeDialog.PageObject.ts index d338b5a4c..3c701638f 100644 --- a/packages/app/src/features/farm-details/dialogs/unstake/UnstakeDialog.PageObject.ts +++ b/packages/app/src/features/farm-details/dialogs/unstake/UnstakeDialog.PageObject.ts @@ -1,146 +1,146 @@ -import { DialogPageObject } from '@/features/dialogs/common/Dialog.PageObject' -import { testIds } from '@/ui/utils/testIds' -import { Page, expect } from '@playwright/test' - -export class UnstakeDialogPageObject extends DialogPageObject { - constructor(page: Page) { - super(page, /Withdraw/) - } - - // #region actions - async clickBackToFarmAction(): Promise { - await this.page.getByRole('button', { name: 'Back to Farm' }).click() - await this.region.waitFor({ - state: 'detached', - }) - } - - async clickExitFarmSwitchAction(): Promise { - await this.page.getByTestId(testIds.farmDetails.unstakeDialog.exitFarmSwitchPanel.switch).click() - } - // - - // #region assertions - async expectExitFarmSwitchToBeHidden(): Promise { - await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.exitFarmSwitchPanel.switch)).toBeHidden() - } - - async expectExitFarmSwitchToBeVisible(): Promise { - await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.exitFarmSwitchPanel.switch)).toBeVisible() - } - - async expectExitFarmSwitchNotChecked(): Promise { - await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.exitFarmSwitchPanel.switch)).not.toBeChecked() - } - - async expectExitFarmSwitchReward({ min, max, token, usdValue }: Reward): Promise { - const regexp = /~([\d,\.]+) (\w+) \(~\$([\d,\.]+)\)/ - const rewardRowText = await this.page - .getByTestId(testIds.farmDetails.unstakeDialog.exitFarmSwitchPanel.reward) - .textContent() - - const match = rewardRowText?.match(regexp) - expect(match).toBeDefined() - - const [rewardAmount, rewardToken, rewardUsdValue] = match!.slice(1) - const rewardNumber = Number(rewardAmount?.replace(/,/g, '')) - expect(rewardNumber).toBeGreaterThanOrEqual(min) - expect(rewardNumber).toBeLessThanOrEqual(max) - expect(rewardToken).toBe(token) - expect(rewardUsdValue).toContain(usdValue) - } - - async expectRoutesOverview(route: Route): Promise { - const routeItemTestIds = testIds.dialog.transactionOverview.routeItem - const txOverviewTestIds = testIds.farmDetails.unstakeDialog.transactionOverview - - for (let i = 0; i < route.swaps.length; i++) { - // i + 1 because the first item in route is farm itself - await expect(this.page.getByTestId(routeItemTestIds.tokenWithAmount(i + 1))).toContainText( - route.swaps[i]!.tokenAmount, - ) - await expect(this.page.getByTestId(routeItemTestIds.tokenUsdValue(i + 1))).toContainText( - route.swaps[i]!.tokenUsdValue, - ) - } - - await expect(this.page.getByTestId(txOverviewTestIds.route.farm.farmName)).toContainText(route.farm.upperText) - await expect(this.page.getByTestId(txOverviewTestIds.route.farm.stakingToken)).toContainText(route.farm.lowerText) - } - - async expectTransactionOverview({ route, outcome }: TransactionOverview): Promise { - await this.expectRoutesOverview(route) - await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.outcome)).toContainText( - outcome, - ) - } - - async expectExitTransactionOverview({ route, reward, outcome }: ExitTransactionOverview): Promise { - await this.expectRoutesOverview(route) - - await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.outcome)).toContainText( - outcome.amount, - ) - await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.outcome)).toContainText( - outcome.token, - ) - await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.outcomeUsd)).toContainText( - outcome.usdValue, - ) - - const rewardAmount = await this.page - .getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.rewardOutcome) - .textContent() - const rewardNumber = Number(rewardAmount?.replace(/[^0-9.]/g, '')) - - expect(rewardNumber).toBeGreaterThanOrEqual(reward.min) - expect(rewardNumber).toBeLessThanOrEqual(reward.max) - await expect( - this.page.getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.rewardOutcome), - ).toContainText(reward.token) - await expect( - this.page.getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.rewardOutcomeUsd), - ).toContainText(reward.usdValue) - } - - async expectSuccessPage(): Promise { - // for now we only check if the success message is visible - await expect(this.page.getByText('Congrats, all done!')).toBeVisible() - } - // #endregion -} - -export interface Reward { - min: number - max: number - token: string - usdValue: string -} - -export interface Outome { - amount: string - token: string - usdValue: string -} - -export interface Route { - swaps: { - tokenAmount: string - tokenUsdValue: string - }[] - farm: { - upperText: string - lowerText: string - } -} - -export interface TransactionOverview { - route: Route - outcome: string -} - -export interface ExitTransactionOverview { - route: Route - reward: Reward - outcome: Outome -} +// import { DialogPageObject } from '@/features/dialogs/common/Dialog.PageObject' +// import { testIds } from '@/ui/utils/testIds' +// import { Page, expect } from '@playwright/test' + +// export class UnstakeDialogPageObject extends DialogPageObject { +// constructor(page: Page) { +// super(page, /Withdraw/) +// } + +// // #region actions +// async clickBackToFarmAction(): Promise { +// await this.page.getByRole('button', { name: 'Back to Farm' }).click() +// await this.region.waitFor({ +// state: 'detached', +// }) +// } + +// async clickExitFarmSwitchAction(): Promise { +// await this.page.getByTestId(testIds.farmDetails.unstakeDialog.exitFarmSwitchPanel.switch).click() +// } +// // + +// // #region assertions +// async expectExitFarmSwitchToBeHidden(): Promise { +// await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.exitFarmSwitchPanel.switch)).toBeHidden() +// } + +// async expectExitFarmSwitchToBeVisible(): Promise { +// await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.exitFarmSwitchPanel.switch)).toBeVisible() +// } + +// async expectExitFarmSwitchNotChecked(): Promise { +// await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.exitFarmSwitchPanel.switch)).not.toBeChecked() +// } + +// async expectExitFarmSwitchReward({ min, max, token, usdValue }: Reward): Promise { +// const regexp = /~([\d,\.]+) (\w+) \(~\$([\d,\.]+)\)/ +// const rewardRowText = await this.page +// .getByTestId(testIds.farmDetails.unstakeDialog.exitFarmSwitchPanel.reward) +// .textContent() + +// const match = rewardRowText?.match(regexp) +// expect(match).toBeDefined() + +// const [rewardAmount, rewardToken, rewardUsdValue] = match!.slice(1) +// const rewardNumber = Number(rewardAmount?.replace(/,/g, '')) +// expect(rewardNumber).toBeGreaterThanOrEqual(min) +// expect(rewardNumber).toBeLessThanOrEqual(max) +// expect(rewardToken).toBe(token) +// expect(rewardUsdValue).toContain(usdValue) +// } + +// async expectRoutesOverview(route: Route): Promise { +// const routeItemTestIds = testIds.dialog.transactionOverview.routeItem +// const txOverviewTestIds = testIds.farmDetails.unstakeDialog.transactionOverview + +// for (let i = 0; i < route.swaps.length; i++) { +// // i + 1 because the first item in route is farm itself +// await expect(this.page.getByTestId(routeItemTestIds.tokenWithAmount(i + 1))).toContainText( +// route.swaps[i]!.tokenAmount, +// ) +// await expect(this.page.getByTestId(routeItemTestIds.tokenUsdValue(i + 1))).toContainText( +// route.swaps[i]!.tokenUsdValue, +// ) +// } + +// await expect(this.page.getByTestId(txOverviewTestIds.route.farm.farmName)).toContainText(route.farm.upperText) +// await expect(this.page.getByTestId(txOverviewTestIds.route.farm.stakingToken)).toContainText(route.farm.lowerText) +// } + +// async expectTransactionOverview({ route, outcome }: TransactionOverview): Promise { +// await this.expectRoutesOverview(route) +// await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.outcome)).toContainText( +// outcome, +// ) +// } + +// async expectExitTransactionOverview({ route, reward, outcome }: ExitTransactionOverview): Promise { +// await this.expectRoutesOverview(route) + +// await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.outcome)).toContainText( +// outcome.amount, +// ) +// await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.outcome)).toContainText( +// outcome.token, +// ) +// await expect(this.page.getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.outcomeUsd)).toContainText( +// outcome.usdValue, +// ) + +// const rewardAmount = await this.page +// .getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.rewardOutcome) +// .textContent() +// const rewardNumber = Number(rewardAmount?.replace(/[^0-9.]/g, '')) + +// expect(rewardNumber).toBeGreaterThanOrEqual(reward.min) +// expect(rewardNumber).toBeLessThanOrEqual(reward.max) +// await expect( +// this.page.getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.rewardOutcome), +// ).toContainText(reward.token) +// await expect( +// this.page.getByTestId(testIds.farmDetails.unstakeDialog.transactionOverview.rewardOutcomeUsd), +// ).toContainText(reward.usdValue) +// } + +// async expectSuccessPage(): Promise { +// // for now we only check if the success message is visible +// await expect(this.page.getByText('Congrats, all done!')).toBeVisible() +// } +// // #endregion +// } + +// export interface Reward { +// min: number +// max: number +// token: string +// usdValue: string +// } + +// export interface Outome { +// amount: string +// token: string +// usdValue: string +// } + +// export interface Route { +// swaps: { +// tokenAmount: string +// tokenUsdValue: string +// }[] +// farm: { +// upperText: string +// lowerText: string +// } +// } + +// export interface TransactionOverview { +// route: Route +// outcome: string +// } + +// export interface ExitTransactionOverview { +// route: Route +// reward: Reward +// outcome: Outome +// } diff --git a/packages/app/src/pages/Borrow.PageObject.ts b/packages/app/src/pages/Borrow.PageObject.ts index f5ea41c2b..1884a53c8 100644 --- a/packages/app/src/pages/Borrow.PageObject.ts +++ b/packages/app/src/pages/Borrow.PageObject.ts @@ -1,176 +1,176 @@ -import { expect } from '@playwright/test' - -import { ActionsPageObject } from '@/features/actions/ActionsContainer.PageObject' -import { BasePageObject } from '@/test/e2e/BasePageObject' -import { TestTokenWithValue, expectAssets } from '@/test/e2e/assertions' -import { buildUrl } from '@/test/e2e/setup' -import { calculateAssetsWorth } from '@/test/e2e/utils' -import { testIds } from '@/ui/utils/testIds' -import { TestnetClient, getUrlFromClient } from '@marsfoundation/common-testnets' - -export class BorrowPageObject extends BasePageObject { - // #region actions - async fillDepositAssetAction(index: number, asset: string, amount: number): Promise { - const inputGroup = this.page - .getByTestId(testIds.easyBorrow.form.deposits) - .getByTestId(testIds.component.MultiAssetSelector.group) - .nth(index) - - const selector = inputGroup.getByTestId(testIds.component.AssetSelector.trigger) - await this.selectOptionByLabelAction(selector, asset) - - await inputGroup.getByRole('textbox').fill(amount.toString()) - } - - async selectBorrowAction(assetName: string): Promise { - const borrowSelector = this.page - .getByTestId(testIds.easyBorrow.form.borrow) - .getByTestId(testIds.component.AssetSelector.trigger) - await this.selectOptionByLabelAction(borrowSelector, assetName) - } - - async fillBorrowAssetAction(amount: number): Promise { - const borrowForm = this.page.getByTestId(testIds.easyBorrow.form.borrow) - - await borrowForm.getByRole('textbox').fill(amount.toString()) - } - - async submitAction(): Promise { - await this.page.locator('main').getByRole('button', { name: 'Borrow' }).click() - } - - async addNewDepositAssetAction(): Promise { - return this.page.getByRole('button', { name: 'Add more' }).click() - } - - async viewInMyPortfolioAction(): Promise { - await this.page.getByRole('link', { name: 'View in portfolio' }).click() - } - - async viewInSavingsAction(): Promise { - await this.page.getByRole('link', { name: 'View in Savings' }).click() - } - - async depositAssetsActions({ - assetsToDeposit, - daiToBorrow, - updateBrowserAndNextBlockTime, - }: { - assetsToDeposit: Record - daiToBorrow: number - updateBrowserAndNextBlockTime: () => Promise - }): Promise { - const actionsContainer = new ActionsPageObject(this.locatePanelByHeader('Actions')) - await this.depositWithoutBorrowActions({ - assetsToDeposit, - daiToBorrow, - actionsContainer, - updateBrowserAndNextBlockTime, - }) - await actionsContainer.acceptActionAtIndex( - Object.entries(assetsToDeposit).length * 2, - updateBrowserAndNextBlockTime, - ) // accept final borrow action - } - - async depositWithoutBorrowActions({ - assetsToDeposit, - daiToBorrow, - actionsContainer: _actionsContainer, - updateBrowserAndNextBlockTime, - }: { - assetsToDeposit: Record - daiToBorrow?: number - actionsContainer?: ActionsPageObject - updateBrowserAndNextBlockTime: () => Promise - }): Promise { - const actionsContainer = _actionsContainer ?? new ActionsPageObject(this.locatePanelByHeader('Actions')) - - let index = 0 - for (const [asset, amount] of Object.entries(assetsToDeposit)) { - if (index !== 0) { - await this.addNewDepositAssetAction() - } - await this.fillDepositAssetAction(index, asset, amount) - index++ - } - await this.fillBorrowAssetAction(daiToBorrow ?? 1) // defaulted value won't matter, if only depositing - await this.submitAction() - await actionsContainer.acceptAllActionsAction(2 * index, updateBrowserAndNextBlockTime) // omitting the borrow action - await actionsContainer.expectEnabledActionAtIndex(2 * index) - } - - async goToEasyBorrowAction(): Promise { - await this.page.goto(buildUrl('easyBorrow')) - } - // #endregion actions - - // #region assertions - async expectLtv(ltv: string): Promise { - await expect(this.page.getByTestId(testIds.easyBorrow.form.ltv)).toHaveText(ltv) - } - - async expectHealthFactor(hf: string): Promise { - const locator = this.page.getByTestId(testIds.component.HealthFactorGauge.value).nth(0) // is rendered twice because of mobile view - await expect(locator).toHaveText(hf) - } - - async expectAssetInputInvalid(errorText: string): Promise { - const locator = this.page.getByTestId(testIds.component.AssetInput.error) - await expect(locator).toHaveText(errorText) - } - - async expectAssetNotListedInDepositSelector(asset: string): Promise { - const depositSelector = this.page - .getByTestId(testIds.easyBorrow.form.deposits) - .getByTestId(testIds.component.MultiAssetSelector.group) - .getByTestId(testIds.component.AssetSelector.trigger) - await depositSelector.click() - await expect(this.page.getByRole('listbox')).not.toHaveText(asset) - } - - async expectBorrowButtonActive(): Promise { - await expect(this.page.locator('main').getByRole('button', { name: 'Borrow' })).toBeEnabled() - } - - async expectUsdsBorrowAlert(): Promise { - await expect(this.page.getByTestId(testIds.easyBorrow.form.usdsBorrowAlert)).toBeVisible() - } - - async expectSuccessPage({ - deposited, - borrowed, - testnetClient, - assetsWorthOverride, - }: { - deposited: TestTokenWithValue[] - borrowed: TestTokenWithValue - testnetClient: TestnetClient - assetsWorthOverride?: Record - }): Promise { - await expect(this.page.getByText('Congrats, all done!')).toBeVisible() - - const transformed = [...deposited, borrowed].reduce( - (acc, { asset, amount: value }) => ({ ...acc, [asset]: value }), - {}, - ) - - const assetsWorth = await (async () => { - if (assetsWorthOverride) { - return assetsWorthOverride - } - - const { assetsWorth } = await calculateAssetsWorth(getUrlFromClient(testnetClient), transformed) - return assetsWorth - })() - - if (deposited.length > 0) { - const depositSummary = await this.page.getByTestId(testIds.easyBorrow.success.deposited).textContent() - expectAssets(depositSummary!, deposited, assetsWorth) - } - - const borrowSummary = await this.page.getByTestId(testIds.easyBorrow.success.borrowed).textContent() - expectAssets(borrowSummary!, [borrowed], assetsWorth) - } - // #endregion -} +// import { expect } from '@playwright/test' + +// import { ActionsPageObject } from '@/features/actions/ActionsContainer.PageObject' +// import { BasePageObject } from '@/test/e2e/BasePageObject' +// import { TestTokenWithValue, expectAssets } from '@/test/e2e/assertions' +// import { buildUrl } from '@/test/e2e/setup' +// import { calculateAssetsWorth } from '@/test/e2e/utils' +// import { testIds } from '@/ui/utils/testIds' +// import { TestnetClient, getUrlFromClient } from '@marsfoundation/common-testnets' + +// export class BorrowPageObject extends BasePageObject { +// // #region actions +// async fillDepositAssetAction(index: number, asset: string, amount: number): Promise { +// const inputGroup = this.page +// .getByTestId(testIds.easyBorrow.form.deposits) +// .getByTestId(testIds.component.MultiAssetSelector.group) +// .nth(index) + +// const selector = inputGroup.getByTestId(testIds.component.AssetSelector.trigger) +// await this.selectOptionByLabelAction(selector, asset) + +// await inputGroup.getByRole('textbox').fill(amount.toString()) +// } + +// async selectBorrowAction(assetName: string): Promise { +// const borrowSelector = this.page +// .getByTestId(testIds.easyBorrow.form.borrow) +// .getByTestId(testIds.component.AssetSelector.trigger) +// await this.selectOptionByLabelAction(borrowSelector, assetName) +// } + +// async fillBorrowAssetAction(amount: number): Promise { +// const borrowForm = this.page.getByTestId(testIds.easyBorrow.form.borrow) + +// await borrowForm.getByRole('textbox').fill(amount.toString()) +// } + +// async submitAction(): Promise { +// await this.page.locator('main').getByRole('button', { name: 'Borrow' }).click() +// } + +// async addNewDepositAssetAction(): Promise { +// return this.page.getByRole('button', { name: 'Add more' }).click() +// } + +// async viewInMyPortfolioAction(): Promise { +// await this.page.getByRole('link', { name: 'View in portfolio' }).click() +// } + +// async viewInSavingsAction(): Promise { +// await this.page.getByRole('link', { name: 'View in Savings' }).click() +// } + +// async depositAssetsActions({ +// assetsToDeposit, +// daiToBorrow, +// updateBrowserAndNextBlockTime, +// }: { +// assetsToDeposit: Record +// daiToBorrow: number +// updateBrowserAndNextBlockTime: () => Promise +// }): Promise { +// const actionsContainer = new ActionsPageObject(this.locatePanelByHeader('Actions')) +// await this.depositWithoutBorrowActions({ +// assetsToDeposit, +// daiToBorrow, +// actionsContainer, +// updateBrowserAndNextBlockTime, +// }) +// await actionsContainer.acceptActionAtIndex( +// Object.entries(assetsToDeposit).length * 2, +// updateBrowserAndNextBlockTime, +// ) // accept final borrow action +// } + +// async depositWithoutBorrowActions({ +// assetsToDeposit, +// daiToBorrow, +// actionsContainer: _actionsContainer, +// updateBrowserAndNextBlockTime, +// }: { +// assetsToDeposit: Record +// daiToBorrow?: number +// actionsContainer?: ActionsPageObject +// updateBrowserAndNextBlockTime: () => Promise +// }): Promise { +// const actionsContainer = _actionsContainer ?? new ActionsPageObject(this.locatePanelByHeader('Actions')) + +// let index = 0 +// for (const [asset, amount] of Object.entries(assetsToDeposit)) { +// if (index !== 0) { +// await this.addNewDepositAssetAction() +// } +// await this.fillDepositAssetAction(index, asset, amount) +// index++ +// } +// await this.fillBorrowAssetAction(daiToBorrow ?? 1) // defaulted value won't matter, if only depositing +// await this.submitAction() +// await actionsContainer.acceptAllActionsAction(2 * index, updateBrowserAndNextBlockTime) // omitting the borrow action +// await actionsContainer.expectEnabledActionAtIndex(2 * index) +// } + +// async goToEasyBorrowAction(): Promise { +// await this.page.goto(buildUrl('easyBorrow')) +// } +// // #endregion actions + +// // #region assertions +// async expectLtv(ltv: string): Promise { +// await expect(this.page.getByTestId(testIds.easyBorrow.form.ltv)).toHaveText(ltv) +// } + +// async expectHealthFactor(hf: string): Promise { +// const locator = this.page.getByTestId(testIds.component.HealthFactorGauge.value).nth(0) // is rendered twice because of mobile view +// await expect(locator).toHaveText(hf) +// } + +// async expectAssetInputInvalid(errorText: string): Promise { +// const locator = this.page.getByTestId(testIds.component.AssetInput.error) +// await expect(locator).toHaveText(errorText) +// } + +// async expectAssetNotListedInDepositSelector(asset: string): Promise { +// const depositSelector = this.page +// .getByTestId(testIds.easyBorrow.form.deposits) +// .getByTestId(testIds.component.MultiAssetSelector.group) +// .getByTestId(testIds.component.AssetSelector.trigger) +// await depositSelector.click() +// await expect(this.page.getByRole('listbox')).not.toHaveText(asset) +// } + +// async expectBorrowButtonActive(): Promise { +// await expect(this.page.locator('main').getByRole('button', { name: 'Borrow' })).toBeEnabled() +// } + +// async expectUsdsBorrowAlert(): Promise { +// await expect(this.page.getByTestId(testIds.easyBorrow.form.usdsBorrowAlert)).toBeVisible() +// } + +// async expectSuccessPage({ +// deposited, +// borrowed, +// testnetClient, +// assetsWorthOverride, +// }: { +// deposited: TestTokenWithValue[] +// borrowed: TestTokenWithValue +// testnetClient: TestnetClient +// assetsWorthOverride?: Record +// }): Promise { +// await expect(this.page.getByText('Congrats, all done!')).toBeVisible() + +// const transformed = [...deposited, borrowed].reduce( +// (acc, { asset, amount: value }) => ({ ...acc, [asset]: value }), +// {}, +// ) + +// const assetsWorth = await (async () => { +// if (assetsWorthOverride) { +// return assetsWorthOverride +// } + +// const { assetsWorth } = await calculateAssetsWorth(getUrlFromClient(testnetClient), transformed) +// return assetsWorth +// })() + +// if (deposited.length > 0) { +// const depositSummary = await this.page.getByTestId(testIds.easyBorrow.success.deposited).textContent() +// expectAssets(depositSummary!, deposited, assetsWorth) +// } + +// const borrowSummary = await this.page.getByTestId(testIds.easyBorrow.success.borrowed).textContent() +// expectAssets(borrowSummary!, [borrowed], assetsWorth) +// } +// // #endregion +// } diff --git a/packages/app/src/test/e2e/BasePageObject.ts b/packages/app/src/test/e2e/BasePageObject.ts index 7052138d0..6d24bef75 100644 --- a/packages/app/src/test/e2e/BasePageObject.ts +++ b/packages/app/src/test/e2e/BasePageObject.ts @@ -1,21 +1,22 @@ import { testIds } from '@/ui/utils/testIds' import { Locator, Page, expect } from '@playwright/test' -import { isPage } from './utils' +import { TestContext } from './setup' /** * BasePageObject is a class that contains common selectors and actions that are shared across the whole app. */ export class BasePageObject { + protected readonly testContext: TestContext protected readonly page: Page protected region: Locator - constructor(pageOrLocator: Page | Locator) { - if (isPage(pageOrLocator)) { - this.page = pageOrLocator - this.region = pageOrLocator.locator('body') + constructor(testContext: TestContext, locator?: Locator) { + this.testContext = testContext + this.page = testContext.page + if (locator) { + this.region = locator } else { - this.page = pageOrLocator.page() - this.region = pageOrLocator + this.region = this.page.locator('body') } } diff --git a/packages/app/src/test/e2e/setup.ts b/packages/app/src/test/e2e/setup.ts index 30c346118..3414a87de 100644 --- a/packages/app/src/test/e2e/setup.ts +++ b/packages/app/src/test/e2e/setup.ts @@ -59,17 +59,23 @@ export interface SetupOptions { skipInjectingNetwork?: boolean } -export type SetupReturn = (T extends 'not-connected' ? {} : { account: Address }) & { - testnetClient: TestnetClient - updateBrowserAndNextBlockTime: (seconds: number) => Promise - incrementTime: (seconds: number) => Promise +export type ProgressSimulation = (seconds: number) => Promise +export interface TestnetController { + client: TestnetClient + progressSimulation: ProgressSimulation + progressSimulationAndMine: ProgressSimulation +} + +export type TestContext = (T extends 'not-connected' ? {} : { account: Address }) & { + testnetController: TestnetController + page: Page } // should be called at the beginning of any test export async function setup( page: Page, options: SetupOptions, -): Promise> { +): Promise> { const { client: testnetClient, initialSnapshotId } = await getTestnetContext(options.blockchain) await testnetClient.revert(initialSnapshotId) @@ -77,7 +83,7 @@ export async function setup( const address = await setupAccount({ page, testnetClient, options: options.account }) await page.goto(buildUrl(options.initialPage, options.initialPageParams)) - async function updateBrowserAndNextBlockTime(seconds: number): Promise { + async function progressSimulation(seconds: number): Promise { const { timestamp: currentTimestamp } = await testnetClient.getBlock() const progressedTimestamp = currentTimestamp + BigInt(seconds) @@ -85,21 +91,25 @@ export async function setup( await injectUpdatedDate(page, new Date(Number(currentTimestamp) * 1000)) } - async function incrementTime(seconds: number): Promise { - await updateBrowserAndNextBlockTime(seconds) + async function progressSimulationAndMine(seconds: number): Promise { + await progressSimulation(seconds) await testnetClient.mineBlocks(1n) - await updateBrowserAndNextBlockTime(5) + await progressSimulation(1) } - // @note: Sync time in browser with current time on blockchain, - // set next block to be mined timestamp to be 5 seconds more. - await updateBrowserAndNextBlockTime(5) + // @note: Set next block to be mined timestamp to be 5 seconds more. + await progressSimulation(5) + + const testnetController = { + client: testnetClient, + progressSimulation, + progressSimulationAndMine, + } return { + page, account: address, - testnetClient, - updateBrowserAndNextBlockTime, - incrementTime, + testnetController, } as any }