@@ -218,12 +218,18 @@ jest.mock('./components/PerpsMarketFiltersBar', () => {
218218 selectedOptionId,
219219 onSortPress,
220220 onWatchlistToggle,
221+ showStocksCommoditiesDropdown,
222+ stocksCommoditiesFilter,
223+ onStocksCommoditiesPress,
221224 testID,
222225 } : {
223226 selectedOptionId : string ;
224227 onSortPress : ( ) => void ;
225228 showWatchlistOnly : boolean ;
226229 onWatchlistToggle : ( ) => void ;
230+ showStocksCommoditiesDropdown ?: boolean ;
231+ stocksCommoditiesFilter ?: 'all' | 'equity' | 'commodity' ;
232+ onStocksCommoditiesPress ?: ( ) => void ;
227233 testID ?: string ;
228234 } ) {
229235 // Map sort option IDs to display labels
@@ -251,14 +257,31 @@ jest.mock('./components/PerpsMarketFiltersBar', () => {
251257 displayText ,
252258 ) ,
253259 ) ,
254- MockReact . createElement (
255- RNTouchableOpacity ,
256- {
257- testID : testID ? `${ testID } -watchlist-toggle` : undefined ,
258- onPress : onWatchlistToggle ,
259- } ,
260- MockReact . createElement ( Text , null , 'Watchlist' ) ,
261- ) ,
260+ onWatchlistToggle &&
261+ MockReact . createElement (
262+ RNTouchableOpacity ,
263+ {
264+ testID : testID ? `${ testID } -watchlist-toggle` : undefined ,
265+ onPress : onWatchlistToggle ,
266+ } ,
267+ MockReact . createElement ( Text , null , 'Watchlist' ) ,
268+ ) ,
269+ showStocksCommoditiesDropdown &&
270+ onStocksCommoditiesPress &&
271+ MockReact . createElement (
272+ RNTouchableOpacity ,
273+ {
274+ testID : testID
275+ ? `${ testID } -stocks-commodities-dropdown`
276+ : undefined ,
277+ onPress : onStocksCommoditiesPress ,
278+ } ,
279+ MockReact . createElement (
280+ Text ,
281+ null ,
282+ `Stocks/Commodities: ${ stocksCommoditiesFilter || 'all' } ` ,
283+ ) ,
284+ ) ,
262285 ) ;
263286 } ;
264287} ) ;
@@ -1196,41 +1219,127 @@ describe('PerpsMarketListView', () => {
11961219 // Note: TabBar Navigation tests removed - PerpsMarketListView does not render a bottom tab bar
11971220 // The component only renders market type tabs (All, Crypto, Stocks) for filtering markets
11981221
1199- describe ( 'Edge Cases' , ( ) => {
1200- it ( 'handles search with whitespace' , async ( ) => {
1201- const { rerender } = renderWithProvider ( < PerpsMarketListView /> , {
1202- state : mockState ,
1222+ describe ( 'Stocks/Commodities Dropdown' , ( ) => {
1223+ it ( 'does not show stocks/commodities dropdown when showStocksCommoditiesDropdown is false' , async ( ) => {
1224+ renderWithProvider ( < PerpsMarketListView /> , { state : mockState } ) ;
1225+
1226+ // Wait for filter bar to render
1227+ await waitFor ( ( ) => {
1228+ expect ( screen . getByText ( 'Volume' ) ) . toBeOnTheScreen ( ) ;
12031229 } ) ;
12041230
1205- const searchButton = screen . getByTestId (
1206- `${ PerpsMarketListViewSelectorsIDs . CLOSE_BUTTON } -search-toggle` ,
1207- ) ;
1231+ // Verify stocks/commodities dropdown is not present
1232+ expect (
1233+ screen . queryByTestId (
1234+ `${ PerpsMarketListViewSelectorsIDs . SORT_FILTERS } -stocks-commodities-dropdown` ,
1235+ ) ,
1236+ ) . not . toBeOnTheScreen ( ) ;
1237+ } ) ;
12081238
1209- // Press search button - this updates mockSearchVisible
1210- await act ( async ( ) => {
1211- fireEvent . press ( searchButton ) ;
1212- // Force re-render to pick up updated mockSearchVisible
1213- rerender ( < PerpsMarketListView /> ) ;
1239+ it ( 'does not show stocks/commodities dropdown regardless of market type filter' , async ( ) => {
1240+ const { usePerpsMarketListView } = jest . requireMock ( '../../hooks' ) ;
1241+
1242+ // Mock the hook to return stocks_and_commodities as the active filter
1243+ usePerpsMarketListView . mockReturnValue ( {
1244+ markets : mockMarketData ,
1245+ searchState : {
1246+ searchQuery : '' ,
1247+ setSearchQuery : jest . fn ( ) ,
1248+ isSearchVisible : false ,
1249+ setIsSearchVisible : jest . fn ( ) ,
1250+ toggleSearchVisibility : jest . fn ( ) ,
1251+ clearSearch : jest . fn ( ) ,
1252+ } ,
1253+ sortState : {
1254+ selectedOptionId : 'volume' ,
1255+ sortBy : 'volume' ,
1256+ direction : 'desc' ,
1257+ handleOptionChange : jest . fn ( ) ,
1258+ } ,
1259+ favoritesState : {
1260+ showFavoritesOnly : false ,
1261+ setShowFavoritesOnly : jest . fn ( ) ,
1262+ } ,
1263+ marketTypeFilterState : {
1264+ marketTypeFilter : 'stocks_and_commodities' ,
1265+ setMarketTypeFilter : jest . fn ( ) ,
1266+ } ,
1267+ marketCounts : {
1268+ crypto : 3 ,
1269+ equity : 2 ,
1270+ commodity : 1 ,
1271+ forex : 0 ,
1272+ } ,
1273+ isLoading : false ,
1274+ error : null ,
1275+ } ) ;
1276+
1277+ renderWithProvider ( < PerpsMarketListView /> , { state : mockState } ) ;
1278+
1279+ // Wait for filter bar to render
1280+ await waitFor ( ( ) => {
1281+ expect ( screen . getByText ( 'Volume' ) ) . toBeOnTheScreen ( ) ;
12141282 } ) ;
12151283
1216- // Wait for search input to appear (mock should now return isSearchVisible: true)
1217- await waitFor (
1218- ( ) => {
1219- const searchInput = screen . getByPlaceholderText (
1220- 'Search by token symbol' ,
1221- ) ;
1222- expect ( searchInput ) . toBeOnTheScreen ( ) ;
1284+ // Verify stocks/commodities dropdown is still not present even with stocks_and_commodities filter
1285+ expect (
1286+ screen . queryByTestId (
1287+ `${ PerpsMarketListViewSelectorsIDs . SORT_FILTERS } -stocks-commodities-dropdown` ,
1288+ ) ,
1289+ ) . not . toBeOnTheScreen ( ) ;
1290+ } ) ;
1291+ } ) ;
1292+
1293+ describe ( 'Edge Cases' , ( ) => {
1294+ it ( 'filters markets with whitespace-only query' , async ( ) => {
1295+ const { usePerpsMarketListView } = jest . requireMock ( '../../hooks' ) ;
1296+
1297+ // Start with search visible
1298+ mockSearchVisible = true ;
1299+ mockSearchQuery = ' ' ;
1300+
1301+ // Mock to return empty results when search query is whitespace
1302+ usePerpsMarketListView . mockReturnValue ( {
1303+ markets : mockMarketData , // Whitespace is trimmed, so all markets show
1304+ searchState : {
1305+ searchQuery : ' ' ,
1306+ setSearchQuery : mockSetSearchQuery ,
1307+ isSearchVisible : true ,
1308+ setIsSearchVisible : mockSetIsSearchVisible ,
1309+ toggleSearchVisibility : mockToggleSearchVisibility ,
1310+ clearSearch : mockClearSearch ,
12231311 } ,
1224- { timeout : 3000 } ,
1225- ) ;
1312+ sortState : {
1313+ selectedOptionId : 'volume' ,
1314+ sortBy : 'volume' ,
1315+ direction : 'desc' ,
1316+ handleOptionChange : jest . fn ( ) ,
1317+ } ,
1318+ favoritesState : {
1319+ showFavoritesOnly : false ,
1320+ setShowFavoritesOnly : jest . fn ( ) ,
1321+ } ,
1322+ marketTypeFilterState : {
1323+ marketTypeFilter : 'all' ,
1324+ setMarketTypeFilter : jest . fn ( ) ,
1325+ } ,
1326+ marketCounts : {
1327+ crypto : 3 ,
1328+ equity : 0 ,
1329+ commodity : 0 ,
1330+ forex : 0 ,
1331+ } ,
1332+ isLoading : false ,
1333+ error : null ,
1334+ } ) ;
12261335
1336+ renderWithProvider ( < PerpsMarketListView /> , { state : mockState } ) ;
1337+
1338+ // Verify search input is visible
12271339 const searchInput = screen . getByPlaceholderText ( 'Search by token symbol' ) ;
1228- await act ( async ( ) => {
1229- fireEvent . changeText ( searchInput , ' ' ) ;
1230- } ) ;
1340+ expect ( searchInput ) . toBeOnTheScreen ( ) ;
12311341
1232- // Wait for markets to appear (whitespace should be trimmed, so all markets show)
1233- // Note: Multiple tabs may render, so we check that at least one instance exists
1342+ // Verify all markets are still displayed (whitespace is trimmed)
12341343 await waitFor ( ( ) => {
12351344 const btcRows = screen . queryAllByTestId ( 'market-row-BTC' ) ;
12361345 const ethRows = screen . queryAllByTestId ( 'market-row-ETH' ) ;
0 commit comments