Skip to content
Merged
Show file tree
Hide file tree
Changes from 209 commits
Commits
Show all changes
212 commits
Select commit Hold shift + click to select a range
15edc39
feat: MUSD-454 add quick convert event tracking (#27305)
Matt561 Mar 12, 2026
1ea19b6
chore: bump core dependencies (#26849)
hmalik88 Mar 12, 2026
4e42bef
feat(card): embed Metal Card checkout flow into onboarding flow (#27420)
Brunonascdev Mar 12, 2026
a29accb
feat: migrate Skeleton (swaps scope) (#27363)
kirillzyusko Mar 12, 2026
581facd
chore(release): Bump main version to 7.71.0 (#27453)
metamaskbot Mar 12, 2026
e0d223c
refactor: Updated perps market details header (#27316)
brianacnguyen Mar 12, 2026
afdab7b
test: Migrate page objects to the new framework (Login) (#27434)
cortisiko Mar 12, 2026
3251d01
test: migrates page objects for MM-Connect along with required functi…
christopherferreira9 Mar 12, 2026
4d0ffbe
feat(predict): add buy with any token flow (#27369)
caieu Mar 13, 2026
69f4c71
feat: modify OTA workflow (#27386)
weitingsun Mar 13, 2026
d6fd3c4
fix(homepage): add dot separator between price and variation for toke…
wachunei Mar 13, 2026
1c25150
Merge origin/main into stable-main-7.71.0
metamaskbot Mar 13, 2026
929d7b0
refactor: migrate OnboardingSuccess settings screens to design system…
tylerc-consensys Mar 16, 2026
122be70
refactor: Updated headers for the remaining of Rewards pages (#27314)
brianacnguyen Mar 16, 2026
3456a82
feat: migrate Skeleton (rewards scope) (#27428)
kirillzyusko Mar 16, 2026
97675c9
refactor: migrate renderBottomContent into independent component (#27…
GeorgeGkas Mar 16, 2026
ec5d4d4
feat: allow sending to token contract as user acknowledges warning. (…
jpuri Mar 16, 2026
045f96c
refactor: remove legacy cancel speed up components and related files …
vinistevam Mar 16, 2026
477da9e
refactor: migrate onboarding screens to design system with Tailwind C…
tylerc-consensys Mar 16, 2026
516973c
fix(25760): prevent Ledger connect image from being cut off on iOS af…
Olivier-BB Mar 16, 2026
d5b137a
ci: add default look back days for post merge validation workflow (#2…
jvbriones Mar 16, 2026
91c89e5
refactor(rewards): simplify claimable reward calculation and update t…
PatrykLucka Mar 16, 2026
b5124ce
refactor(MusdConversionAssetListCta): enhance CTA component with full…
PatrykLucka Mar 16, 2026
c1e2acc
refactor: simplify button styles in AdditionalNetworkItem component (…
PatrykLucka Mar 16, 2026
f57e8e9
test: CV - add `nock` and cleanup Trending CV services mocks (#27412)
Prithpal-Sooriya Mar 16, 2026
319610a
chore(release): sync stable to main for version 7.69.0 (#27467)
metamaskbotv2[bot] Mar 16, 2026
8024253
feat: show skeleton when loading NFT images (#27413)
juanmigdr Mar 16, 2026
2d1ed07
refactor: Reverted selected state for explore tab icon cp-7.69.1 cp-7…
brianacnguyen Mar 16, 2026
df1eeeb
chore: Polish MainActionButton to match designs (#27342)
amandaye0h Mar 16, 2026
3c1ee48
fix: Updated root pages scrollable behavior with safeareaview cp-7.69…
brianacnguyen Mar 16, 2026
e04b592
feat(card): add MMM_CARD origin for Card delegation transactions (#27…
rarquevaux Mar 16, 2026
5beada8
ci: test to try new keystore (#27301)
tommasini Mar 16, 2026
0050742
chore: New Crowdin translations by Github Action cp-7.70.0 (#27390)
metamaskbot Mar 16, 2026
dab238f
chore: Market Insights design review cp-7.70.0 (#27259)
zone-live Mar 16, 2026
81f6bcb
fix: use sentence case for remove-network modal header (#27480)
PatrykLucka Mar 16, 2026
fac3ea2
fix(networks): align network header trash icon color (#27481)
PatrykLucka Mar 16, 2026
3bdf001
feat: MUSD-508 align earn balance rows with parent asset layout and a…
Matt561 Mar 16, 2026
7e1cc53
feat: add risk label to PRs from Smart E2E selection output …
cmd-ob Mar 16, 2026
af384ae
chore: correct token price formatting in wallet token list cp-7.69.1 …
juanmigdr Mar 16, 2026
91f809c
refactor(predict): migrate usePredictPriceHistory to React Query (#26…
Kureev Mar 16, 2026
385cd71
feat: retain expired swaps quote in ui (#27340)
GeorgeGkas Mar 16, 2026
caaa82c
fix(ramp): Correct ramp v2 order detail's crypto amount formatting (#…
imyugioh Mar 16, 2026
62782c9
chore: default RAMP_INTERNAL_BUILD to false (#27507)
weitingsun Mar 17, 2026
4e1ff6b
refactor(analytics): PR A2 split types from MetaMetrics (#26988)
NicolasMassart Mar 17, 2026
5336c7c
feat: add security data section in token details page (#27073)
sahar-fehri Mar 17, 2026
6f6b619
feat: migrate Label (core scope) (#27263)
kirillzyusko Mar 17, 2026
89ebae3
test: disables swap test due to flakiness (#27531)
christopherferreira9 Mar 17, 2026
7430a84
fix: amount formatting in simulation section for approve confirmation…
jpuri Mar 17, 2026
f0cee54
test: fix flaky (#27521)
racitores Mar 17, 2026
7a4ae4e
refactor: update NetworkDetailsView to use KeyboardProvider and impro…
PatrykLucka Mar 17, 2026
d9347f4
fix(network-details): correct RPC URL focus and border styling (#27482)
PatrykLucka Mar 17, 2026
204e222
feat(perps): CDP improvements — recipe actions, agentic commands, fas…
abretonc7s Mar 17, 2026
9104ee1
test: refactor hardcoded testIds into dedicated files (#27380)
christopherferreira9 Mar 17, 2026
21c17e2
fix: Throw if Snaps execution webview is missing (#27528)
FrederikBolding Mar 17, 2026
06619cd
test: handles aborted calls on mockServer (#27537)
christopherferreira9 Mar 17, 2026
34c5ebc
feat: use backend-provided intent `typedData` for signing (#25913)
oscarwroche Mar 17, 2026
76be707
feat: Update setting copy and behavior for smart account dapp request…
jpuri Mar 17, 2026
1de86fb
test: MMQA-1598: move nock API mocking to component-view framework an…
racitores Mar 17, 2026
004f1e3
test: Mmqa 1506 dapp connectivity performance (#27500)
javiergarciavera Mar 17, 2026
66797f6
feat: implement claimable bonus threshold logic for MerklRewards (#27…
PatrykLucka Mar 17, 2026
fd6b85a
feat(ramps): add custom action order handling for external checkout f…
georgeweiler Mar 17, 2026
80fb2dd
test: add websocket infra for account activity (#27490)
pnarayanaswamy Mar 17, 2026
72ed4fd
fix(ci): ensure setup-dependencies runs when skip_version_bump is tru…
tommasini Mar 17, 2026
902f2ad
chore: adds market insights to perps (#27419)
zone-live Mar 17, 2026
8482f6c
fix: fix stop loss banner debounce (#27458)
gambinish Mar 17, 2026
f93a7a7
refactor(ramp): align TokenSelection rows with app token list typogra…
wachunei Mar 17, 2026
ed16e5c
feat(card): add attention badge on Card button (#27425)
Brunonascdev Mar 17, 2026
31f5c1d
fix(card): Refactors Card onboarding to use the useRegions hook inste…
Brunonascdev Mar 17, 2026
6aaaebc
chore(ci): migrate nightly build from Bitrise to GitHub Actions with …
tommasini Mar 17, 2026
2e4645a
feat: MUSD-518: Add segment event that tracks when the claim CTA is s…
shane-t Mar 17, 2026
739788f
chore: add ramp env variables to builds.yml and ota envs (#27553)
weitingsun Mar 17, 2026
ed27aa0
fix(ramps): check for providers before checking array length (#27566)
georgeweiler Mar 17, 2026
7329b92
test: improve coverage for onboarding JS components (#27508)
tylerc-consensys Mar 18, 2026
bb5bfa8
chore(deps): bump @metamask/profile-metrics-controller to 3.1.0 (#27486)
NicolasMassart Mar 18, 2026
9f534c4
feat: migrate OptinMetrics to new design system (#27529)
grvgoel81 Mar 18, 2026
76a819d
chore: add flag to disable STX for MMPay transactions (#26997)
jpuri Mar 18, 2026
39c509d
fix: remove dead error branch in handlePostSocialLogin (#27578)
grvgoel81 Mar 18, 2026
6556ecd
feat: restore wallet tailwind migration (#27575)
grvgoel81 Mar 18, 2026
3bf82cf
feat: support relay execute in metamask pay (#27430)
matthewwalsh0 Mar 18, 2026
5a1a3b9
test: Add Component View Tests for Send Flow (#26094)
davibroc Mar 18, 2026
ed0638c
fix(ci): namespace node_modules artifact names by build_name to preve…
tommasini Mar 18, 2026
1470836
fix: correct Spanish translation for obtaining mUSD in es.json cp-7.7…
PatrykLucka Mar 18, 2026
0dde4d0
chore: remove deprecated payment request (#27519)
juanmigdr Mar 18, 2026
feb4268
fix(agentic): store password in SecureKeychain for Android auto-unloc…
abretonc7s Mar 18, 2026
3e74af4
fix: improve hardware wallet icon colors and copy (#27597)
mathieuartu Mar 18, 2026
1bf5d78
fix(perps): fix stale data and missing price change after reconnectio…
abretonc7s Mar 18, 2026
a300f0a
chore: add press opacity feedback to NFT grid item (#27488)
juanmigdr Mar 18, 2026
8158b8e
fix: nfts not showing when non-evm is chosen cp-7.70.0 (#27514)
juanmigdr Mar 18, 2026
b23e56d
test: updates tests docs (#27551)
christopherferreira9 Mar 18, 2026
db4c00d
chore(metro): make resetCache conditional via METRO_RESET_CACHE env v…
abretonc7s Mar 18, 2026
cf02cad
fix(perps): abstract breadcrumb calls and remove external dependencie…
abretonc7s Mar 18, 2026
0d326cb
feat: Default predict withdraw token from last used selection or from…
dan437 Mar 18, 2026
36e01b9
test: delete onramp-limits.failing e2e test (already covered) [MMQA-1…
chrisleewilcox Mar 18, 2026
f55954e
chore: bump bridge controllers (#27607)
bfullam Mar 18, 2026
245dd6f
feat: rwds 1069 display campaigns in mobile app (#27556)
sophieqgu Mar 18, 2026
d350b8d
feat(tron): add claim button for unstaked TRX withdrawal (#27076)
ulissesferreira Mar 18, 2026
7666d6a
fix: fix padding in security screen header (#27621)
sahar-fehri Mar 18, 2026
0d26017
fix: skip handle oauth-redirect deeplink [TO-592] (#27511)
ieow Mar 18, 2026
1db9700
chore(bridge): add bridge controller to CODEOWNERS for swaps team (#2…
tommasini Mar 18, 2026
d876391
ci: adapt automated tests metrics logic (#27552)
jvbriones Mar 18, 2026
e8e693d
fix: market insights animation bug cp-7.70.0 (#27617)
joaosantos15 Mar 18, 2026
964f7b6
chore: Update `@metamask/eslint-config-typescript` to v13 (#26125)
Gudahtt Mar 18, 2026
9528e1b
fix(homepage): hide Predictions section on API connection errors cp-7…
matallui Mar 18, 2026
ccd83bc
feat(ramps): redirect buy deeplinks to unified V2 flow when enabled -…
wachunei Mar 18, 2026
c8405fc
feat(ramp): HeaderCompactStandard and DS Text/Button in buy modals (#…
wachunei Mar 18, 2026
f41c069
chore: remove stale CentraNo1 font references from QA and Flask plist…
georgewrmarshall Mar 18, 2026
285da87
ci: add expo dev build GitHub Actions workflow (#27639)
tommasini Mar 18, 2026
8990394
feat(rewards): add campaign opt-in flow with details, mechanics, and …
VGR-GIT Mar 18, 2026
0d6ecb7
chore: Use AWS secrets for Test flight workflow (#27585)
Cal-L Mar 18, 2026
1fe77d2
test: add AI generated RC manual testing plan (#27492)
sleepytanya Mar 18, 2026
432fbf5
feat: improve hardware wallet connection ui (#27649)
mathieuartu Mar 18, 2026
e7719ba
chore: cp-7.70.0 patch assets-controllers to fix non-EVM chain pollin…
salimtb Mar 18, 2026
ccc1f2d
ci: grant contents write permission to expo dev build workflow (#27653)
tommasini Mar 18, 2026
27cc72a
fix: fixed TokenList crash when changing networks (#27655)
Matt561 Mar 18, 2026
d2ccb55
fix: add user onboarded version [TO-597] (#27573)
ieow Mar 19, 2026
a8ca884
fix: adjust spacing in Homepage component (#27637)
PatrykLucka Mar 19, 2026
ab3db47
fix: resolve onboarding button text contrast in dark mode (#27550)
georgewrmarshall Mar 19, 2026
7176f71
feat: render rich text from contentful (#27658)
sophieqgu Mar 19, 2026
e8d5375
fix: test multiple ios execution (#27635)
racitores Mar 19, 2026
43e2312
feat(perps): add missing analytics properties and fix source propagat…
michalconsensys Mar 19, 2026
0a62384
refactor(AccountBackupStep1): migrate to design system components (#2…
tylerc-consensys Mar 19, 2026
543e138
feat: migrate WalletCreationError screens to design system (#27613)
grvgoel81 Mar 19, 2026
34182c0
fix(ci): assign unique build versions for nightly exp and rc builds (…
tommasini Mar 19, 2026
6dc66fb
refactor(ManualBackupStep2): migrate to design system components (#27…
tylerc-consensys Mar 19, 2026
d015f34
test: removes llamarpc.com as an allowed rpc url (#27595)
christopherferreira9 Mar 19, 2026
ffe9e50
refactor: migrate Login to design system components and Tailwind CSS …
smgv Mar 19, 2026
3767354
feat: authenticate sentinel and transaction api transaction submissio…
klejeune Mar 19, 2026
f7a914b
feat: migrate Skeleton component (perps scope) (#27366)
kirillzyusko Mar 19, 2026
6cbb169
feat: migrate Button (acc-eng scope) (#27549)
kirillzyusko Mar 19, 2026
290655d
feat: migrate Skeleton component (predict scope) (#27370)
kirillzyusko Mar 19, 2026
2c92ecc
fix(snaps): Improve WebView loading detection (#27626)
FrederikBolding Mar 19, 2026
a9111b3
feat(ramp): Converts payment methods and quotes to use react-query fo…
imyugioh Mar 19, 2026
e0486ca
fix: update MegaETH explorer display name to Megaeth Explorer (#27592)
jeremytsng Mar 19, 2026
9f52a9c
fix(perps): resolve blank activity tabs from perps home (#27509)
geositta Mar 19, 2026
36b4602
feat: add metrics property mm_pay_time_to_complete_s (#27476)
jpuri Mar 19, 2026
2ba87de
fix(network-details): require network name in NetworkDetails form (#2…
PatrykLucka Mar 19, 2026
678abd6
fix(accounts-menu): remove network management feature flag gate (#27591)
PatrykLucka Mar 19, 2026
84d4ae9
feat: extend smart E2E selection to release branch PRs and skip draft…
cmd-ob Mar 19, 2026
62cbdf5
chore: update controller usage for breaking changes from core#8183 (#…
cryptodev-2s Mar 19, 2026
a3ec12c
feat(card): Card Authentication migration from CardSDK to CardContro…
Brunonascdev Mar 19, 2026
25ced94
test(e2e): MMQA-1614: declarative MetaMetrics assertions via withFixt…
racitores Mar 19, 2026
3735f04
feat: migrate Button component (rewards scope) (#27623)
kirillzyusko Mar 19, 2026
ea55f69
refactor: normalize networkClientId handling in useGasFeeEstimates ho…
PatrykLucka Mar 19, 2026
e185571
feat: fix incorrect styling of claimable bonus font weight and toolti…
Matt561 Mar 19, 2026
623cfc0
fix: make SDKv1 and WC origin handling better (#27230)
jiexi Mar 19, 2026
1a588d5
feat(card): add selectIsUserInSupportedCardCountry (#27695)
Brunonascdev Mar 19, 2026
35fb472
feat: MUSD-455 bring back claim section on asset details screen (#27567)
Matt561 Mar 19, 2026
5d8659e
test: update Browserstack config in unified framework (#27659)
cortisiko Mar 19, 2026
1e425e6
fix: update test descriptions to use ApprovalController new method na…
cryptodev-2s Mar 19, 2026
bb507cc
feat(perps): add deferEligibilityCheck option to PerpsController (#27…
abretonc7s Mar 19, 2026
eb832ce
chore: bump `@metamask/smart-transactions-controller` to ^23.0.0 (#27…
cryptodev-2s Mar 19, 2026
5a86bf1
ci: make TestFlight external distribution configurable (#27683)
tommasini Mar 19, 2026
43130d6
fix(perps): BRENTOIL shows up in the 'explore crypto' section (#27699)
abretonc7s Mar 19, 2026
3a853ff
feat: MUSD-531 updated mUSD aggregated balance row to redirect to cas…
Matt561 Mar 19, 2026
b68e892
feat: migrate Button component (notifications scope) (#27632)
kirillzyusko Mar 19, 2026
2737b7b
feat: migrate Button component (assets scope) (#27630)
kirillzyusko Mar 19, 2026
8287109
test: Fixed Swap and Bridge tests to run with SSE enabled (#27644)
davibroc Mar 19, 2026
b38ce3b
feat: compliance infrastructure (#26436)
aganglada Mar 19, 2026
7c27827
[skip ci] Bump version number to 4105
metamaskbot Mar 19, 2026
d620dc5
cherry-pick of #27690: feat: Add A/B test for bridge token selector b…
bfullam Mar 20, 2026
058316b
[skip ci] Bump version number to 4116
metamaskbot Mar 20, 2026
979ebf4
chore(runway): cherry-pick chore: Exempt `metamaskbotv2` from CLA che…
runway-github[bot] Mar 23, 2026
b29c766
[skip ci] Bump version number to 4144
metamaskbot Mar 23, 2026
4246be9
chore(runway): cherry-pick refactor: simplify rampsUnifiedBuyV2 featu…
runway-github[bot] Mar 23, 2026
3ce6160
[skip ci] Bump version number to 4146
metamaskbot Mar 23, 2026
5834a30
chore(runway): cherry-pick fix(ramps): Preserve user-entered amount d…
runway-github[bot] Mar 23, 2026
445b430
[skip ci] Bump version number to 4147
metamaskbot Mar 23, 2026
cc3dfdc
chore(runway): cherry-pick fix(ramp): fixes order details bug cp-7.71…
runway-github[bot] Mar 23, 2026
38b2cc9
[skip ci] Bump version number to 4148
metamaskbot Mar 23, 2026
63cee1a
chore: resolve merge conflicts for stable sync into release/7.71.0
chloeYue Mar 23, 2026
ddf4721
chore(runway): cherry-pick fix: start Ramps V2 init when remote featu…
runway-github[bot] Mar 23, 2026
b158563
[skip ci] Bump version number to 4149
metamaskbot Mar 23, 2026
0cc5d5e
chore(runway): cherry-pick fix(ramps): fixes 0 ETH ramps issue when o…
runway-github[bot] Mar 23, 2026
9035d5c
[skip ci] Bump version number to 4150
metamaskbot Mar 23, 2026
b356513
chore: Stable sync release 7.71.0 (#27813)
chloeYue Mar 23, 2026
8d1b7c0
[skip ci] Bump version number to 4151
metamaskbot Mar 23, 2026
c6a9f87
chore(runway): cherry-pick chore(deps): ramps-controller preview for …
runway-github[bot] Mar 23, 2026
b7b8475
[skip ci] Bump version number to 4155
metamaskbot Mar 23, 2026
5ee4f82
chore(runway): cherry-pick chore: adds market insights metric to Perp…
runway-github[bot] Mar 24, 2026
27fa10a
chore(runway): cherry-pick fix(ramps): improve external-browser callb…
runway-github[bot] Mar 24, 2026
aa8a788
[skip ci] Bump version number to 4165
metamaskbot Mar 24, 2026
8b303c4
chore(runway): cherry-pick fix: support webcredentials cp-7.71.0 (#27…
runway-github[bot] Mar 24, 2026
b4f3655
[skip ci] Bump version number to 4168
metamaskbot Mar 24, 2026
6db5885
chore(runway): cherry-pick fix: add metrics opt In event cp-7.71.0 (#…
runway-github[bot] Mar 24, 2026
6ebe482
[skip ci] Bump version number to 4171
metamaskbot Mar 24, 2026
8f743b4
chore(runway): cherry-pick fix(ramps): filter activity tab's transfer…
runway-github[bot] Mar 24, 2026
94e6bcb
[skip ci] Bump version number to 4172
metamaskbot Mar 24, 2026
77eca9c
chore(runway): cherry-pick feat: legacy-ios-feature-flag cp-7.71.0 (#…
runway-github[bot] Mar 24, 2026
b22241e
[skip ci] Bump version number to 4173
metamaskbot Mar 24, 2026
3bfa916
chore(runway): cherry-pick fix(perps): validate TP/SL prices, clear s…
runway-github[bot] Mar 25, 2026
39889c8
[skip ci] Bump version number to 4179
metamaskbot Mar 25, 2026
0e4683f
chore(runway): cherry-pick fix: disable Branch test instance and debu…
runway-github[bot] Mar 25, 2026
6c47666
[skip ci] Bump version number to 4181
metamaskbot Mar 25, 2026
74b9399
chore(runway): cherry-pick fix: hardware wallet eip 7702 issue () (#2…
runway-github[bot] Mar 25, 2026
9f24f30
[skip ci] Bump version number to 4182
metamaskbot Mar 25, 2026
901b9ae
chore(runway): cherry-pick fix(perps): fix HIP-3 asset ID lookup fail…
runway-github[bot] Mar 25, 2026
56b2332
[skip ci] Bump version number to 4183
metamaskbot Mar 25, 2026
57b7cfa
chore: Stable sync release 7.71.0 (7.70.1) (#27915)
chloeYue Mar 25, 2026
6599c4a
[skip ci] Bump version number to 4184
metamaskbot Mar 25, 2026
4876bad
chore(runway): cherry-pick chore: New Crowdin translations by Github …
runway-github[bot] Mar 25, 2026
759fd72
[skip ci] Bump version number to 4186
metamaskbot Mar 25, 2026
16da3b1
chore(runway): cherry-pick feat(earn): gate Tron unstaked claim butto…
runway-github[bot] Mar 26, 2026
9c40658
[skip ci] Bump version number to 4191
metamaskbot Mar 26, 2026
6ae9023
chore(runway): cherry-pick feat: show legacy ios login warning prompt…
runway-github[bot] Mar 26, 2026
7ebe54c
[skip ci] Bump version number to 4192
metamaskbot Mar 26, 2026
32d70a8
chore(runway): cherry-pick fix: hides perps buttons in ai insights wh…
runway-github[bot] Mar 26, 2026
0074970
[skip ci] Bump version number to 4193
metamaskbot Mar 26, 2026
42968c3
[skip ci] Bump version number to 4199
metamaskbot Mar 26, 2026
ad9aa0f
release: release-changelog/7.71.0 (#27710)
metamaskbot Mar 27, 2026
0ceeef0
[skip ci] Bump version number to 4208
metamaskbot Mar 27, 2026
424324a
chore(release): merge stable into release/7.71.0; resolve CHANGELOG (…
chloeYue Mar 27, 2026
a3233d2
chore(release): merge stable into release/7.71.0; resolve CHANGELOG (…
chloeYue Mar 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .agents/skills/component-view-test/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ tests/component-view/
├── mocks.ts ← Engine + native mocks (import this first, always)
├── render.tsx ← renderComponentViewScreen, renderScreenWithRoutes
├── stateFixture.ts ← StateFixtureBuilder (createStateFixture)
├── platform.ts ← describeForPlatforms, itForPlatforms (run per iOS/Android)
├── api-mocking/ ← HTTP API mocks (nock) — extensible, one file per feature
├── presets/ ← initialState<Feature>() builders — one file per feature area
└── renderers/ ← render<Feature>View() functions — one file per feature area
```
Expand Down
124 changes: 42 additions & 82 deletions .agents/skills/component-view-test/references/navigation-mocking.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,102 +134,62 @@ Route names live in `app/constants/navigation/Routes.ts`.

## External Service / API Mocking

Some views call external services **directly** (not through Engine controllers) — e.g. a `getTrendingTokens()` function imported from a package, or a `fetch()` call to an external API. These cannot be driven through Redux state overrides.
Some views call **external HTTP APIs** (e.g. `fetch()` to a REST endpoint). Those requests cannot be driven through Redux state. The framework provides an **api-mocking** layer using [nock](https://github.com/nock/nock) so tests intercept HTTP at the network level **without** using `jest.mock` on service modules (which would violate the “only Engine and allowed native mocks” rule).

### Current pattern — jest.mock on the service module
### Preferred pattern — nock (api-mocking folder)

When a view calls an external service function directly, mock the module in a dedicated file under `tests/component-view/mocks/` and expose setup/clear helpers:
All HTTP API mocks for component view tests live under `tests/component-view/api-mocking/`. Each feature has one file (e.g. `trending.ts`) that exports:

```typescript
// tests/component-view/mocks/myFeatureApiMocks.ts
import { getMyFeatureData } from '@metamask/some-package';

export const getMyFeatureDataMock = getMyFeatureData as jest.Mock;
- Mock response data (e.g. `mockTrendingTokensData`)
- A **setup** function (e.g. `setupTrendingApiFetchMock(responseData?, customReply?)`) that uses nock to intercept the endpoint
- A **clear** function (e.g. `clearTrendingApiMocks()`) to call in `afterEach`

export const mockFeatureData = [
{ id: 'item-1', name: 'Token A', price: '100.00', change24h: 5.2 },
{ id: 'item-2', name: 'Token B', price: '200.00', change24h: -1.8 },
];
Shared nock lifecycle helpers (`clearAllNockMocks`, `disableNetConnect`, `teardownNock`) are in `api-mocking/nockHelpers.ts`. To **add a new API mock** for another view, add a file `api-mocking/<feature>.ts` following the pattern in `api-mocking/trending.ts` (mock data, `setupXxxApiMock`, `clearXxxApiMocks` using `nockHelpers`), and call setup/clear in the view test’s `beforeEach`/`afterEach`.

export const setupMyFeatureApiMock = (data = mockFeatureData) => {
getMyFeatureDataMock.mockImplementation(async () => data);
};

export const clearMyFeatureApiMocks = () => {
jest.clearAllMocks();
};
```

In the test file, declare the `jest.mock` at module scope and use `beforeEach`/`afterEach` for lifecycle:
**Example (trending):**

```typescript
// NOTE: antipattern — only Engine and native modules should be mocked in view tests.
// This is a temporary workaround for service functions called directly from components,
// not through Engine. Track removal in the linked issue.
// eslint-disable-next-line no-restricted-syntax
jest.mock('@metamask/some-package', () => {
const actual = jest.requireActual('@metamask/some-package');
return { ...actual, getMyFeatureData: jest.fn().mockResolvedValue([]) };
});

import {
setupMyFeatureApiMock,
clearMyFeatureApiMocks,
mockFeatureData,
getMyFeatureDataMock,
} from '../../../../tests/component-view/mocks/myFeatureApiMocks';

describe('MyFeatureView', () => {
beforeEach(() => {
setupMyFeatureApiMock(mockFeatureData);
});

afterEach(() => {
clearMyFeatureApiMocks();
});

it('shows token list after data loads from the external service', async () => {
const { findByText } = renderMyFeatureWithRoutes();
setupTrendingApiFetchMock,
clearTrendingApiMocks,
mockTrendingTokensData,
mockBnbChainToken,
} from '../../../../tests/component-view/api-mocking/trending';

beforeEach(() => {
setupTrendingApiFetchMock(mockTrendingTokensData);
});
afterEach(() => {
clearTrendingApiMocks();
});

expect(await findByText('Token A')).toBeOnTheScreen();
it('user sees trending tokens section with mocked data', async () => {
const { findByText, queryByTestId } = renderTrendingViewWithRoutes();
await waitFor(async () => {
expect(await findByText('Ethereum')).toBeOnTheScreen();
});
// assert rows with assertTrendingTokenRowsVisibility(...)
});

it('shows only filtered results when a specific param is passed', async () => {
getMyFeatureDataMock.mockImplementation(async (params) => {
if (params?.chainId === 'eip155:56') return [mockBnbData];
return mockFeatureData;
});

const { findByText } = renderMyFeatureWithRoutes();
// ... interact to trigger the filter, then assert
it('displays only BNB tokens when BNB Chain network filter is selected', async () => {
setupTrendingApiFetchMock(mockTrendingTokensData, (uri) => {
const url = new URL(uri, 'https://token.api.cx.metamask.io');
const chainIdsParam = url.searchParams.get('chainIds') ?? '';
const chainIds = chainIdsParam.split(',').map((s) => s.trim());
if (chainIds.length === 1 && chainIds[0] === 'eip155:56') {
return mockBnbChainToken;
}
return mockTrendingTokensData;
});
const { getByTestId, findByText, queryByTestId } =
renderTrendingViewWithRoutes();
// ... navigate to full view, open network filter, select BNB Chain
// assert visible: [BNB], missing: [ETH, BTC, UNI]
});
```

> ⚠️ **This is a known antipattern.** The golden rule is that only Engine and allowed native modules should be mocked in `*.view.test.*` files. Mocking a service module directly bypasses the ESLint guard (note the `eslint-disable` comment). Always link to a tracking issue and plan to migrate to a proper solution.

### Future pattern — Mock Service Worker (MSW)

> 📌 **Placeholder — no example exists yet in this codebase.**
### Fallback — jest.mock on the service module (antipattern)

For views that call HTTP endpoints directly (via `fetch`), the intended approach is [Mock Service Worker (msw)](https://mswjs.io/), which intercepts requests at the network level without needing `jest.mock`. This keeps tests closer to real behavior and avoids the module-mock antipattern.
When a view calls an external **function** (not `fetch`) from a package and that function cannot be replaced by nock (e.g. no HTTP), you may mock the module in a file under `tests/component-view/mocks/` and use setup/clear helpers. This requires an `eslint-disable` and is a **known antipattern**; prefer moving the integration to an HTTP API and using api-mocking, or drive data through Engine/Redux when possible.

When the first MSW-based view test is written, document the setup here:

```typescript
// TODO: Add MSW setup example once the first test using it is merged.
// Expected shape:
//
// import { setupServer } from 'msw/node';
// import { http, HttpResponse } from 'msw';
//
// const server = setupServer(
// http.get('https://api.example.com/tokens', () =>
// HttpResponse.json(mockTokensData),
// ),
// );
//
// beforeAll(() => server.listen());
// afterEach(() => server.resetHandlers());
// afterAll(() => server.close());
```
> ⚠️ Only Engine and allowed native modules should be mocked in `*.view.test.*` files. Mocking a service module directly bypasses the ESLint guard. Always link to a tracking issue and plan to migrate to nock (api-mocking) or Engine/Redux.
1 change: 1 addition & 0 deletions .agents/skills/component-view-test/references/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ yarn eslint <path/to/test.tsx>
| Engine + native mocks | `tests/component-view/mocks.ts` |
| render, renderScreenWithRoutes | `tests/component-view/render.tsx` |
| StateFixtureBuilder | `tests/component-view/stateFixture.ts` |
| HTTP API mocks (nock) | `tests/component-view/api-mocking/` (per-feature) |
| Feature renderers (per view) | `tests/component-view/renderers/` (e.g. bridge, wallet) |
| Feature presets (per view) | `tests/component-view/presets/` (e.g. bridge, wallet) |
| DeepPartial type | `app/util/test/renderWithProvider` |
Expand Down
33 changes: 33 additions & 0 deletions .agents/skills/component-view-test/references/writing-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Before writing any test, read:
- Any existing `*.view.test.tsx` for the same component
- The relevant preset(s) in `tests/component-view/presets/`
- The relevant renderer(s) in `tests/component-view/renderers/`
- If the view calls an external HTTP API: `tests/component-view/api-mocking/` and any existing `api-mocking/<feature>.ts` for that API (see navigation-mocking.md, External Service / API Mocking)

---

Expand Down Expand Up @@ -194,6 +195,38 @@ const defaultBridgeWithTokens = (overrides?: Record<string, unknown>) => {

Then each test only specifies its delta from this baseline.

### describe / it and platform (iOS + Android)

Import from `tests/component-view/platform`. All helpers accept an optional **filter** (3rd arg): `'ios'` | `'android'` | `['ios','android']` | `{ only: 'ios' }` | `{ skip: ['android'] }`. Env: `TEST_OS=ios` or `TEST_OS=android` to run only one OS.

| Helper | Use |
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `describeForPlatforms(name, define, filter?)` | One describe per OS. Inside, `define({ os })`; use `it()` or `itForPlatforms()` — each runs once per that OS. |
| `itForPlatforms(name, (ctx) => {}, filter?)` | One `it` per OS. Callback receives `{ os }`. |
| `itOnlyForPlatforms(name, fn, filter?)` | Same as `itForPlatforms` but registers `it.only`. |
| `itEach(table)(name, (row) => {}, filter?)` | One `it` per table row × per OS. Use `$key` in name to interpolate row fields. |
| `describeEach(table)(name, (row) => { it('...', () => {}); }, filter?)` | One describe per row × per OS. Use `$key` in name. |
| `getTargetPlatforms(filter?)` | Returns `['ios','android']` (or filtered list) for custom loops. |

Example — `itEach` (each case runs on iOS and Android):

```typescript
import { itEach } from '../../../../../../tests/component-view/platform';

const cases = [
{ name: 'renders empty', amount: '0' },
{ name: 'displays fiat', amount: '1' },
];
itEach(cases)('$name', ({ amount }) => {
const { findByDisplayValue } = renderDefault({
bridge: { sourceAmount: amount },
});
expect(findByDisplayValue(amount)).toBeOnTheScreen();
});
```

Jest modifiers (`it.only`, `it.skip`, `describe.only`, `describe.skip`) work as usual inside these blocks.

### Minimal template

```typescript
Expand Down
8 changes: 7 additions & 1 deletion .agents/skills/e2e-test/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ name: e2e-test
description:
Add and fix Detox E2E tests (smoke and regression) for MetaMask Mobile using
withFixtures, Page Objects, and tests/framework. Use when creating a new spec,
fixing a failing E2E test, or adding page objects and selectors.
fixing a failing E2E test, adding page objects and selectors, or adding
MetaMetrics analytics expectations (analyticsExpectations).
---

# E2E Test Builder — Skill
Expand Down Expand Up @@ -44,6 +45,10 @@ Task → What do you need?
│ → Open references/mocking.md (testSpecificMock, setupRemoteFeatureFlagsMock, setupMockRequest)
│ → When writing the spec: open references/writing-tests.md
├─ MetaMetrics / Segment analytics assertions (`analyticsExpectations` on `withFixtures`)
│ → Open [tests/docs/analytics-e2e.md](../../../tests/docs/analytics-e2e.md) (config shape, teardown order, presets under `tests/helpers/analytics/expectations/`, `runAnalyticsExpectations`)
│ → When wiring a spec: still follow references/writing-tests.md for `withFixtures` usage
└─ Run tests, debug failures, or self-review
→ Open references/running-tests.md (build check, detox commands, common failures, retry patterns)
```
Expand Down Expand Up @@ -89,4 +94,5 @@ Documentation is split by **action**. Open only the reference that matches what
| **Writing or updating a spec** | [references/writing-tests.md](references/writing-tests.md) | New spec file, spec structure, FixtureBuilder patterns, smoke/regression templates. |
| **Page Objects and selectors** | [references/page-objects.md](references/page-objects.md) | Create or update POM classes, selector/testId conventions, Matchers/Gestures/Assertions API. |
| **API and feature flag mocking** | [references/mocking.md](references/mocking.md) | testSpecificMock, setupRemoteFeatureFlagsMock, setupMockRequest, shared mock files. |
| **MetaMetrics / analytics expectations** | [tests/docs/analytics-e2e.md](../../../tests/docs/analytics-e2e.md) | `analyticsExpectations` on `withFixtures`, declarative checks, presets in `tests/helpers/analytics/expectations/`. |
| **Running tests, debugging, fixing failures** | [references/running-tests.md](references/running-tests.md) | Build check, detox run commands, lint/tsc, common failures table, retry patterns, iteration loop. |
2 changes: 2 additions & 0 deletions .cursor/rules/deeplink-handler-guidelines.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ This guide walks you through adding new deeplink handlers to MetaMask Mobile. Fo

## Quick Reference

The **`deposit` deeplink** (`metamask://deposit`, `/deposit`) is **deprecated** and not handled; do not add handlers under Ramp Deposit `deeplink/` for it.

| File | Purpose |
|------|---------|
| `app/constants/deeplinks.ts` | Define action constants |
Expand Down
10 changes: 7 additions & 3 deletions .depcheckrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ ignores:
- '@metamask/perps-controller'
# Used in scripts/repack for CI optimization
- '@expo/repack-app'

# ESLint plugins, resolvers, parsers, configuration, etc.
- 'eslint-config-prettier'
- 'eslint-import-resolver-typescript'
- 'eslint-plugin-prettier'
- 'eslint-plugin-react-native'

# Note: Everything below this line should be removed after investigation
# TODO: Investigate each dependency to see whether it's used

Expand All @@ -63,9 +70,6 @@ ignores:
- 'babel-core'
- 'babel-loader'
- 'chromedriver'
- 'eslint-config-prettier'
- 'eslint-plugin-prettier'
- 'eslint-plugin-react-native'
- 'execa'
- 'jetifier'
- 'metro-react-native-babel-preset'
Expand Down
Loading
Loading