Skip to content

Commit 6c19369

Browse files
committed
chore: address merge conflicts
1 parent 6afb395 commit 6c19369

1 file changed

Lines changed: 84 additions & 239 deletions

File tree

app/components/UI/Perps/Views/PerpsClosePositionView/PerpsClosePositionView.test.tsx

Lines changed: 84 additions & 239 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { act, fireEvent, render, waitFor } from '@testing-library/react-native';
22
import {
33
PERPS_EVENT_PROPERTY,
44
PERPS_EVENT_VALUE,
5-
ORDER_SLIPPAGE_CONFIG
5+
ORDER_SLIPPAGE_CONFIG,
66
} from '@metamask/perps-controller';
77
import { MetaMetricsEvents } from '../../../../../core/Analytics';
88
import React from 'react';
@@ -1998,7 +1998,6 @@ describe('PerpsClosePositionView', () => {
19981998
// HyperLiquid's marginUsed already includes PnL
19991999
// receivedAmount = marginUsed - fees = 1450 - 45 = 1405
20002000
// realizedPnl = unrealizedPnl = 150 (from defaultPerpsPositionMock)
2001-
<<<<<<< HEAD
20022001
expect(handleClosePosition).toHaveBeenCalledWith(
20032002
expect.objectContaining({
20042003
position: defaultPerpsPositionMock,
@@ -2022,167 +2021,11 @@ describe('PerpsClosePositionView', () => {
20222021
slippage: {
20232022
usdAmount: undefined, // undefined for full close to bypass $10 minimum validation
20242023
priceAtCalculation: 3000, // effectivePrice: currentPrice for market orders
2025-
maxSlippageBps: 300, // maxSlippageBps: 3% slippage tolerance (300 basis points) - conservative default
2024+
maxSlippageBps: ORDER_SLIPPAGE_CONFIG.DefaultMarketSlippageBps,
20262025
},
20272026
}),
20282027
);
20292028
});
2030-
2031-
it('validates limit order requires price before confirmation', async () => {
2032-
// Test the early return in handleConfirm when limit has no price
2033-
const handleClosePosition = jest.fn();
2034-
usePerpsClosePositionMock.mockReturnValue({
2035-
handleClosePosition,
2036-
isClosing: false,
2037-
});
2038-
2039-
// Create a test component that simulates limit order without price
2040-
const TestComponent = () => {
2041-
const [orderType] = React.useState<'market' | 'limit'>('limit');
2042-
const [limitPrice] = React.useState(''); // No price set
2043-
2044-
return (
2045-
<TouchableOpacity
2046-
testID="test-confirm-no-price"
2047-
onPress={async () => {
2048-
// This simulates the handleConfirm logic that returns early
2049-
if (orderType === 'limit' && !limitPrice) {
2050-
return; // Early return - should not call handleClosePosition
2051-
}
2052-
await handleClosePosition();
2053-
}}
2054-
>
2055-
<Text>Confirm</Text>
2056-
</TouchableOpacity>
2057-
);
2058-
};
2059-
2060-
const { getByTestId } = render(<TestComponent />);
2061-
2062-
// Act - Try to confirm without limit price
2063-
fireEvent.press(getByTestId('test-confirm-no-price'));
2064-
2065-
// Assert - Should NOT call handleClosePosition due to early return
2066-
await waitFor(() => {
2067-
expect(handleClosePosition).not.toHaveBeenCalled();
2068-
});
2069-
});
2070-
2071-
it('handles limit order confirmation with price validation', async () => {
2072-
// Arrange
2073-
const handleClosePosition = jest.fn().mockResolvedValue(undefined);
2074-
usePerpsClosePositionMock.mockReturnValue({
2075-
handleClosePosition,
2076-
isClosing: false,
2077-
});
2078-
2079-
// Mock a component state with limit order and price
2080-
const TestComponent = () => {
2081-
const [orderType] = React.useState<'market' | 'limit'>('limit');
2082-
const [limitPrice] = React.useState('50000');
2083-
2084-
return (
2085-
<View>
2086-
<TouchableOpacity
2087-
testID="test-confirm"
2088-
onPress={async () => {
2089-
// Simulate the handleConfirm logic for limit orders
2090-
if (orderType === 'limit' && !limitPrice) {
2091-
return; // Should not proceed without price
2092-
}
2093-
await handleClosePosition({
2094-
position: defaultPerpsPositionMock,
2095-
size: '',
2096-
orderType,
2097-
limitPrice: orderType === 'limit' ? limitPrice : undefined,
2098-
trackingData: {
2099-
totalFee: 45,
2100-
marketPrice: 3000,
2101-
receivedAmount: 1405,
2102-
realizedPnl: 150,
2103-
metamaskFeeRate: 0,
2104-
feeDiscountPercentage: undefined,
2105-
metamaskFee: 0,
2106-
estimatedPoints: undefined,
2107-
inputMethod: 'default',
2108-
},
2109-
marketPrice: '3000.00',
2110-
slippage: {
2111-
usdAmount: '4500',
2112-
priceAtCalculation: 3000,
2113-
maxSlippageBps: 100,
2114-
},
2115-
});
2116-
}}
2117-
>
2118-
<Text>Confirm</Text>
2119-
</TouchableOpacity>
2120-
</View>
2121-
);
2122-
};
2123-
2124-
const { getByTestId } = render(<TestComponent />);
2125-
2126-
// Act - Press confirm for limit order
2127-
fireEvent.press(getByTestId('test-confirm'));
2128-
2129-
// Assert - Should call with limit price and specific calculated values
2130-
await waitFor(() => {
2131-
expect(handleClosePosition).toHaveBeenCalledWith(
2132-
expect.objectContaining({
2133-
position: defaultPerpsPositionMock,
2134-
size: '',
2135-
orderType: 'limit',
2136-
limitPrice: '50000',
2137-
trackingData: expect.objectContaining({
2138-
totalFee: 45,
2139-
marketPrice: 3000,
2140-
receivedAmount: 1405,
2141-
realizedPnl: 150,
2142-
metamaskFeeRate: 0,
2143-
metamaskFee: 0,
2144-
feeDiscountPercentage: undefined,
2145-
estimatedPoints: undefined,
2146-
inputMethod: 'default',
2147-
}),
2148-
marketPrice: '3000.00',
2149-
slippage: {
2150-
usdAmount: '4500',
2151-
priceAtCalculation: 3000,
2152-
maxSlippageBps: 100,
2153-
},
2154-
}),
2155-
);
2156-
});
2157-
});
2158-
=======
2159-
expect(handleClosePosition).toHaveBeenCalledWith({
2160-
position: defaultPerpsPositionMock,
2161-
size: '',
2162-
orderType: 'market',
2163-
limitPrice: undefined,
2164-
trackingData: {
2165-
totalFee: 45,
2166-
marketPrice: 3000,
2167-
receivedAmount: 1405,
2168-
realizedPnl: 150,
2169-
metamaskFeeRate: 0,
2170-
metamaskFee: 0,
2171-
feeDiscountPercentage: undefined,
2172-
estimatedPoints: undefined,
2173-
inputMethod: 'default',
2174-
},
2175-
marketPrice: '3000.00',
2176-
// Slippage parameters added in USD-as-source-of-truth refactor
2177-
// For full closes (100%), usdAmount is undefined to bypass $10 minimum validation
2178-
slippage: {
2179-
usdAmount: undefined, // undefined for full close to bypass $10 minimum validation
2180-
priceAtCalculation: 3000, // effectivePrice: currentPrice for market orders
2181-
maxSlippageBps: ORDER_SLIPPAGE_CONFIG.DefaultMarketSlippageBps,
2182-
},
2183-
});
2184-
});
2185-
>>>>>>> main
21862029
});
21872030

21882031
describe('Keypad Interaction - Real Component', () => {
@@ -3214,7 +3057,6 @@ describe('PerpsClosePositionView', () => {
32143057
});
32153058
});
32163059

3217-
<<<<<<< HEAD
32183060
describe('abandon order tracking', () => {
32193061
const abandonInteraction = [
32203062
MetaMetricsEvents.PERPS_UI_INTERACTION,
@@ -3290,7 +3132,88 @@ describe('PerpsClosePositionView', () => {
32903132
const fire = setupAbandonNav([{ key: 'close' }]);
32913133
const { getByTestId } = renderWithProvider(<PerpsClosePositionView />);
32923134

3293-
=======
3135+
fireEvent.press(
3136+
getByTestId(
3137+
PerpsClosePositionViewSelectorsIDs.CLOSE_POSITION_CONFIRM_BUTTON,
3138+
),
3139+
);
3140+
act(() => fire('beforeRemove'));
3141+
3142+
expect(defaultPerpsEventTrackingMock.track).not.toHaveBeenCalledWith(
3143+
...abandonInteraction,
3144+
);
3145+
});
3146+
});
3147+
3148+
describe('position_close entry action (button_clicked)', () => {
3149+
const expectScreenViewed = (expected: Record<string, unknown>) =>
3150+
expect(defaultPerpsEventTrackingMock.track).toHaveBeenCalledWith(
3151+
MetaMetricsEvents.PERPS_SCREEN_VIEWED,
3152+
expect.objectContaining({
3153+
[PERPS_EVENT_PROPERTY.SCREEN_TYPE]:
3154+
PERPS_EVENT_VALUE.SCREEN_TYPE.POSITION_CLOSE,
3155+
...expected,
3156+
}),
3157+
);
3158+
3159+
it('reports button_clicked=reduce_exposure and source=position_screen when opened via the reduce-exposure entry', () => {
3160+
useRouteMock.mockReturnValue({
3161+
params: {
3162+
position: defaultPerpsPositionMock,
3163+
source: PERPS_EVENT_VALUE.SOURCE.POSITION_SCREEN,
3164+
buttonClicked: PERPS_EVENT_VALUE.BUTTON_CLICKED.REDUCE_EXPOSURE,
3165+
buttonLocation: PERPS_EVENT_VALUE.BUTTON_LOCATION.SCREEN,
3166+
},
3167+
});
3168+
3169+
renderWithProvider(<PerpsClosePositionView />);
3170+
3171+
expectScreenViewed({
3172+
[PERPS_EVENT_PROPERTY.SOURCE]: PERPS_EVENT_VALUE.SOURCE.POSITION_SCREEN,
3173+
[PERPS_EVENT_PROPERTY.BUTTON_CLICKED]:
3174+
PERPS_EVENT_VALUE.BUTTON_CLICKED.REDUCE_EXPOSURE,
3175+
[PERPS_EVENT_PROPERTY.BUTTON_LOCATION]:
3176+
PERPS_EVENT_VALUE.BUTTON_LOCATION.SCREEN,
3177+
});
3178+
});
3179+
3180+
it('reports button_clicked=close and source=order_book when opened via the order-book close entry', () => {
3181+
useRouteMock.mockReturnValue({
3182+
params: {
3183+
position: defaultPerpsPositionMock,
3184+
source: PERPS_EVENT_VALUE.SOURCE.ORDER_BOOK,
3185+
buttonClicked: PERPS_EVENT_VALUE.BUTTON_CLICKED.CLOSE,
3186+
buttonLocation: PERPS_EVENT_VALUE.BUTTON_LOCATION.ORDER_BOOK,
3187+
},
3188+
});
3189+
3190+
renderWithProvider(<PerpsClosePositionView />);
3191+
3192+
expectScreenViewed({
3193+
[PERPS_EVENT_PROPERTY.SOURCE]: PERPS_EVENT_VALUE.SOURCE.ORDER_BOOK,
3194+
[PERPS_EVENT_PROPERTY.BUTTON_CLICKED]:
3195+
PERPS_EVENT_VALUE.BUTTON_CLICKED.CLOSE,
3196+
[PERPS_EVENT_PROPERTY.BUTTON_LOCATION]:
3197+
PERPS_EVENT_VALUE.BUTTON_LOCATION.ORDER_BOOK,
3198+
});
3199+
});
3200+
3201+
it('defaults button_clicked=close and source=perp_asset_screen when no entry action is provided', () => {
3202+
useRouteMock.mockReturnValue({
3203+
params: { position: defaultPerpsPositionMock },
3204+
});
3205+
3206+
renderWithProvider(<PerpsClosePositionView />);
3207+
3208+
expectScreenViewed({
3209+
[PERPS_EVENT_PROPERTY.SOURCE]:
3210+
PERPS_EVENT_VALUE.SOURCE.PERP_ASSET_SCREEN,
3211+
[PERPS_EVENT_PROPERTY.BUTTON_CLICKED]:
3212+
PERPS_EVENT_VALUE.BUTTON_CLICKED.CLOSE,
3213+
});
3214+
});
3215+
});
3216+
32943217
describe('Order type selector (feature flag)', () => {
32953218
const selectPerpsClosePositionLimitOrderEnabledFlagMock = jest.mocked(
32963219
jest.requireMock('../../selectors/featureFlags')
@@ -3421,88 +3344,11 @@ describe('PerpsClosePositionView', () => {
34213344
).toBeNull();
34223345

34233346
// Act - confirm the close
3424-
>>>>>>> main
34253347
fireEvent.press(
34263348
getByTestId(
34273349
PerpsClosePositionViewSelectorsIDs.CLOSE_POSITION_CONFIRM_BUTTON,
34283350
),
34293351
);
3430-
<<<<<<< HEAD
3431-
act(() => fire('beforeRemove'));
3432-
3433-
expect(defaultPerpsEventTrackingMock.track).not.toHaveBeenCalledWith(
3434-
...abandonInteraction,
3435-
);
3436-
});
3437-
});
3438-
3439-
describe('position_close entry action (button_clicked)', () => {
3440-
const expectScreenViewed = (expected: Record<string, unknown>) =>
3441-
expect(defaultPerpsEventTrackingMock.track).toHaveBeenCalledWith(
3442-
MetaMetricsEvents.PERPS_SCREEN_VIEWED,
3443-
expect.objectContaining({
3444-
[PERPS_EVENT_PROPERTY.SCREEN_TYPE]:
3445-
PERPS_EVENT_VALUE.SCREEN_TYPE.POSITION_CLOSE,
3446-
...expected,
3447-
}),
3448-
);
3449-
3450-
it('reports button_clicked=reduce_exposure and source=position_screen when opened via the reduce-exposure entry', () => {
3451-
useRouteMock.mockReturnValue({
3452-
params: {
3453-
position: defaultPerpsPositionMock,
3454-
source: PERPS_EVENT_VALUE.SOURCE.POSITION_SCREEN,
3455-
buttonClicked: PERPS_EVENT_VALUE.BUTTON_CLICKED.REDUCE_EXPOSURE,
3456-
buttonLocation: PERPS_EVENT_VALUE.BUTTON_LOCATION.SCREEN,
3457-
},
3458-
});
3459-
3460-
renderWithProvider(<PerpsClosePositionView />);
3461-
3462-
expectScreenViewed({
3463-
[PERPS_EVENT_PROPERTY.SOURCE]: PERPS_EVENT_VALUE.SOURCE.POSITION_SCREEN,
3464-
[PERPS_EVENT_PROPERTY.BUTTON_CLICKED]:
3465-
PERPS_EVENT_VALUE.BUTTON_CLICKED.REDUCE_EXPOSURE,
3466-
[PERPS_EVENT_PROPERTY.BUTTON_LOCATION]:
3467-
PERPS_EVENT_VALUE.BUTTON_LOCATION.SCREEN,
3468-
});
3469-
});
3470-
3471-
it('reports button_clicked=close and source=order_book when opened via the order-book close entry', () => {
3472-
useRouteMock.mockReturnValue({
3473-
params: {
3474-
position: defaultPerpsPositionMock,
3475-
source: PERPS_EVENT_VALUE.SOURCE.ORDER_BOOK,
3476-
buttonClicked: PERPS_EVENT_VALUE.BUTTON_CLICKED.CLOSE,
3477-
buttonLocation: PERPS_EVENT_VALUE.BUTTON_LOCATION.ORDER_BOOK,
3478-
},
3479-
});
3480-
3481-
renderWithProvider(<PerpsClosePositionView />);
3482-
3483-
expectScreenViewed({
3484-
[PERPS_EVENT_PROPERTY.SOURCE]: PERPS_EVENT_VALUE.SOURCE.ORDER_BOOK,
3485-
[PERPS_EVENT_PROPERTY.BUTTON_CLICKED]:
3486-
PERPS_EVENT_VALUE.BUTTON_CLICKED.CLOSE,
3487-
[PERPS_EVENT_PROPERTY.BUTTON_LOCATION]:
3488-
PERPS_EVENT_VALUE.BUTTON_LOCATION.ORDER_BOOK,
3489-
});
3490-
});
3491-
3492-
it('defaults button_clicked=close and source=perp_asset_screen when no entry action is provided', () => {
3493-
useRouteMock.mockReturnValue({
3494-
params: { position: defaultPerpsPositionMock },
3495-
});
3496-
3497-
renderWithProvider(<PerpsClosePositionView />);
3498-
3499-
expectScreenViewed({
3500-
[PERPS_EVENT_PROPERTY.SOURCE]:
3501-
PERPS_EVENT_VALUE.SOURCE.PERP_ASSET_SCREEN,
3502-
[PERPS_EVENT_PROPERTY.BUTTON_CLICKED]:
3503-
PERPS_EVENT_VALUE.BUTTON_CLICKED.CLOSE,
3504-
});
3505-
=======
35063352

35073353
// Assert - a market close is submitted, never a limit order behind the flag
35083354
await waitFor(() => {
@@ -3551,7 +3397,6 @@ describe('PerpsClosePositionView', () => {
35513397
expect(
35523398
queryByTestId(PerpsLimitPriceBottomSheetSelectorsIDs.CONFIRM_BUTTON),
35533399
).toBeNull();
3554-
>>>>>>> main
35553400
});
35563401
});
35573402
});

0 commit comments

Comments
 (0)