Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/components/Nav/Main/MainNavigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ const HomeTabs = () => {
<Tab.Screen
name={Routes.REWARDS_VIEW}
options={options.rewards}
component={RewardsHome}
component={RewardsModalFlow}
layout={({ children }) => UnmountOnBlurComponent(children)}
/>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,6 @@ const PerpsClosePositionView: React.FC = () => {
<PerpsAmountDisplay
label={strings('perps.close_position.select_amount')}
amount={displayMode === 'usd' ? closeAmountUSDString : closeAmount}
maxAmount={positionValue}
showWarning={false}
onPress={handleAmountPress}
isActive={isInputFocused}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -743,10 +743,11 @@ const PerpsOrderViewContentBase: React.FC = () => {
{/* Amount Display */}
<PerpsAmountDisplay
amount={orderForm.amount}
maxAmount={availableBalance * orderForm.leverage}
showWarning={availableBalance === 0}
onPress={handleAmountPress}
isActive={isInputFocused}
tokenAmount={positionSize}
tokenSymbol={orderForm.asset}
/>

{/* Amount Slider - Hide when keypad is active */}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { render, fireEvent } from '@testing-library/react-native';
import { render, fireEvent, screen } from '@testing-library/react-native';
import { PerpsAmountDisplaySelectorsIDs } from '../../../../../../e2e/selectors/Perps/Perps.selectors';
import PerpsAmountDisplay from './PerpsAmountDisplay';
import { formatPrice, formatPositionSize } from '../../utils/formatUtils';

Expand Down Expand Up @@ -38,30 +39,23 @@ describe('PerpsAmountDisplay', () => {
});

describe('Rendering', () => {
it('displays amount and max amount with proper formatting', () => {
it('displays amount with proper formatting', () => {
// Arrange
const amount = '1000';
const maxAmount = 5000;

// Act
const { getByText } = render(
<PerpsAmountDisplay amount={amount} maxAmount={maxAmount} />,
);
const { getByText } = render(<PerpsAmountDisplay amount={amount} />);

// Assert
expect(getByText('$1000')).toBeTruthy();
expect(getByText('$5000 max')).toBeTruthy();
});

it('displays $0 when amount is empty', () => {
// Arrange
const emptyAmount = '';
const maxAmount = 5000;

// Act
const { getByText } = render(
<PerpsAmountDisplay amount={emptyAmount} maxAmount={maxAmount} />,
);
const { getByText } = render(<PerpsAmountDisplay amount={emptyAmount} />);

// Assert
expect(getByText('$0')).toBeTruthy();
Expand All @@ -71,15 +65,10 @@ describe('PerpsAmountDisplay', () => {
// Arrange - Testing branch coverage for line 72
const label = 'Enter Amount';
const amount = '1000';
const maxAmount = 10000;

// Act
const { getByText } = render(
<PerpsAmountDisplay
amount={amount}
label={label}
maxAmount={maxAmount}
/>,
<PerpsAmountDisplay amount={amount} label={label} />,
);

// Assert
Expand All @@ -91,21 +80,23 @@ describe('PerpsAmountDisplay', () => {
const tokenAmount = '0.5';
const tokenSymbol = 'ETH';
const amount = '1000';
const maxAmount = 10000;

// Act
const { getByText } = render(
render(
<PerpsAmountDisplay
amount={amount}
maxAmount={maxAmount}
showTokenAmount
tokenAmount={tokenAmount}
tokenSymbol={tokenSymbol}
/>,
);

// Assert
expect(getByText(`${tokenAmount} ${tokenSymbol}`)).toBeTruthy();
// There will be 2 elements: one in the main display and one in the token amount section
const tokenElements = screen.getAllByText(
`${tokenAmount} ${tokenSymbol}`,
);
expect(tokenElements.length).toBe(2);
expect(formatPositionSize).toHaveBeenCalledWith(tokenAmount);
});
});
Expand All @@ -114,15 +105,10 @@ describe('PerpsAmountDisplay', () => {
it('shows default warning when showWarning is true and maxAmount is 0', () => {
// Arrange
const amount = '1000';
const maxAmount = 0;

// Act
const { getByText } = render(
<PerpsAmountDisplay
amount={amount}
maxAmount={maxAmount}
showWarning
/>,
<PerpsAmountDisplay amount={amount} showWarning />,
);

// Assert
Expand All @@ -135,13 +121,11 @@ describe('PerpsAmountDisplay', () => {
// Arrange
const customMessage = 'Insufficient balance';
const amount = '1000';
const maxAmount = 5000;

// Act
const { getByText } = render(
<PerpsAmountDisplay
amount={amount}
maxAmount={maxAmount}
showWarning
warningMessage={customMessage}
/>,
Expand All @@ -157,15 +141,10 @@ describe('PerpsAmountDisplay', () => {
// Arrange
const onPressMock = jest.fn();
const amount = '1000';
const maxAmount = 5000;

// Act
const { getByText } = render(
<PerpsAmountDisplay
amount={amount}
maxAmount={maxAmount}
onPress={onPressMock}
/>,
<PerpsAmountDisplay amount={amount} onPress={onPressMock} />,
);
fireEvent.press(getByText('$1000'));

Expand All @@ -176,12 +155,9 @@ describe('PerpsAmountDisplay', () => {
it('handles press gracefully when onPress is not provided', () => {
// Arrange
const amount = '1000';
const maxAmount = 5000;

// Act
const { getByText } = render(
<PerpsAmountDisplay amount={amount} maxAmount={maxAmount} />,
);
const { getByText } = render(<PerpsAmountDisplay amount={amount} />);

// Assert - This should not throw an error
expect(() => fireEvent.press(getByText('$1000'))).not.toThrow();
Expand All @@ -192,11 +168,10 @@ describe('PerpsAmountDisplay', () => {
it('shows cursor when isActive is true', () => {
// Arrange
const amount = '1000';
const maxAmount = 5000;

// Act
const { getByTestId } = render(
<PerpsAmountDisplay amount={amount} maxAmount={maxAmount} isActive />,
<PerpsAmountDisplay amount={amount} isActive />,
);

// Assert
Expand All @@ -206,49 +181,101 @@ describe('PerpsAmountDisplay', () => {
it('hides cursor when isActive is false', () => {
// Arrange
const amount = '1000';
const maxAmount = 5000;

// Act
const { queryByTestId } = render(
<PerpsAmountDisplay amount={amount} isActive={false} />,
);

// Assert
expect(queryByTestId('cursor')).toBeNull();
});
});

describe('Token Amount Display', () => {
it('displays token amount when showMaxAmount is true with token data', () => {
// Arrange
const amount = '1000';
const tokenAmount = '0.025';
const tokenSymbol = 'BTC';

// Act
const { getByText } = render(
<PerpsAmountDisplay
amount={amount}
maxAmount={maxAmount}
isActive={false}
showMaxAmount
tokenAmount={tokenAmount}
tokenSymbol={tokenSymbol}
/>,
);

// Assert
expect(queryByTestId('cursor')).toBeNull();
expect(getByText('0.025 BTC')).toBeTruthy();
expect(formatPositionSize).toHaveBeenCalledWith(tokenAmount);
});

it('does not display token amount when showMaxAmount is false', () => {
// Arrange
const amount = '1000';
const tokenAmount = '0.025';
const tokenSymbol = 'BTC';

// Act
const { queryByText } = render(
<PerpsAmountDisplay
amount={amount}
showMaxAmount={false}
tokenAmount={tokenAmount}
tokenSymbol={tokenSymbol}
/>,
);

// Assert
expect(queryByText('0.025 BTC')).toBeNull();
});

it('does not display anything when showMaxAmount is true but no token data', () => {
// Arrange
const amount = '1000';

// Act
const { queryByTestId } = render(
<PerpsAmountDisplay amount={amount} showMaxAmount />,
);

// Assert - The component should not show the token amount section
// When no token data is provided, the token amount section won't be rendered
// We verify by checking if the amount display is there but no token text
expect(
queryByTestId(PerpsAmountDisplaySelectorsIDs.CONTAINER),
).toBeTruthy();
// No token amount should be displayed
expect(screen.queryByText(/BTC|ETH|SOL/)).toBeNull();
});
});

describe('Formatting', () => {
it('formats prices with correct decimal places', () => {
// Arrange
const amount = '1234.56';
const maxAmount = 9876.54;

// Act
render(<PerpsAmountDisplay amount={amount} maxAmount={maxAmount} />);
render(<PerpsAmountDisplay amount={amount} />);

// Assert
expect(formatPrice).toHaveBeenCalledWith('1234.56', {
minimumDecimals: 0,
maximumDecimals: 2,
});
expect(formatPrice).toHaveBeenCalledWith(9876.54, {
minimumDecimals: 2,
maximumDecimals: 2,
});
// Note: formatPrice is no longer called with maxAmount for display
});

it('formats USD amounts with maximum 2 decimal places', () => {
// Arrange
const amount = '1234.5678';
const maxAmount = 5000;

// Act
render(<PerpsAmountDisplay amount={amount} maxAmount={maxAmount} />);
render(<PerpsAmountDisplay amount={amount} />);

// Assert - Verify USD amounts are limited to 2 decimal places
expect(formatPrice).toHaveBeenCalledWith('1234.5678', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ import Text, {
import { useTheme } from '../../../../../util/theme';
import { formatPrice, formatPositionSize } from '../../utils/formatUtils';
import createStyles from './PerpsAmountDisplay.styles';
import { strings } from '../../../../../../locales/i18n';

interface PerpsAmountDisplayProps {
amount: string;
maxAmount: number;
showWarning?: boolean;
warningMessage?: string;
onPress?: () => void;
Expand All @@ -26,7 +24,6 @@ interface PerpsAmountDisplayProps {

const PerpsAmountDisplay: React.FC<PerpsAmountDisplayProps> = ({
amount,
maxAmount,
showWarning = false,
warningMessage = 'No funds available. Please deposit first.',
onPress,
Expand Down Expand Up @@ -106,15 +103,15 @@ const PerpsAmountDisplay: React.FC<PerpsAmountDisplayProps> = ({
/>
)}
</View>
{showMaxAmount && (
{/* Display token amount equivalent for current input */}
{showMaxAmount && tokenAmount && tokenSymbol && (
<Text
variant={TextVariant.BodyMD}
color={TextColor.Alternative}
style={styles.maxAmount}
testID={PerpsAmountDisplaySelectorsIDs.MAX_LABEL}
>
{formatPrice(maxAmount, { minimumDecimals: 2, maximumDecimals: 2 })}{' '}
{strings('perps.order.max')}
{formatPositionSize(tokenAmount)} {tokenSymbol}
</Text>
)}
{showWarning && (
Expand Down
Loading
Loading