diff --git a/packages/app/.env.playwright b/packages/app/.env.playwright index 847fc84de..08ff13cce 100644 --- a/packages/app/.env.playwright +++ b/packages/app/.env.playwright @@ -4,6 +4,6 @@ VITE_PLAYWRIGHT=true VITE_FEATURE_CONFIGURABLE_SLIPPAGE=1 # development -VITE_DEV_NATIVE_ROUTES=0 +VITE_DEV_NATIVE_ROUTES=1 VITE_BLOCK_ANALITICA_API_URL=https://spark-api.blockanalitica.com/api diff --git a/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/MakerTransactionOverview.tsx b/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/MakerTransactionOverview.tsx index 890bd6b41..2d987cfeb 100644 --- a/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/MakerTransactionOverview.tsx +++ b/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/MakerTransactionOverview.tsx @@ -23,33 +23,28 @@ export function MakerTransactionOverview({ txOverview, selectedToken }: MakerTra assert(route.length > 0, 'Route must have at least one item') const outcome = route.at(-1)! - let dataTestIdIndex = 0 - return ( Transaction overview - + - +
{route.map((item, index) => ( - + ))}
- +
- - + +
) diff --git a/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/APYDetails.tsx b/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/APYDetails.tsx index dea2e2283..5500a5d29 100644 --- a/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/APYDetails.tsx +++ b/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/APYDetails.tsx @@ -1,6 +1,7 @@ import { formatPercentage } from '@/domain/common/format' import { NormalizedUnitNumber, Percentage } from '@/domain/types/NumericValues' import { USD_MOCK_TOKEN } from '@/domain/types/Token' +import { testIds } from '@/ui/utils/testIds' export interface APYDetailsProps { APY: Percentage @@ -10,8 +11,13 @@ export interface APYDetailsProps { export function APYDetails({ APY, daiEarnRate }: APYDetailsProps) { return (
-
{formatPercentage(APY)}
-
Earn ~{USD_MOCK_TOKEN.formatUSD(daiEarnRate)} DAI per year
+
{formatPercentage(APY)}
+
+ Earn ~{USD_MOCK_TOKEN.format(daiEarnRate, { style: 'auto' })} DAI per year +
) } diff --git a/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/MakerBadge.tsx b/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/MakerBadge.tsx index 9aaec1387..da92c7896 100644 --- a/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/MakerBadge.tsx +++ b/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/MakerBadge.tsx @@ -4,11 +4,15 @@ import { Info } from '@/ui/molecules/info/Info' export interface MakerBadgeProps { token: Token + 'data-testid'?: string } -export function MakerBadge({ token }: MakerBadgeProps) { +export function MakerBadge({ token, 'data-testid': dataTestId }: MakerBadgeProps) { return ( -
+
Powered by Maker. diff --git a/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/RouteItem.tsx b/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/RouteItem.tsx index 9ae77c7ce..0feb40e35 100644 --- a/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/RouteItem.tsx +++ b/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/RouteItem.tsx @@ -1,19 +1,24 @@ import { USD_MOCK_TOKEN } from '@/domain/types/Token' import { assets } from '@/ui/assets' import { cn } from '@/ui/utils/style' +import { testIds } from '@/ui/utils/testIds' import { RouteItem as RouteItemType } from '../../../types' export interface RouteItemProps { item: RouteItemType + index: number isLast: boolean } -export function RouteItem({ item, isLast }: RouteItemProps) { +export function RouteItem({ item, index, isLast }: RouteItemProps) { return (
-
+
{item.token.format(item.value, { style: 'auto' })} {item.token.symbol}
-
+
{USD_MOCK_TOKEN.formatUSD(item.usdValue)}
{!isLast && ( diff --git a/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/TransactionOutcome.tsx b/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/TransactionOutcome.tsx index 218527786..a27d62836 100644 --- a/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/TransactionOutcome.tsx +++ b/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/TransactionOutcome.tsx @@ -3,11 +3,12 @@ import { RouteItem } from '../../../types' export interface TransactionOutcomeProps { outcome: RouteItem + 'data-testid'?: string } -export function TransactionOutcome({ outcome }: TransactionOutcomeProps) { +export function TransactionOutcome({ outcome, 'data-testid': dataTestId }: TransactionOutcomeProps) { return ( -
+
{outcome.token.format(outcome.value, { style: 'auto' })} {outcome.token.symbol} diff --git a/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/TransactionOverviewDetailsItem.tsx b/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/TransactionOverviewDetailsItem.tsx index 0a068f19c..fe661789b 100644 --- a/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/TransactionOverviewDetailsItem.tsx +++ b/packages/app/src/features/dialogs/savings/common/components/maker-transaction-overview/components/TransactionOverviewDetailsItem.tsx @@ -3,16 +3,11 @@ import { ReactNode } from 'react' export interface TransactionOverviewDetailsItemProps { label: string children: ReactNode - 'data-testid'?: string } -export function TransactionOverviewDetailsItem({ - label, - children, - 'data-testid': dataTestId, -}: TransactionOverviewDetailsItemProps) { +export function TransactionOverviewDetailsItem({ label, children }: TransactionOverviewDetailsItemProps) { return ( -
+
{label}
{children}
diff --git a/packages/app/src/features/dialogs/savings/deposit/SavingsDepositDialog.PageObject.ts b/packages/app/src/features/dialogs/savings/deposit/SavingsDepositDialog.PageObject.ts index ac26eab38..8e75bb092 100644 --- a/packages/app/src/features/dialogs/savings/deposit/SavingsDepositDialog.PageObject.ts +++ b/packages/app/src/features/dialogs/savings/deposit/SavingsDepositDialog.PageObject.ts @@ -45,6 +45,44 @@ export class SavingsDepositDialogPageObject extends DialogPageObject { } } + async expectNativeRouteTransactionOverview(transactionOverview: NativeRouteTransactionOverview): Promise { + const panel = this.locatePanelByHeader('Transaction overview') + await expect(panel).toBeVisible() + const txOverviewTestIds = testIds.dialog.savings.nativeRouteTransactionOverview + + const apyValue = panel.getByTestId(txOverviewTestIds.apy.value) + const apyDescription = panel.getByTestId(txOverviewTestIds.apy.description) + await expect(apyValue).toContainText(transactionOverview.apy.value) + await expect(apyDescription).toContainText(transactionOverview.apy.description) + + for (const [index, { tokenAmount: tokenWithAmount, tokenUsdValue }] of transactionOverview.routeItems.entries()) { + const routeItem = panel.getByTestId(txOverviewTestIds.routeItem.tokenWithAmount(index)) + const routeItemUSD = panel.getByTestId(txOverviewTestIds.routeItem.tokenUsdValue(index)) + await expect(routeItem).toContainText(tokenWithAmount) + await expect(routeItemUSD).toContainText(tokenUsdValue) + } + + const makerBadge = panel.getByTestId(txOverviewTestIds.makerBadge) + await expect(makerBadge).toBeVisible() + + const outcome = panel.getByTestId(txOverviewTestIds.outcome) + await expect(outcome).toContainText(transactionOverview.outcome) + } + + async expectToUseNativeSDaiAction(nativeSDaiDepositParams: { + title: string + type: 'deposit' | 'withdraw' + }): Promise { + const testId = + nativeSDaiDepositParams.type === 'deposit' + ? testIds.actions.flavours.nativeSDaiDepositActionRow.wrapper + : testIds.actions.flavours.nativeSDaiWithdrawActionRow.wrapper + const depositRow = this.locatePanelByHeader('Actions').getByTestId(testId) + + await expect(depositRow).toBeVisible() + await expect(depositRow).toContainText(nativeSDaiDepositParams.title) + } + async expectToUseLifiSwap(lifiSwapParams: LifiSwapParams): Promise { const exchangeRow = this.locatePanelByHeader('Actions').getByTestId( testIds.actions.flavours.exchangeActionRow.wrapper, @@ -82,3 +120,15 @@ interface LifiSwapParams { } type TransactionOverview = [string, string][] + +interface NativeRouteTransactionOverview { + apy: { + value: string + description: string + } + routeItems: { + tokenAmount: string + tokenUsdValue: string + }[] + outcome: string +} diff --git a/packages/app/src/features/dialogs/savings/deposit/e2e/DepositDAI.test-e2e.ts b/packages/app/src/features/dialogs/savings/deposit/e2e/DepositDAI.test-e2e.ts new file mode 100644 index 000000000..2d0f0440f --- /dev/null +++ b/packages/app/src/features/dialogs/savings/deposit/e2e/DepositDAI.test-e2e.ts @@ -0,0 +1,71 @@ +import { ActionsPageObject } from '@/features/actions/ActionsContainer.PageObject' +import { SavingsPageObject } from '@/pages/Savings.PageObject' +import { DEFAULT_BLOCK_NUMBER } from '@/test/e2e/constants' +import { setup } from '@/test/e2e/setup' +import { setupFork } from '@/test/e2e/setupFork' +import { test } from '@playwright/test' +import { mainnet } from 'viem/chains' +import { SavingsDepositDialogPageObject } from '../SavingsDepositDialog.PageObject' + +test.describe('Deposit DAI on Mainnet', () => { + const fork = setupFork({ blockNumber: DEFAULT_BLOCK_NUMBER, chainId: mainnet.id }) + let savingsPage: SavingsPageObject + let depositDialog: SavingsDepositDialogPageObject + + test.beforeEach(async ({ page }) => { + await setup(page, fork, { + initialPage: 'savings', + account: { + type: 'connected', + assetBalances: { + ETH: 1, + DAI: 10_000, + }, + }, + }) + + savingsPage = new SavingsPageObject(page) + await savingsPage.clickDepositButtonAction('DAI') + + depositDialog = new SavingsDepositDialogPageObject(page) + await depositDialog.fillAmountAction(10_000) + }) + + test('uses native sDai deposit', async ({ page, browser }) => { + await depositDialog.expectToUseNativeSDaiAction({ + title: 'Wrap DAI into sDAI', + type: 'deposit', + }) + }) + + test('displays transaction overview', async () => { + await depositDialog.expectNativeRouteTransactionOverview({ + apy: { + value: '5.00%', + description: 'Earn ~$500.00 DAI per year', + }, + routeItems: [ + { + tokenAmount: '10,000.00 DAI', + tokenUsdValue: '$10,000.00', + }, + { + tokenAmount: '9,332.66 sDAI', + tokenUsdValue: '$10,000.00', + }, + ], + outcome: '9,332.66 sDAI worth $10,000.00', + }) + }) + + test('executes deposit', async () => { + const actionsContainer = new ActionsPageObject(depositDialog.locatePanelByHeader('Actions')) + await actionsContainer.acceptAllActionsAction(2) + + await depositDialog.expectSuccessPage() + await depositDialog.clickBackToSavingsButton() + + await savingsPage.expectSavingsBalance({ sDaiBalance: '9,332.66 sDAI', estimatedDaiValue: '10,000' }) + await savingsPage.expectCashInWalletAssetBalance('DAI', '-') + }) +}) diff --git a/packages/app/src/ui/utils/testIds.ts b/packages/app/src/ui/utils/testIds.ts index bb35465c8..d133e8a97 100644 --- a/packages/app/src/ui/utils/testIds.ts +++ b/packages/app/src/ui/utils/testIds.ts @@ -53,6 +53,20 @@ export const testIds = makeTestIds({ }, success: true, acknowledgeRiskSwitch: true, + savings: { + nativeRouteTransactionOverview: { + apy: { + value: true, + description: true, + }, + routeItem: { + tokenWithAmount: (index: number) => index, + tokenUsdValue: (index: number) => index, + }, + outcome: true, + makerBadge: true, + }, + }, depositSavings: { transactionDetailsRow: (index: number) => index, }, @@ -76,6 +90,9 @@ export const testIds = makeTestIds({ nativeSDaiDepositActionRow: { wrapper: true, }, + nativeSDaiWithdrawActionRow: { + wrapper: true, + }, }, }, navbar: {