diff --git a/packages/app/src/pages/MarketDetails.test-e2e.ts b/packages/app/src/pages/MarketDetails.test-e2e.ts index 559b406a3..91aeeffca 100644 --- a/packages/app/src/pages/MarketDetails.test-e2e.ts +++ b/packages/app/src/pages/MarketDetails.test-e2e.ts @@ -1,589 +1,599 @@ -// import { test } from '@playwright/test' -// import { gnosis, mainnet } from 'viem/chains' - -// import { DialogPageObject } from '@/features/dialogs/common/Dialog.PageObject' -// import { DEFAULT_BLOCK_NUMBER, GNOSIS_DEFAULT_BLOCK_NUMBER } from '@/test/e2e/constants' -// import { setupFork } from '@/test/e2e/forking/setupFork' -// import { buildUrl, setup } from '@/test/e2e/setup' -// import { screenshot } from '@/test/e2e/utils' - -// import { BorrowPageObject } from './Borrow.PageObject' -// import { MarketDetailsPageObject } from './MarketDetails.PageObject' - -// test.describe('Market details Mainnet', () => { -// const DAI = '0x6B175474E89094C44Da98b954EedeAC495271d0F' -// const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' -// const WEETH = '0xcd5fe23c85820f7b72d0926fc9b05b43e359b7ee' -// const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' -// const WBTC = '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599' - -// const fork = setupFork({ -// blockNumber: DEFAULT_BLOCK_NUMBER, -// chainId: mainnet.id, -// simulationDateOverride: new Date('2024-09-04T14:21:19Z'), -// }) - -// test.describe('Market overview', () => { -// test('DAI', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: DAI, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) -// await marketDetailsPage.expectMarketOverviewValue('Borrowed', '$910.8M') -// await marketDetailsPage.expectMarketOverviewValue('Instantly available', '$44.01M') -// await marketDetailsPage.expectMarketOverviewValue('Sky capacity', '$1.586B') - -// await screenshot(page, 'market-details-dai') -// }) - -// test('WETH', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: WETH, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) -// await marketDetailsPage.expectMarketOverviewValue('Borrowed', '$571.1M') -// await marketDetailsPage.expectMarketOverviewValue('Instantly available', '$125.4M') - -// await screenshot(page, 'market-details-weth') -// }) - -// test.describe('token that cannot be borrowed', () => { -// test('overview is visible when borrowed balance greater than non-zero', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: WBTC, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) -// await marketDetailsPage.expectToBeLoaded() -// }) - -// test('overview is hidden when borrowed balance equal zero', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: WEETH, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) -// await marketDetailsPage.expectMarketOverviewToBeHidden() -// }) -// }) -// }) - -// test.describe('Dialogs', () => { -// const initialDeposits = { -// wstETH: 10, -// } - -// test('guest state', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: DAI, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectToBeLoaded() - -// await marketDetailsPage.expectConnectWalletButton() -// await marketDetailsPage.expectDialogButtonToBeInvisible('Lend') -// await marketDetailsPage.expectDialogButtonToBeInvisible('Deposit') -// await marketDetailsPage.expectDialogButtonToBeInvisible('Borrow') -// }) - -// test("can't deposit if not enough balance", async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: WETH, chainId: fork.chainId.toString() }, -// account: { -// type: 'connected-random', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectToBeLoaded() - -// await marketDetailsPage.expectDialogButtonToBeInactive('Deposit') -// }) - -// test("can't lend if not enough balance", async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: DAI, chainId: fork.chainId.toString() }, -// account: { -// type: 'connected-random', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectToBeLoaded() - -// await marketDetailsPage.expectDialogButtonToBeInactive('Lend') -// }) - -// test("can't borrow if not enough balance", async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: DAI, chainId: fork.chainId.toString() }, -// account: { -// type: 'connected-random', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectToBeLoaded() - -// await marketDetailsPage.expectBorrowNotAvailableDisclaimer() -// await marketDetailsPage.expectDialogButtonToBeInvisible('Borrow') -// }) - -// test('opens dialogs for DAI', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'easyBorrow', -// account: { -// type: 'connected-random', -// assetBalances: { -// ...initialDeposits, -// DAI: 1000, -// sDAI: 1000, -// }, -// }, -// }) - -// const borrowPage = new BorrowPageObject(page) -// await borrowPage.depositWithoutBorrowActions({ ...initialDeposits }) - -// await page.goto(buildUrl('marketDetails', { asset: DAI, chainId: fork.chainId.toString() })) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.openDialogAction('Lend') -// const lendDialog = new DialogPageObject(page, /Deposit/i) -// await lendDialog.expectDialogHeader('Deposit DAI') -// await lendDialog.closeDialog() - -// await marketDetailsPage.openDialogAction('Deposit') -// const depositDialog = new DialogPageObject(page, /Deposit/i) -// await depositDialog.expectDialogHeader('Deposit sDAI') -// await depositDialog.closeDialog() - -// await marketDetailsPage.openDialogAction('Borrow') -// const borrowDialog = new DialogPageObject(page, /Borrow/i) -// await borrowDialog.expectDialogHeader('Borrow DAI') -// await borrowDialog.closeDialog() -// }) - -// test('opens dialogs for WETH', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'easyBorrow', -// account: { -// type: 'connected-random', -// assetBalances: { -// ...initialDeposits, -// WETH: 10, -// }, -// }, -// }) - -// const borrowPage = new BorrowPageObject(page) -// await borrowPage.depositWithoutBorrowActions({ ...initialDeposits }) - -// await page.goto(buildUrl('marketDetails', { asset: WETH, chainId: fork.chainId.toString() })) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.openDialogAction('Deposit') -// const lendDialog = new DialogPageObject(page, /Deposit/i) -// await lendDialog.expectDialogHeader('Deposit WETH') -// await lendDialog.closeDialog() - -// await marketDetailsPage.openDialogAction('Borrow') -// const borrowDialog = new DialogPageObject(page, /Borrow/i) -// await borrowDialog.expectDialogHeader('Borrow WETH') -// await borrowDialog.closeDialog() -// }) - -// // @todo: this scenario is inaccurate, because user has only ETH - in future dialog should open on ETH tab -// test('opens dialogs for WETH when having only ETH', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'easyBorrow', -// account: { -// type: 'connected-random', -// assetBalances: { -// ...initialDeposits, -// ETH: 5, -// }, -// }, -// }) - -// const borrowPage = new BorrowPageObject(page) -// await borrowPage.depositWithoutBorrowActions({ ...initialDeposits }) - -// await page.goto(buildUrl('marketDetails', { asset: WETH, chainId: fork.chainId.toString() })) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectWalletBalance('5.00 WETH') - -// await marketDetailsPage.openDialogAction('Deposit') -// const lendDialog = new DialogPageObject(page, /Deposit/i) -// await lendDialog.expectDialogHeader('Deposit WETH') -// await lendDialog.closeDialog() - -// await marketDetailsPage.openDialogAction('Borrow') -// const borrowDialog = new DialogPageObject(page, /Borrow/i) -// await borrowDialog.expectDialogHeader('Borrow WETH') -// await borrowDialog.closeDialog() -// }) - -// test('wallet displays sum of WETH and ETH', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { -// asset: WETH, -// chainId: fork.chainId.toString(), -// }, -// account: { -// type: 'connected-random', -// assetBalances: { -// ...initialDeposits, -// ETH: 5, -// WETH: 10, -// }, -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectWalletBalance('15.00 WETH') -// }) -// }) - -// test.describe('Isolated assets', () => { -// const BLOCK_NUMBER_WITH_WEETH = 20118125n -// const fork = setupFork({ blockNumber: BLOCK_NUMBER_WITH_WEETH, chainId: mainnet.id }) - -// test('Correctly displays debt ceiling', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: WEETH, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) -// await marketDetailsPage.expectDebt('$3.17M') -// await marketDetailsPage.expectDebtCeiling('$50M') -// }) -// }) - -// test.describe('Errors', () => { -// const NOT_A_RESERVE = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' - -// test('displays 404 page for unknown chain', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: DAI, chainId: '12345' }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) -// await marketDetailsPage.expect404() -// }) - -// test('displays 404 page for unknown asset', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: NOT_A_RESERVE, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) -// await marketDetailsPage.expect404() -// }) -// }) - -// test.describe('Cap automator', () => { -// test('WETH', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: WETH, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectSupplyCap('403.2K WETH') -// await marketDetailsPage.expectSupplyMaxCap('2M WETH') -// await marketDetailsPage.expectSupplyCapCooldown('0h 00m 00s') - -// await marketDetailsPage.expectBorrowCap('256K WETH') -// await marketDetailsPage.expectBorrowMaxCap('1M WETH') -// await marketDetailsPage.expectBorrowCapCooldown('0h 00m 00s') -// }) - -// test('USDC', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: USDC, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectSupplyPanelNotVisible() - -// await marketDetailsPage.expectBorrowCap('7.678M USDC') -// await marketDetailsPage.expectBorrowMaxCap('57M USDC') -// await marketDetailsPage.expectBorrowCapCooldown('0h 00m 00s') -// }) - -// test('WBTC', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: WBTC, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectSupplyCap('4,780 WBTC') -// await marketDetailsPage.expectSupplyMaxCap('10K WBTC') -// await marketDetailsPage.expectSupplyCapCooldown('0h 00m 00s') - -// await marketDetailsPage.expectBorrowPanelNotVisible() -// await marketDetailsPage.expectToBeDisabledAsCollateral() -// await marketDetailsPage.expectDisabledCollateralInfoVisible() -// }) -// }) - -// test.describe('Oracles', () => { -// test('Fixed price', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: DAI, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectOraclePanelToHaveTitle('Fixed Price') - -// await marketDetailsPage.expectOracleInfo({ -// price: '$1.00', -// asset: 'DAI', -// oracleContract: '0x42a03F81dd8A1cEcD746dc262e4d1CD9fD39F777', -// }) -// }) -// test('Market price - not redundant', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: WBTC, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectOraclePanelToHaveTitle('Market Price') -// await marketDetailsPage.expectOracleToBeNotRedundant() - -// await marketDetailsPage.expectOracleInfo({ -// price: '$58,229.82', -// asset: 'WBTC', -// oracleContract: '0x230E0321Cf38F09e247e50Afc7801EA2351fe56F', -// }) -// }) - -// test('Yielding fixed price - redundant', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: WEETH, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectOraclePanelToHaveTitle('Yielding Fixed Price') -// await marketDetailsPage.expectOracleToBeRedundant() - -// await marketDetailsPage.expectOracleInfo({ -// price: '$2,576.50', -// asset: 'weETH', -// oracleContract: '0x1A6BDB22b9d7a454D20EAf12DB55D6B5F058183D', -// }) -// await marketDetailsPage.expectYieldingFixedOracleBaseAssetInfo({ -// asset: 'WETH', -// price: '$2,460.69', -// oracleContract: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', -// }) -// await marketDetailsPage.expectYieldingFixedOracleRatioInfo({ -// ratio: '1.0471', -// ratioContract: '0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee', -// }) -// }) -// }) -// }) - -// test.describe('Market details Gnosis', () => { -// const XDAI = '0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d' -// const EURe = '0xcB444e90D8198415266c6a2724b7900fb12FC56E' -// const WETH = '0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1' -// const sDAI = '0xaf204776c7245bF4147c2612BF6e5972Ee483701' - -// const fork = setupFork({ -// blockNumber: GNOSIS_DEFAULT_BLOCK_NUMBER, -// chainId: gnosis.id, -// useTenderlyVnet: true, -// }) - -// test.describe('Cap automator', () => { -// test('WETH', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: WETH, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectSupplyCap('5,000 WETH') -// await marketDetailsPage.expectSupplyMaxCapNotVisible() - -// await marketDetailsPage.expectBorrowCap('3,000 WETH') -// await marketDetailsPage.expectBorrowMaxCapNotVisible() -// }) - -// test('XDAI', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: XDAI, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectSupplyCap('20M WXDAI') -// await marketDetailsPage.expectSupplyMaxCapNotVisible() - -// await marketDetailsPage.expectBorrowCap('16M WXDAI') -// await marketDetailsPage.expectBorrowMaxCapNotVisible() - -// await marketDetailsPage.expectCollateralPanelNotVisible() -// }) -// }) - -// test.describe('Oracles', () => { -// test('Fixed price', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: XDAI, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectOraclePanelToHaveTitle('Fixed Price') - -// await marketDetailsPage.expectOracleInfo({ -// price: '$1.00', -// asset: 'WXDAI', -// oracleContract: '0x6FC2871B6d9A94866B7260896257Fd5b50c09900', -// }) -// }) - -// test('Underlying asset price', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: EURe, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectOraclePanelToHaveTitle('Underlying Asset Price') - -// await marketDetailsPage.expectOracleInfo({ -// price: '$1.07', -// asset: 'EUR', -// oracleContract: '0xab70BCB260073d036d1660201e9d5405F5829b7a', -// }) -// }) - -// test('Yielding fixed price - not redundant', async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'marketDetails', -// initialPageParams: { asset: sDAI, chainId: fork.chainId.toString() }, -// account: { -// type: 'not-connected', -// }, -// }) - -// const marketDetailsPage = new MarketDetailsPageObject(page) - -// await marketDetailsPage.expectOraclePanelToHaveTitle('Yielding Fixed Price') -// await marketDetailsPage.expectOracleToBeNotRedundant() - -// await marketDetailsPage.expectOracleInfo({ -// price: '$1.0875', -// asset: 'sDAI', -// oracleContract: '0x1D0f881Ce1a646E2f27Dec3c57Fa056cB838BCC2', -// }) -// await marketDetailsPage.expectYieldingFixedOracleBaseAssetInfo({ -// asset: 'DAI', -// price: '$0.9997', -// oracleContract: '0x678df3415fc31947dA4324eC63212874be5a82f8', -// }) -// await marketDetailsPage.expectYieldingFixedOracleRatioInfo({ -// ratio: '1.0878', -// ratioContract: '0xaf204776c7245bF4147c2612BF6e5972Ee483701', -// }) -// }) -// }) -// }) +import { DialogPageObject } from '@/features/dialogs/common/Dialog.PageObject' +import { DEFAULT_BLOCK_NUMBER, GNOSIS_DEFAULT_BLOCK_NUMBER } from '@/test/e2e/constants' +import { buildUrl, setup } from '@/test/e2e/setup' +import { test } from '@playwright/test' +import { gnosis, mainnet } from 'viem/chains' + +import { BorrowPageObject } from './Borrow.PageObject' +import { MarketDetailsPageObject } from './MarketDetails.PageObject' + +test.describe('Market details Mainnet', () => { + const DAI = '0x6B175474E89094C44Da98b954EedeAC495271d0F' + const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' + const WEETH = '0xcd5fe23c85820f7b72d0926fc9b05b43e359b7ee' + const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' + const WBTC = '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599' + + test.describe('Market overview', () => { + test('DAI', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: DAI, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + await marketDetailsPage.expectMarketOverviewValue('Borrowed', '$1.626B') + await marketDetailsPage.expectMarketOverviewValue('Instantly available', '$112.8M') + await marketDetailsPage.expectMarketOverviewValue('Sky capacity', '$793.4M') + }) + + test('WETH', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: WETH, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + await marketDetailsPage.expectMarketOverviewValue('Borrowed', '$1.365B') + await marketDetailsPage.expectMarketOverviewValue('Instantly available', '$171M') + }) + + test.describe('token that cannot be borrowed', () => { + test('overview is visible when borrowed balance greater than non-zero', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { + blockNumber: DEFAULT_BLOCK_NUMBER, + chainId: mainnet.id, + }, + initialPage: 'marketDetails', + initialPageParams: { asset: WBTC, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + await marketDetailsPage.expectToBeLoaded() + }) + + test('overview is hidden when borrowed balance equal zero', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { + blockNumber: DEFAULT_BLOCK_NUMBER, + chainId: mainnet.id, + }, + initialPage: 'marketDetails', + initialPageParams: { asset: WEETH, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + await marketDetailsPage.expectMarketOverviewToBeHidden() + }) + }) + }) + + test.describe('Dialogs', () => { + const initialDeposits = { + wstETH: 10, + } + + test('guest state', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: DAI, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectToBeLoaded() + + await marketDetailsPage.expectConnectWalletButton() + await marketDetailsPage.expectDialogButtonToBeInvisible('Lend') + await marketDetailsPage.expectDialogButtonToBeInvisible('Deposit') + await marketDetailsPage.expectDialogButtonToBeInvisible('Borrow') + }) + + test("can't deposit if not enough balance", async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: WETH, chainId: mainnet.id.toString() }, + account: { + type: 'connected-random', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectToBeLoaded() + + await marketDetailsPage.expectDialogButtonToBeInactive('Deposit') + }) + + test("can't lend if not enough balance", async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: DAI, chainId: mainnet.id.toString() }, + account: { + type: 'connected-random', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectToBeLoaded() + + await marketDetailsPage.expectDialogButtonToBeInactive('Lend') + }) + + test("can't borrow if not enough balance", async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: DAI, chainId: mainnet.id.toString() }, + account: { + type: 'connected-random', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectToBeLoaded() + + await marketDetailsPage.expectBorrowNotAvailableDisclaimer() + await marketDetailsPage.expectDialogButtonToBeInvisible('Borrow') + }) + + test('opens dialogs for DAI', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'easyBorrow', + account: { + type: 'connected-random', + assetBalances: { + ...initialDeposits, + DAI: 1000, + sDAI: 1000, + }, + }, + }) + + const borrowPage = new BorrowPageObject(testContext) + await borrowPage.depositWithoutBorrowActions({ assetsToDeposit: initialDeposits }) + + await page.goto(buildUrl('marketDetails', { asset: DAI, chainId: mainnet.id.toString() })) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.openDialogAction('Lend') + const lendDialog = new DialogPageObject({ testContext, header: /Deposit/i }) + await lendDialog.expectDialogHeader('Deposit DAI') + await lendDialog.closeDialog() + + await marketDetailsPage.openDialogAction('Deposit') + const depositDialog = new DialogPageObject({ testContext, header: /Deposit/i }) + await depositDialog.expectDialogHeader('Deposit sDAI') + await depositDialog.closeDialog() + + await marketDetailsPage.openDialogAction('Borrow') + const borrowDialog = new DialogPageObject({ testContext, header: /Borrow/i }) + await borrowDialog.expectDialogHeader('Borrow DAI') + await borrowDialog.closeDialog() + }) + + test('opens dialogs for WETH', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'easyBorrow', + account: { + type: 'connected-random', + assetBalances: { + ...initialDeposits, + WETH: 10, + }, + }, + }) + + const borrowPage = new BorrowPageObject(testContext) + await borrowPage.depositWithoutBorrowActions({ assetsToDeposit: initialDeposits }) + + await page.goto(buildUrl('marketDetails', { asset: WETH, chainId: mainnet.id.toString() })) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.openDialogAction('Deposit') + const lendDialog = new DialogPageObject({ testContext, header: /Deposit/i }) + await lendDialog.expectDialogHeader('Deposit WETH') + await lendDialog.closeDialog() + + await marketDetailsPage.openDialogAction('Borrow') + const borrowDialog = new DialogPageObject({ testContext, header: /Borrow/i }) + await borrowDialog.expectDialogHeader('Borrow WETH') + await borrowDialog.closeDialog() + }) + + // @todo: this scenario is inaccurate, because user has only ETH - in future dialog should open on ETH tab + test('opens dialogs for WETH when having only ETH', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'easyBorrow', + account: { + type: 'connected-random', + assetBalances: { + ...initialDeposits, + ETH: 5, + }, + }, + }) + + const borrowPage = new BorrowPageObject(testContext) + await borrowPage.depositWithoutBorrowActions({ assetsToDeposit: initialDeposits }) + + await page.goto(buildUrl('marketDetails', { asset: WETH, chainId: mainnet.id.toString() })) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectWalletBalance('5.00 WETH') + + await marketDetailsPage.openDialogAction('Deposit') + const lendDialog = new DialogPageObject({ testContext, header: /Deposit/i }) + await lendDialog.expectDialogHeader('Deposit WETH') + await lendDialog.closeDialog() + + await marketDetailsPage.openDialogAction('Borrow') + const borrowDialog = new DialogPageObject({ testContext, header: /Borrow/i }) + await borrowDialog.expectDialogHeader('Borrow WETH') + await borrowDialog.closeDialog() + }) + + test('wallet displays sum of WETH and ETH', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { + asset: WETH, + chainId: mainnet.id.toString(), + }, + account: { + type: 'connected-random', + assetBalances: { + ...initialDeposits, + ETH: 5, + WETH: 10, + }, + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectWalletBalance('15.00 WETH') + }) + }) + + test.describe('Isolated assets', () => { + test('Correctly displays debt ceiling', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: WEETH, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + await marketDetailsPage.expectDebt('$89M') + await marketDetailsPage.expectDebtCeiling('$200M') + }) + }) + + test.describe('Errors', () => { + const NOT_A_RESERVE = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' + + test('displays 404 page for unknown chain', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: DAI, chainId: '12345' }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + await marketDetailsPage.expect404() + }) + + test('displays 404 page for unknown asset', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: NOT_A_RESERVE, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + await marketDetailsPage.expect404() + }) + }) + + test.describe('Cap automator', () => { + test('WETH', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: WETH, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectSupplyCap('569.9K WETH') + await marketDetailsPage.expectSupplyMaxCap('2M WETH') + await marketDetailsPage.expectSupplyCapCooldown('0h 00m 00s') + + await marketDetailsPage.expectBorrowCap('368.2K WETH') + await marketDetailsPage.expectBorrowMaxCap('1M WETH') + await marketDetailsPage.expectBorrowCapCooldown('0h 00m 00s') + }) + + test('USDC', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: USDC, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectSupplyPanelNotVisible() + + await marketDetailsPage.expectBorrowCap('7.678M USDC') + await marketDetailsPage.expectBorrowMaxCap('57M USDC') + await marketDetailsPage.expectBorrowCapCooldown('0h 00m 00s') + }) + + test('WBTC', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: WBTC, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectSupplyCap('1,941 WBTC') + await marketDetailsPage.expectSupplyMaxCap('5,000 WBTC') + await marketDetailsPage.expectSupplyCapCooldown('0h 00m 00s') + + await marketDetailsPage.expectBorrowPanelNotVisible() + await marketDetailsPage.expectToBeDisabledAsCollateral() + await marketDetailsPage.expectDisabledCollateralInfoVisible() + }) + }) + + test.describe('Oracles', () => { + test('Fixed price', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: DAI, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectOraclePanelToHaveTitle('Fixed Price') + + await marketDetailsPage.expectOracleInfo({ + price: '$1.00', + asset: 'DAI', + oracleContract: '0x42a03F81dd8A1cEcD746dc262e4d1CD9fD39F777', + }) + }) + test('Market price - not redundant', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: WBTC, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectOraclePanelToHaveTitle('Market Price') + await marketDetailsPage.expectOracleToBeNotRedundant() + + await marketDetailsPage.expectOracleInfo({ + price: '$101,496.42', + asset: 'WBTC', + oracleContract: '0x230E0321Cf38F09e247e50Afc7801EA2351fe56F', + }) + }) + + test('Yielding fixed price - redundant', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: WEETH, chainId: mainnet.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectOraclePanelToHaveTitle('Yielding Fixed Price') + await marketDetailsPage.expectOracleToBeRedundant() + + await marketDetailsPage.expectOracleInfo({ + price: '$4,145.06', + asset: 'weETH', + oracleContract: '0x28897036f8459bFBa886083dD6b4Ce4d2f14a57F', + }) + await marketDetailsPage.expectYieldingFixedOracleBaseAssetInfo({ + asset: 'WETH', + price: '$3,928.31', + oracleContract: '0xb20A1374EfCaFa32F701Ab14316fA2E5b3400eD5', + }) + await marketDetailsPage.expectYieldingFixedOracleRatioInfo({ + ratio: '1.0552', + ratioContract: '0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee', + }) + }) + }) +}) + +test.describe('Market details Gnosis', () => { + const XDAI = '0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d' + const EURe = '0xcB444e90D8198415266c6a2724b7900fb12FC56E' + const WETH = '0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1' + const sDAI = '0xaf204776c7245bF4147c2612BF6e5972Ee483701' + + test.describe('Cap automator', () => { + test('WETH', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: GNOSIS_DEFAULT_BLOCK_NUMBER, chainId: gnosis.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: WETH, chainId: gnosis.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectSupplyCap('5,000 WETH') + await marketDetailsPage.expectSupplyMaxCapNotVisible() + + await marketDetailsPage.expectBorrowCap('3,000 WETH') + await marketDetailsPage.expectBorrowMaxCapNotVisible() + }) + + test('XDAI', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: GNOSIS_DEFAULT_BLOCK_NUMBER, chainId: gnosis.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: XDAI, chainId: gnosis.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectSupplyCap('20M WXDAI') + await marketDetailsPage.expectSupplyMaxCapNotVisible() + + await marketDetailsPage.expectBorrowCap('16M WXDAI') + await marketDetailsPage.expectBorrowMaxCapNotVisible() + + await marketDetailsPage.expectCollateralPanelNotVisible() + }) + }) + + test.describe('Oracles', () => { + test('Fixed price', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: GNOSIS_DEFAULT_BLOCK_NUMBER, chainId: gnosis.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: XDAI, chainId: gnosis.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectOraclePanelToHaveTitle('Fixed Price') + + await marketDetailsPage.expectOracleInfo({ + price: '$1.00', + asset: 'WXDAI', + oracleContract: '0x6FC2871B6d9A94866B7260896257Fd5b50c09900', + }) + }) + + test('Underlying asset price', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: GNOSIS_DEFAULT_BLOCK_NUMBER, chainId: gnosis.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: EURe, chainId: gnosis.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectOraclePanelToHaveTitle('Underlying Asset Price') + + await marketDetailsPage.expectOracleInfo({ + price: '$1.07', + asset: 'EUR', + oracleContract: '0xab70BCB260073d036d1660201e9d5405F5829b7a', + }) + }) + + test('Yielding fixed price - not redundant', async ({ page }) => { + const testContext = await setup(page, { + blockchain: { blockNumber: GNOSIS_DEFAULT_BLOCK_NUMBER, chainId: gnosis.id }, + initialPage: 'marketDetails', + initialPageParams: { asset: sDAI, chainId: gnosis.id.toString() }, + account: { + type: 'not-connected', + }, + }) + + const marketDetailsPage = new MarketDetailsPageObject(testContext) + + await marketDetailsPage.expectOraclePanelToHaveTitle('Yielding Fixed Price') + await marketDetailsPage.expectOracleToBeNotRedundant() + + await marketDetailsPage.expectOracleInfo({ + price: '$1.0875', + asset: 'sDAI', + oracleContract: '0x1D0f881Ce1a646E2f27Dec3c57Fa056cB838BCC2', + }) + await marketDetailsPage.expectYieldingFixedOracleBaseAssetInfo({ + asset: 'DAI', + price: '$0.9997', + oracleContract: '0x678df3415fc31947dA4324eC63212874be5a82f8', + }) + await marketDetailsPage.expectYieldingFixedOracleRatioInfo({ + ratio: '1.0878', + ratioContract: '0xaf204776c7245bF4147c2612BF6e5972Ee483701', + }) + }) + }) +}) diff --git a/packages/app/src/pages/Markets.test-e2e.ts b/packages/app/src/pages/Markets.test-e2e.ts index 20faee6e4..fb69d5f40 100644 --- a/packages/app/src/pages/Markets.test-e2e.ts +++ b/packages/app/src/pages/Markets.test-e2e.ts @@ -1,280 +1,325 @@ -// import { DEFAULT_BLOCK_NUMBER } from '@/test/e2e/constants' -// import { setupFork } from '@/test/e2e/forking/setupFork' -// import { setup } from '@/test/e2e/setup' -// import { test } from '@playwright/test' -// import { mainnet } from 'viem/chains' -// import { MarketsPageObject } from './Markets.PageObject' +import { DEFAULT_BLOCK_NUMBER } from '@/test/e2e/constants' +import { setup } from '@/test/e2e/setup' +import { test } from '@playwright/test' +import { mainnet } from 'viem/chains' +import { MarketsPageObject } from './Markets.PageObject' -// test.describe('Markets', () => { -// const fork = setupFork({ blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }) -// let marketsPage: MarketsPageObject +test.describe('Markets', () => { + let marketsPage: MarketsPageObject -// test.beforeEach(async ({ page }) => { -// await setup(page, fork, { -// initialPage: 'markets', -// account: { -// type: 'not-connected', -// }, -// }) + test.beforeEach(async ({ page }) => { + const testContext = await setup(page, { + blockchain: { + chainId: mainnet.id, + blockNumber: DEFAULT_BLOCK_NUMBER, + }, + initialPage: 'markets', + account: { + type: 'not-connected', + }, + }) -// marketsPage = new MarketsPageObject(page) -// }) + marketsPage = new MarketsPageObject(testContext) + }) -// test('summary', async () => { -// await marketsPage.expectSummary([ -// { description: 'Total market size', value: '$4.441B' }, -// { description: 'Total value locked', value: '$2.869B' }, -// { description: 'Total available', value: '$2.904B' }, -// { description: 'Total borrows', value: '$1.537B' }, -// ]) -// }) + test('summary', async () => { + await marketsPage.expectSummary([ + { description: 'Total market size', value: '$8.145B' }, + { description: 'Total value locked', value: '$5.068B' }, + { description: 'Total available', value: '$5.149B' }, + { description: 'Total borrows', value: '$2.997B' }, + ]) + }) -// test('active markets table', async () => { -// await marketsPage.expectActiveMarketsTable([ -// { -// asset: { -// name: 'Lido Staked ETH', -// symbol: 'wstETH', -// }, -// totalSupplied: { -// tokenAmount: '519K', -// usdValue: '$2.06B', -// }, -// depositAPY: { -// value: '<0.01%', -// }, -// totalBorrowed: { -// tokenAmount: '51.56', -// usdValue: '$204.7K', -// }, -// borrowAPY: { -// value: '0.25%', -// }, -// status: { -// supply: 'Can be supplied', -// collateral: 'Can be used as collateral', -// borrow: 'Can be borrowed', -// }, -// }, -// { -// asset: { -// name: 'DAI Stablecoin', -// symbol: 'DAI', -// }, -// totalSupplied: { -// tokenAmount: '962.8M', -// usdValue: '$962.8M', -// }, -// depositAPY: { -// // @note: This value is different in production since VITE_FEATURE_DISABLE_DAI_LEND is disabled in playwright tests -// value: '8.52%', -// }, -// totalBorrowed: { -// tokenAmount: '913.6M', -// usdValue: '$913.6M', -// }, -// borrowAPY: { -// value: '9.00%', -// hasAirDrop: true, -// }, -// status: { -// // @note: This value is different in production since VITE_FEATURE_DISABLE_DAI_LEND is disabled in playwright tests -// supply: 'Can be supplied', -// collateral: 'Cannot be used as collateral', -// borrow: 'Can be borrowed', -// }, -// }, -// { -// asset: { -// name: 'Ethereum', -// symbol: 'ETH', -// }, -// totalSupplied: { -// tokenAmount: '252.1K', -// usdValue: '$854.8M', -// }, -// depositAPY: { -// value: '1.31%', -// hasAirDrop: true, -// }, -// totalBorrowed: { -// tokenAmount: '177K', -// usdValue: '$600M', -// }, -// borrowAPY: { -// value: '1.97%', -// }, -// status: { -// supply: 'Can be supplied', -// collateral: 'Can be used as collateral', -// borrow: 'Can be borrowed', -// }, -// }, -// { -// asset: { -// name: 'Wrapped BTC', -// symbol: 'WBTC', -// }, -// totalSupplied: { -// tokenAmount: '5,790', -// usdValue: '$358M', -// }, -// depositAPY: { -// value: '<0.01%', -// }, -// totalBorrowed: { -// tokenAmount: '332.8', -// usdValue: '$20.58M', -// }, -// borrowAPY: { -// value: '0.19%', -// }, -// status: { -// supply: 'Can be supplied', -// collateral: 'Can be used as collateral', -// borrow: 'Can be borrowed', -// }, -// }, -// { -// asset: { -// name: 'Rocket Pool Staked ETH', -// symbol: 'rETH', -// }, -// totalSupplied: { -// tokenAmount: '38.95K', -// usdValue: '$146.5M', -// }, -// depositAPY: { -// value: '<0.01%', -// }, -// totalBorrowed: { -// tokenAmount: '6.271', -// usdValue: '$23.59K', -// }, -// borrowAPY: { -// value: '0.25%', -// }, -// status: { -// supply: 'Can be supplied', -// collateral: 'Can be used as collateral', -// borrow: 'Can be borrowed', -// }, -// }, -// { -// asset: { -// name: 'Ether.fi Staked ETH', -// symbol: 'weETH', -// }, -// totalSupplied: { -// tokenAmount: '11.66K', -// usdValue: '$41.17M', -// }, -// depositAPY: { -// value: '0.00%', -// }, -// totalBorrowed: undefined, -// borrowAPY: undefined, -// status: { -// supply: 'Can be supplied', -// collateral: 'Can be used as collateral only in isolation mode', -// borrow: 'Cannot be borrowed', -// }, -// }, -// { -// asset: { -// name: 'Savings Dai', -// symbol: 'sDAI', -// }, -// totalSupplied: { -// tokenAmount: '13.49M', -// usdValue: '$14.73M', -// }, -// depositAPY: { -// value: '0.00%', -// }, -// totalBorrowed: undefined, -// borrowAPY: undefined, -// status: { -// supply: 'Can be supplied', -// collateral: 'Can be used as collateral', -// borrow: 'Cannot be borrowed', -// }, -// }, -// { -// asset: { -// name: 'Circle USD', -// symbol: 'USDC', -// }, -// totalSupplied: { -// tokenAmount: '2.559M', -// usdValue: '$2.559M', -// }, -// depositAPY: { -// value: '5.90%', -// }, -// totalBorrowed: { -// tokenAmount: '2.077M', -// usdValue: '$2.077M', -// }, -// borrowAPY: { -// value: '7.72%', -// }, -// status: { -// supply: 'Can be supplied', -// collateral: 'Cannot be used as collateral', -// borrow: 'Can be borrowed', -// }, -// }, -// { -// asset: { -// name: 'Tether USD', -// symbol: 'USDT', -// }, -// totalSupplied: { -// tokenAmount: '316.6K', -// usdValue: '$316.6K', -// }, -// depositAPY: { -// value: '4.03%', -// }, -// totalBorrowed: { -// tokenAmount: '213.2K', -// usdValue: '$213.2K', -// }, -// borrowAPY: { -// value: '6.36%', -// }, -// status: { -// supply: 'Can be supplied', -// collateral: 'Cannot be used as collateral', -// borrow: 'Can be borrowed', -// }, -// }, -// ]) -// }) + test('active markets table', async () => { + await marketsPage.expectActiveMarketsTable([ + { + asset: { + name: 'Lido Staked ETH', + symbol: 'wstETH', + }, + totalSupplied: { + tokenAmount: '861.3K', + usdValue: '$4.018B', + }, + depositAPY: { + value: '<0.01%', + }, + totalBorrowed: { + tokenAmount: '98.42', + usdValue: '$459.2K', + }, + borrowAPY: { + value: '0.25%', + }, + status: { + supply: 'Can be supplied', + collateral: 'Can be used as collateral', + borrow: 'Can be borrowed', + }, + }, + { + asset: { + name: 'DAI Stablecoin', + symbol: 'DAI', + }, + totalSupplied: { + tokenAmount: '1.739B', + usdValue: '$1.739B', + }, + depositAPY: { + // @note: This value is different in production since VITE_FEATURE_DISABLE_DAI_LEND is disabled in playwright tests + value: '11.69%', + }, + totalBorrowed: { + tokenAmount: '1.626B', + usdValue: '$1.626B', + }, + borrowAPY: { + value: '12.55%', + hasAirDrop: true, + }, + status: { + // @note: This value is different in production since VITE_FEATURE_DISABLE_DAI_LEND is disabled in playwright tests + supply: 'Can be supplied', + collateral: 'Cannot be used as collateral', + borrow: 'Can be borrowed', + }, + }, + { + asset: { + name: 'Ethereum', + symbol: 'ETH', + }, + totalSupplied: { + tokenAmount: '391.1K', + usdValue: '$1.536B', + }, + depositAPY: { + value: '2.03%', + hasAirDrop: true, + }, + totalBorrowed: { + tokenAmount: '347.6K', + usdValue: '$1.365B', + }, + borrowAPY: { + value: '2.41%', + }, + status: { + supply: 'Can be supplied', + collateral: 'Can be used as collateral', + borrow: 'Can be borrowed', + }, + }, + { + asset: { + name: 'Coinbase Wrapped BTC', + symbol: 'cbBTC', + }, + totalSupplied: { + tokenAmount: '2,950', + usdValue: '$300M', + }, + depositAPY: { + value: '<0.01%', + }, + totalBorrowed: { + tokenAmount: '5.65', + usdValue: '$574.6K', + }, + borrowAPY: { + value: '0.01%', + }, + status: { + supply: 'Can be supplied', + collateral: 'Can be used as collateral', + borrow: 'Can be borrowed', + }, + }, + { + asset: { + name: 'Ether.fi Staked ETH', + symbol: 'weETH', + }, + totalSupplied: { + tokenAmount: '51.75', + usdValue: '$214.5M', + }, + depositAPY: { + value: '0.00%', + }, + totalBorrowed: undefined, + borrowAPY: undefined, + status: { + supply: 'Can be supplied', + collateral: 'Can be used as collateral only in isolation mode', + borrow: 'Cannot be borrowed', + }, + }, + { + asset: { + name: 'Wrapped BTC', + symbol: 'WBTC', + }, + totalSupplied: { + tokenAmount: '1,742', + usdValue: '$176.8', + }, + depositAPY: { + value: '<0.01%', + }, + totalBorrowed: { + tokenAmount: '18.12', + usdValue: '$1.839M', + }, + borrowAPY: undefined, + status: { + supply: 'Can be supplied', + collateral: 'Cannot be used as collateral', + borrow: 'Cannot be borrowed', + }, + }, + { + asset: { + name: 'Rocket Pool Staked ETH', + symbol: 'rETH', + }, + totalSupplied: { + tokenAmount: '34.47K', + usdValue: '$152.1M', + }, + depositAPY: { + value: '<0.01%', + }, + totalBorrowed: { + tokenAmount: '7.991', + usdValue: '$35.26K', + }, + borrowAPY: { + value: '0.25%', + }, + status: { + supply: 'Can be supplied', + collateral: 'Can be used as collateral', + borrow: 'Can be borrowed', + }, + }, + { + asset: { + name: 'Savings USDS', + symbol: 'sUSDS', + }, + totalSupplied: { + tokenAmount: '4.154M', + usdValue: '$4.226M', + }, + depositAPY: { + value: '0.00%', + }, + totalBorrowed: undefined, + borrowAPY: undefined, + status: { + supply: 'Can be supplied', + collateral: 'Can be used as collateral', + borrow: 'Cannot be borrowed', + }, + }, + { + asset: { + name: 'Circle USD', + symbol: 'USDC', + }, + totalSupplied: { + tokenAmount: '1.916M', + usdValue: '$1.916M', + }, + depositAPY: { + value: '16.20%', + }, + totalBorrowed: { + tokenAmount: '1.849M', + usdValue: '$1.849M', + }, + borrowAPY: { + value: '17.79%', + }, + status: { + supply: 'Can be supplied', + collateral: 'Cannot be used as collateral', + borrow: 'Can be borrowed', + }, + }, + { + asset: { + name: 'Savings Dai', + symbol: 'sDAI', + }, + totalSupplied: { + tokenAmount: '1.25M', + usdValue: '$1.407M', + }, + depositAPY: { + value: '0.00%', + }, + totalBorrowed: undefined, + borrowAPY: undefined, + status: { + supply: 'Can be supplied', + collateral: 'Can be used as collateral', + borrow: 'Cannot be borrowed', + }, + }, + { + asset: { + name: 'Tether USD', + symbol: 'USDT', + }, + totalSupplied: { + tokenAmount: '579.3K', + usdValue: '$579.3K', + }, + depositAPY: { + value: '6.58%', + }, + totalBorrowed: { + tokenAmount: '424.3K', + usdValue: '$424.3K', + }, + borrowAPY: { + value: '9.60%', + }, + status: { + supply: 'Can be supplied', + collateral: 'Cannot be used as collateral', + borrow: 'Can be borrowed', + }, + }, + ]) + }) -// test('frozen markets table', async () => { -// await marketsPage.showFrozenMarkets() -// await marketsPage.expectFrozenMarketsTable([ -// { -// asset: { -// name: 'Gnosis Token', -// symbol: 'GNO', -// isFrozen: true, -// }, -// totalSupplied: { -// tokenAmount: '55.1', -// usdValue: '$15.91K', -// }, -// depositAPY: undefined, -// totalBorrowed: undefined, -// borrowAPY: undefined, -// status: { -// supply: 'Cannot be supplied', -// collateral: 'Cannot be used as collateral', -// borrow: 'Cannot be borrowed', -// }, -// }, -// ]) -// }) -// }) + test('frozen markets table', async () => { + await marketsPage.showFrozenMarkets() + await marketsPage.expectFrozenMarketsTable([ + { + asset: { + name: 'Gnosis Token', + symbol: 'GNO', + isFrozen: true, + }, + totalSupplied: { + tokenAmount: '5', + usdValue: '$1,459', + }, + depositAPY: undefined, + totalBorrowed: undefined, + borrowAPY: undefined, + status: { + supply: 'Cannot be supplied', + collateral: 'Cannot be used as collateral', + borrow: 'Cannot be borrowed', + }, + }, + ]) + }) +}) diff --git a/packages/app/src/test/e2e/utils.ts b/packages/app/src/test/e2e/utils.ts index 98c53e708..8e96ab494 100644 --- a/packages/app/src/test/e2e/utils.ts +++ b/packages/app/src/test/e2e/utils.ts @@ -10,54 +10,6 @@ import { Locator, Page } from '@playwright/test' import { http, Address, createPublicClient, erc20Abi, weiUnits } from 'viem' import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts' -/** - * Helper function to take deterministic screenshots. - */ -export async function screenshot(pageOrLocator: Page | Locator, name: string): Promise { - const page = isPage(pageOrLocator) ? pageOrLocator : pageOrLocator.page() - const locator = isPage(pageOrLocator) ? page.locator('html') : pageOrLocator - - // note: hide entirely elements that can change in size - const selectorsToHide = [ - `[data-testid="wallet-button"]`, // hide address because it can change - '.toast-notifications', // hide notifications because sometimes they are fast to disappear and can't be captured deterministically - `[data-testid="react-confetti"]`, - ] - // note: mask elements that can change but not in size - const selectorsToMask: string[] = [] - - // hide elements - await page.evaluate((selectors) => { - for (const selector of selectors) { - const element: any = document.querySelector(selector) - if (!element) { - continue // skip if element not found - } - - element.__oldDisplay = element.style.display - element.style.display = 'none' - } - }, selectorsToHide) - - await locator.screenshot({ - path: `__screenshots-e2e__/${name}-${page.viewportSize()?.width}.png`, - animations: 'disabled', - mask: selectorsToMask.map((selector) => page.locator(selector)), - }) - - // unhide elements - await page.evaluate((selectors) => { - for (const selector of selectors) { - const element: any = document.querySelector(selector) - if (!element) { - return - } - - element.style.display = element.__oldDisplay - } - }, selectorsToHide) -} - export async function waitForButtonEnabled(page: Page, name: string): Promise { await page.waitForFunction((name) => { const buttons = document.querySelectorAll('button')