Commit 93fba69
authored
feat: OmniSearch integration in WebBrowser (#25358)
## **Description**
This PR integrates the omni-search feature from the Explore page into
the browser URL bar autocomplete, enabling users to search across
multiple categories directly from the browser.
Jira Ticket: https://consensyssoftware.atlassian.net/browse/MCWP-218
### What changed
**New Omni-Search Integration:**
- When users type in the browser URL bar, they now see search results
for:
- **Sites** - Curated web3 sites matching the query
- **Recents** - Recently visited URLs filtered by query
- **Favorites** - Bookmarked URLs filtered by query
- **Tokens** - Trending tokens with price and 24h change
- **Perps** - Perpetual trading markets with leverage info
- **Predictions** - Prediction markets from Polymarket
**Architecture:**
- Reuses the existing `useExploreSearch` hook from TrendingView
- Browser-specific section order: Sites → Recents → Favorites → Tokens →
Perps → Predictions
- Transforms API data (TrendingAsset, PerpsMarketData, PredictMarket) to
unified `AutocompleteSearchResult` type
- Wraps search content with `PerpsConnectionProvider` and
`PerpsStreamProvider` for real-time data
**Result Component Enhancements:**
- Extended `Result.tsx` to render all new result types (Tokens, Perps,
Predictions)
- Added swap button for token results that navigates to swap flow
- Integrated `TrendingTokenLogo` and `PerpsTokenLogo` components
- Shows price and percentage change for tokens and perps
**Type System:**
- Added discriminated union types: `TokenSearchResult`,
`PerpsSearchResult`, `PredictionsSearchResult`
- `AutocompleteSearchResult` is now a union of all result types
- Type-safe category handling with `UrlAutocompleteCategory` enum
**E2E Test Fixes:**
The omni-search integration introduced new API calls that caused E2E
smoke tests to fail with "unmocked request" errors:
- `GET https://token.api.cx.metamask.io/tokens/search?...`
- `GET https://token.api.cx.metamask.io/v3/tokens/trending?...`
**Fix:** Added `TRENDING_API_MOCKS` to the default mock configuration in
`tests/api-mocking/mock-responses/defaults/index.ts`. These mocks
already existed in `trending-api-mocks.ts` but weren't loaded into the
E2E test harness.
**Other Changes:**
- Fixed TypeScript error in `DiscoveryTab.tsx` with proper type
narrowing for union types
- Extended `useExploreSearch` hook to accept custom `sectionsOrder`
option
- Added comprehensive unit tests achieving 85%+ coverage
### Files Changed (14 files)
| File | Description |
|------|-------------|
| `UrlAutocomplete/index.tsx` | Main integration - omni-search hook,
data transformers, search content |
| `UrlAutocomplete/Result.tsx` | Extended to render Tokens, Perps,
Predictions results |
| `UrlAutocomplete/types.ts` | New types for all search result
categories |
| `UrlAutocomplete/UrlAutocomplete.constants.ts` | New constants for
browser search config |
| `UrlAutocomplete/index.test.tsx` | Unit tests for omni-search
integration |
| `UrlAutocomplete/Result.test.tsx` | New unit tests for Result
component |
| `BrowserTab/BrowserTab.tsx` | Updated to handle new result types in
onSelect |
| `DiscoveryTab/DiscoveryTab.tsx` | Fixed TypeScript error with type
narrowing |
| `ExploreSearchResults/ExploreSearchResults.tsx` | Minor updates for
shared hook |
| `ExploreSearchResults/ExploreSearchResults.test.tsx` | Improved test
coverage |
| `useExploreSearch.ts` | Added sectionsOrder option for custom ordering
|
| `useExploreSearch.test.ts` | New unit tests for hook |
| `locales/languages/en.json` | Added localization strings for new
categories |
| `tests/api-mocking/.../defaults/index.ts` | Added `TRENDING_API_MOCKS`
import to fix E2E smoke test failures |
## **Changelog**
CHANGELOG entry: Added omni-search to browser URL bar - search tokens,
perps, and predictions directly from the browser
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: Browser URL Bar Omni-Search
Scenario: User searches for tokens in browser URL bar
Given user is on the browser tab
And user taps on the URL bar
When user types "eth"
Then user sees search results organized by category
And user sees Sites section with matching web3 sites
And user sees Tokens section with Ethereum and related tokens
And each token shows name, symbol, price, and 24h change
And each token has a swap button
Scenario: User initiates swap from search result
Given user has searched for "eth" in the URL bar
And user sees Ethereum in the Tokens section
When user taps the swap button on Ethereum
Then user is navigated to the swap screen
And Ethereum is pre-selected as the destination token
Scenario: User searches for perps markets
Given user is on the browser tab
And user taps on the URL bar
When user types "btc"
Then user sees Perps section with BTC-USD market
And market shows name, symbol, leverage, and price
Scenario: User searches for prediction markets
Given user is on the browser tab
And user taps on the URL bar
When user types "bitcoin"
Then user sees Predictions section with matching markets
And each prediction shows title and status (Open/Closed/Resolved)
Scenario: User sees empty state with recents and favorites
Given user is on the browser tab
And user has browser history and bookmarks
When user taps on the URL bar without typing
Then user sees Recents section with recent URLs
And user sees Favorites section with bookmarked URLs
Scenario: Basic functionality disabled hides API-dependent sections
Given user has disabled basic functionality in settings
And user is on the browser tab
When user types a search query in the URL bar
Then user only sees Recents and Favorites (local data)
And user does not see Tokens, Perps, or Predictions sections
```
## **Screenshots/Recordings**
<!-- Add screenshots/recordings showing:
1. Empty state with Recents and Favorites
2. Search results with Sites, Tokens, Perps, Predictions
3. Token result with swap button
4. Loading state with activity indicator
-->
### **Before**
<!-- Browser URL bar only showed Recents and Favorites -->
### **After**
<!-- Browser URL bar now shows omni-search results across all categories
-->
https://github.com/user-attachments/assets/6bf3cfe8-2e19-42b0-99cf-68f72e8a015c
## **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**
- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] 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.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Expands browser URL autocomplete into a multi-source search that now
triggers additional API-driven sections and new navigation paths
(asset/perps/predictions and swaps). Risk is mainly around UI
correctness, section ordering/loading, and navigation/selection behavior
rather than security-critical logic.
>
> **Overview**
> Browser URL autocomplete is refactored to use `useExploreSearch` (with
a browser-specific section order) and to combine API-driven results
(sites/tokens/perps/predictions) with locally filtered
recents/favorites; empty state is now explicitly limited to
recents/favorites.
>
> `Result` now renders new result types with appropriate icons and
metadata (token price/24h change, perps leverage/price/change,
prediction status/image) and adds a token swap action button. Selection
handling is updated so token/perps/predictions navigate to their detail
screens (and avoid auto-hiding autocomplete), while URL-based results
continue to navigate the webview.
>
> Shared search plumbing is extended by adding an optional
`sectionsOrder` to `useExploreSearch`, tests are expanded/updated
accordingly, new i18n strings are added for the new sections, and
default E2E mocks now include `TRENDING_API_MOCKS` to cover the new
token API calls.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d2c682f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->1 parent be610d8 commit 93fba69
14 files changed
Lines changed: 2283 additions & 227 deletions
File tree
- app/components
- UI/UrlAutocomplete
- Views
- BrowserTab
- DiscoveryTab
- TrendingView
- components/ExploreSearchResults
- hooks
- locales/languages
- tests/api-mocking/mock-responses/defaults
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
9 | | - | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
10 | 18 | | |
11 | 19 | | |
12 | | - | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
13 | 38 | | |
14 | 39 | | |
15 | 40 | | |
16 | 41 | | |
| 42 | + | |
| 43 | + | |
17 | 44 | | |
18 | 45 | | |
19 | | - | |
20 | | - | |
21 | | - | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
22 | 73 | | |
23 | | - | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
24 | 78 | | |
25 | | - | |
| 79 | + | |
26 | 80 | | |
27 | | - | |
28 | | - | |
29 | | - | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
30 | 84 | | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
47 | 218 | | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
Lines changed: 43 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
4 | 36 | | |
5 | 37 | | |
6 | 38 | | |
7 | 39 | | |
8 | 40 | | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
0 commit comments