Skip to content

Commit e3a5282

Browse files
authored
chore(predict): Adds correct no search results found empty state (#22654)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** - Adds correct empty state when no search results are found <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: [PRED-295](https://consensyssoftware.atlassian.net/browse/PRED-295) ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <img width="420" alt="Simulator Screenshot - iPhone 16 Pro Max - 2025-11-13 at 10 06 02" src="https://github.com/user-attachments/assets/5d0d9aec-49e0-4e48-acf7-28ed878dda32" /> <img width="420" alt="Simulator Screenshot - iPhone 16 Pro Max - 2025-11-13 at 09 57 57" src="https://github.com/user-attachments/assets/927646d3-cab1-4144-8da6-1c4afd1e3831" /> ## **Pre-merge author checklist** - [x] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [PRED-295]: https://consensyssoftware.atlassian.net/browse/PRED-295?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds a localized, themed empty state for no search results in Predict market list, updates styles/tests, and adds i18n strings and assets. > > - **Predict UI**: > - **Search Empty State**: When `q` is present and no results, render themed illustration and message in `app/components/UI/Predict/components/MarketListContent/MarketListContent.tsx` using `useAssetFromTheme`, `PredictionsLight/Dark` SVGs, and `strings('predict.search_no_markets_found', { q })`. > - **Default Empty State**: Replace hardcoded copy with `strings('predict.search_empty_state', { category })`. > - **Styles**: Add `emptySearchContainer` in `MarketListContent.styles.ts`. > - **Tests**: > - Update `MarketListContent.test.tsx` to support `q` prop, and add test asserting search empty state (icon + localized text) via `getPredictMarketListSelector.emptyState()`. > - **Assets & i18n**: > - Add `predictions-no-search-results-light.svg` and `predictions-no-search-results-dark.svg`. > - Add `predict.search_empty_state` and `predict.search_no_markets_found` to `locales/languages/en.json`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 2f19186. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 20f3ae5 commit e3a5282

File tree

6 files changed

+145
-3
lines changed

6 files changed

+145
-3
lines changed

app/components/UI/Predict/components/MarketListContent/MarketListContent.styles.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ const styleSheet = () =>
2424
width: '100%',
2525
padding: 16,
2626
},
27+
emptySearchContainer: {
28+
justifyContent: 'center',
29+
alignItems: 'center',
30+
width: '100%',
31+
marginTop: 42,
32+
padding: 16,
33+
},
2734
marketListContainer: {
2835
flex: 1,
2936
width: '100%',

app/components/UI/Predict/components/MarketListContent/MarketListContent.test.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import renderWithProvider from '../../../../../util/test/renderWithProvider';
55
import { backgroundState } from '../../../../../util/test/initial-root-state';
66
import { PredictCategory, PredictMarket, Recurrence } from '../../types';
77
import { usePredictMarketData } from '../../hooks/usePredictMarketData';
8+
import { strings } from '../../../../../../locales/i18n';
9+
import { getPredictMarketListSelector } from '../../../../../../e2e/selectors/Predict/Predict.selectors';
810

911
// Mock animations to prevent act() warnings
1012
jest.mock('react-native/Libraries/Animated/Animated', () => {
@@ -172,13 +174,14 @@ const initialState = {
172174
function setupMarketListContentTest(
173175
marketDataOverrides = {},
174176
category: PredictCategory = 'trending',
177+
q?: string,
175178
) {
176179
jest.clearAllMocks();
177180
mockUsePredictMarketData.mockReturnValue({
178181
...defaultMockReturn,
179182
...marketDataOverrides,
180183
});
181-
return renderWithProvider(<MarketListContent category={category} />, {
184+
return renderWithProvider(<MarketListContent category={category} q={q} />, {
182185
state: initialState,
183186
});
184187
}
@@ -255,6 +258,26 @@ describe('MarketListContent', () => {
255258

256259
expect(getByText('No crypto markets available')).toBeOnTheScreen();
257260
});
261+
262+
it('renders search empty state when query has no matching markets', () => {
263+
const searchTerm = 'bitcoin';
264+
const expectedEmptySearchText = strings(
265+
'predict.search_no_markets_found',
266+
{ q: searchTerm },
267+
);
268+
269+
const { getByText, getByTestId } = setupMarketListContentTest(
270+
{ marketData: [] },
271+
'crypto',
272+
searchTerm,
273+
);
274+
275+
expect(
276+
getByTestId(getPredictMarketListSelector.emptyState()),
277+
).toBeOnTheScreen();
278+
expect(getByTestId('icon')).toBeOnTheScreen();
279+
expect(getByText(expectedEmptySearchText)).toBeOnTheScreen();
280+
});
258281
});
259282

260283
describe('Data Rendering', () => {

app/components/UI/Predict/components/MarketListContent/MarketListContent.tsx

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ import PredictMarketSkeleton from '../PredictMarketSkeleton';
2222
import { getPredictMarketListSelector } from '../../../../../../e2e/selectors/Predict/Predict.selectors';
2323
import { ScrollCoordinator } from '../../types/scrollCoordinator';
2424
import PredictOffline from '../PredictOffline';
25-
25+
import { strings } from '../../../../../../locales/i18n';
26+
import PredictionsDark from '../../../../../images/predictions-no-search-results-dark.svg';
27+
import PredictionsLight from '../../../../../images/predictions-no-search-results-light.svg';
28+
import { useAssetFromTheme } from '../../../../../util/theme';
2629
interface MarketListContentProps {
2730
q?: string;
2831
category: PredictCategory;
@@ -43,6 +46,10 @@ const MarketListContent: React.FC<MarketListContentProps> = ({
4346
scrollCoordinator,
4447
}) => {
4548
const { styles } = useStyles(styleSheet, {});
49+
const ThemedPredictions = useAssetFromTheme(
50+
PredictionsLight,
51+
PredictionsDark,
52+
);
4653
const tw = useTailwind();
4754
const {
4855
marketData,
@@ -115,14 +122,33 @@ const MarketListContent: React.FC<MarketListContentProps> = ({
115122
return <PredictOffline onRetry={handleRefresh} />;
116123
}
117124

125+
if (q && q.length > 0 && marketData.length === 0) {
126+
return (
127+
<Box
128+
testID={getPredictMarketListSelector.emptyState()}
129+
style={styles.emptySearchContainer}
130+
>
131+
<ThemedPredictions
132+
testID="icon"
133+
width={100}
134+
height={100}
135+
style={tw.style('mb-4')}
136+
/>
137+
<Text variant={TextVariant.BodyMD} color={TextColor.Alternative}>
138+
{strings('predict.search_no_markets_found', { q })}
139+
</Text>
140+
</Box>
141+
);
142+
}
143+
118144
if (!marketData || marketData.length === 0) {
119145
return (
120146
<Box
121147
testID={getPredictMarketListSelector.emptyState()}
122148
style={styles.emptyContainer}
123149
>
124150
<Text variant={TextVariant.BodyMD} color={TextColor.Alternative}>
125-
No {category} markets available
151+
{strings('predict.search_empty_state', { category })}
126152
</Text>
127153
</Box>
128154
);
Lines changed: 42 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)