Skip to content

Commit d2c0525

Browse files
Merge branch 'main' into run-system-tests
2 parents f1d7841 + 9432aa0 commit d2c0525

1,354 files changed

Lines changed: 77927 additions & 61214 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/e2e-test/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Do not read the full reference files until the decision tree or workflow sends y
6666
5. **Never use `TestHelpers.delay()`** — use `Assertions.*` which has auto-retry
6767
6. **Use `FixtureBuilder` for state** — do not set state through UI interactions
6868
7. **Selectors live in `*.testIds.ts`** (co-located) or `tests/selectors/` (legacy)
69-
8. **Tag correctly** — Use the tag that matches your feature and test type. Options include `SmokeE2E`, `SmokeTrade`, `SmokePredictions`, `SmokePerps`, `SmokeConfirmations`, `RegressionTrade`, `RegressionWallet`, etc. Check **`tests/tags.js`** for the full list and descriptions, and **existing specs in the same feature folder** to see which tag they use.
69+
8. **Tag correctly** — Use the tag that matches your feature and test type. Options include `SmokeE2E`, `SmokeSwap`, `SmokeStake`, `SmokeMoney`, `SmokePredictions`, `SmokePerps`, `SmokeConfirmations`, `RegressionTrade`, `RegressionWallet`, etc. Check **`tests/tags.js`** for the full list and descriptions, and **existing specs in the same feature folder** to see which tag they use.
7070
9. **Descriptive test names** — no 'should' prefix (e.g., `'opens market details'`)
7171
10. **Fix lint/tsc before running** — never run with known errors
7272

.agents/skills/e2e-test/references/writing-tests.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
## Spec File Location
44

5-
| Test Type | Directory | Tag |
6-
| ---------- | ------------------------------------------- | -------------------------------------------------------------------------------------- |
7-
| Smoke | `tests/smoke/<feature>/<name>.spec.ts` | `SmokeE2E`, `SmokeTrade`, `SmokePredictions`, `SmokePerps`, `SmokeConfirmations`, etc. |
8-
| Regression | `tests/regression/<feature>/<name>.spec.ts` | `RegressionTrade`, `RegressionWallet`, etc. |
5+
| Test Type | Directory | Tag |
6+
| ---------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
7+
| Smoke | `tests/smoke/<feature>/<name>.spec.ts` | `SmokeE2E`, `SmokeSwap`, `SmokeStake`, `SmokeMoney`, `SmokePredictions`, `SmokePerps`, `SmokeConfirmations`, etc. |
8+
| Regression | `tests/regression/<feature>/<name>.spec.ts` | `RegressionTrade`, `RegressionWallet`, etc. |
99

10-
Import tags from `tests/tags.ts`. Check **`tests/tags.js`** for the full list and descriptions. Use the same tag as **existing specs in that feature folder** (e.g. `tests/smoke/predict/` uses `SmokeTrade`).
10+
Import tags from `tests/tags.ts`. Check **`tests/tags.js`** for the full list and descriptions. Use the same tag as **existing specs in that feature folder** (e.g. `tests/smoke/swap/` uses `SmokeSwap`, `tests/smoke/stake/` uses `SmokeStake`, `tests/smoke/card/` and `tests/smoke/ramps/` use `SmokeMoney`).
1111

1212
## Minimal Smoke Spec
1313

.eslintrc.js

Lines changed: 248 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,136 @@
11
/* eslint-disable import-x/no-commonjs */
2+
3+
/**
4+
* Files still allowed to import deprecated `app/util/number/index.js` during
5+
* the BN.js → BigInt migration. Kept in one array so the default import-fence
6+
* override can exclude them while the follow-up override below re-applies only
7+
* the expo-haptics / perps restrictions (see comments on those overrides).
8+
*/
9+
const utilNumberImportBurndownFiles = [
10+
'app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.tsx',
11+
'app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx',
12+
'app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.tsx',
13+
'app/component-library/components-temp/Price/AggregatedPercentage/utils.ts',
14+
'app/components/UI/AccountInfoCard/index.js',
15+
'app/components/UI/AssetOverview/Price/Price.advanced.tsx',
16+
'app/components/UI/AssetOverview/Price/Price.legacy.tsx',
17+
'app/components/UI/AssetOverview/utils/marketDetails.ts',
18+
'app/components/UI/Bridge/components/QuoteSelectorView/QuoteRow.tsx',
19+
'app/components/UI/Bridge/components/QuoteSelectorView/index.tsx',
20+
'app/components/UI/Bridge/hooks/useBridgeQuoteData/index.ts',
21+
'app/components/UI/Bridge/hooks/useFormattedBalanceWithThreshold/index.ts',
22+
'app/components/UI/Bridge/hooks/useHasSufficientGas/index.ts',
23+
'app/components/UI/Bridge/hooks/useInsufficientBalance/index.ts',
24+
'app/components/UI/Bridge/hooks/useTokenBalanceInUsd/index.ts',
25+
'app/components/UI/Bridge/hooks/useTokensWithBalance/index.ts',
26+
'app/components/UI/Bridge/utils/exchange-rates.ts',
27+
'app/components/UI/Bridge/utils/formatNetworkFee.test.ts',
28+
'app/components/UI/Bridge/utils/formatNetworkFee.ts',
29+
'app/components/UI/Bridge/utils/transaction-history.ts',
30+
'app/components/UI/Card/hooks/useAssetBalances.tsx',
31+
'app/components/UI/Card/hooks/useCardDelegation.test.ts',
32+
'app/components/UI/Card/hooks/useCardDelegation.ts',
33+
'app/components/UI/Card/hooks/useNeedsGasFaucet.ts',
34+
'app/components/UI/Card/sdk/CardSDK.ts',
35+
'app/components/UI/CollectibleOverview/index.js',
36+
'app/components/UI/Earn/Views/EarnInputView/EarnInputView.test.tsx',
37+
'app/components/UI/Earn/Views/EarnLendingDepositConfirmationView/components/Erc20TokenHero/index.tsx',
38+
'app/components/UI/Earn/Views/EarnLendingDepositConfirmationView/index.tsx',
39+
'app/components/UI/Earn/Views/EarnLendingWithdrawalConfirmationView/index.tsx',
40+
'app/components/UI/Earn/Views/EarnWithdrawInputView/EarnWithdrawInputView.tsx',
41+
'app/components/UI/Earn/components/EarnLendingBalance/index.tsx',
42+
'app/components/UI/Earn/components/Earnings/EarningsHistory/EarningsHistory.utils.ts',
43+
'app/components/UI/Earn/components/InputDisplay/InputDisplay.test.tsx',
44+
'app/components/UI/Earn/hooks/useEarnGasFee.ts',
45+
'app/components/UI/Earn/hooks/useEarnInput.ts',
46+
'app/components/UI/Earn/hooks/useEarnings.ts',
47+
'app/components/UI/Earn/hooks/useInput.ts',
48+
'app/components/UI/Earn/hooks/useMultichainInputHandlers.ts',
49+
'app/components/UI/Earn/hooks/useMusdBalance.ts',
50+
'app/components/UI/Earn/hooks/useMusdCtaVisibility.ts',
51+
'app/components/UI/Earn/utils/number.ts',
52+
'app/components/UI/Earn/utils/token/index.ts',
53+
'app/components/UI/Earn/utils/tron.ts',
54+
'app/components/UI/HardwareWallet/AccountDetails/index.tsx',
55+
'app/components/UI/Money/constants/activityStyles.ts',
56+
'app/components/UI/Money/hooks/useMoneyAccountBalance.ts',
57+
'app/components/UI/Money/utils/moneyActivityFiat.ts',
58+
'app/components/UI/MultichainBridgeTransactionListItem/MultichainBridgeTransactionListItem.tsx',
59+
'app/components/UI/Notification/TransactionNotification/index.js',
60+
'app/components/UI/Ramp/Aggregator/Views/BuildQuote/BuildQuote.test.tsx',
61+
'app/components/UI/Ramp/Aggregator/Views/BuildQuote/BuildQuote.tsx',
62+
'app/components/UI/Ramp/Aggregator/Views/OrdersList/OrdersList.tsx',
63+
'app/components/UI/Ramp/Aggregator/Views/SendTransaction/SendTransaction.tsx',
64+
'app/components/UI/Ramp/Aggregator/components/OrderDetails.tsx',
65+
'app/components/UI/Ramp/Aggregator/components/OrderListItem/OrderListItem.tsx',
66+
'app/components/UI/Ramp/Aggregator/components/Quote/Quote.tsx',
67+
'app/components/UI/Ramp/Aggregator/hooks/useBalance.test.ts',
68+
'app/components/UI/Ramp/Aggregator/hooks/useBalance.ts',
69+
'app/components/UI/Ramp/Aggregator/hooks/useERC20GasLimitEstimation.ts',
70+
'app/components/UI/Ramp/Aggregator/hooks/useHandleSuccessfulOrder.ts',
71+
'app/components/UI/Ramp/Aggregator/hooks/useIntentAmount.ts',
72+
'app/components/UI/Ramp/Aggregator/utils/index.ts',
73+
'app/components/UI/Ramp/Deposit/utils/index.ts',
74+
'app/components/UI/Ramp/utils/getOrderAmount.ts',
75+
'app/components/UI/Ramp/utils/v2OrderToast.ts',
76+
'app/components/UI/Stake/components/StakingBalance/StakingBanners/ClaimBanner/ClaimBanner.tsx',
77+
'app/components/UI/Stake/components/StakingConfirmation/TokenValueStack/TokenValueStack.test.tsx',
78+
'app/components/UI/Stake/components/StakingConfirmation/TokenValueStack/TokenValueStack.tsx',
79+
'app/components/UI/Stake/components/StakingConfirmation/YouReceiveCard/YouReceiveCard.test.tsx',
80+
'app/components/UI/Stake/components/StakingConfirmation/YouReceiveCard/YouReceiveCard.tsx',
81+
'app/components/UI/Stake/hooks/useBalance.ts',
82+
'app/components/UI/Tokens/util/deriveBalanceFromAssetMarketDetails.test.ts',
83+
'app/components/UI/Tokens/util/deriveBalanceFromAssetMarketDetails.ts',
84+
'app/components/UI/TransactionElement/utils-gas.js',
85+
'app/components/UI/TransactionElement/utils.js',
86+
'app/components/UI/UrlAutocomplete/Result.tsx',
87+
'app/components/Views/AssetDetails/index.tsx',
88+
'app/components/Views/DetectedTokens/components/Token.tsx',
89+
'app/components/Views/GasEducationCarousel/index.js',
90+
'app/components/Views/NetworksManagement/NetworkDetailsView/hooks/useNetworkValidation.ts',
91+
'app/components/Views/SocialLeaderboard/TraderPositionView/components/QuickBuyBottomSheet/useQuickBuyBottomSheet.ts',
92+
'app/components/Views/SocialLeaderboard/TraderPositionView/components/QuickBuyBottomSheet/useQuickBuyQuotes.ts',
93+
'app/components/Views/SocialLeaderboard/utils/formatters.ts',
94+
'app/components/Views/UnifiedTransactionsView/useUnifiedTxActions.test.ts',
95+
'app/components/Views/confirmations/components/gas/max-base-fee-input/max-base-fee-input.tsx',
96+
'app/components/Views/confirmations/components/gas/priority-fee-input/priority-fee-input.tsx',
97+
'app/components/Views/confirmations/components/info/typed-sign-v3v4/simulation/components/native-value-display/native-value-display.tsx',
98+
'app/components/Views/confirmations/components/info/typed-sign-v3v4/simulation/components/value-display/value-display.tsx',
99+
'app/components/Views/confirmations/components/transactions/custom-amount/custom-amount.tsx',
100+
'app/components/Views/confirmations/context/send-context/utils.ts',
101+
'app/components/Views/confirmations/external/staking/hooks/useStakingDetails.ts',
102+
'app/components/Views/confirmations/hooks/earn/useCustomAmount.tsx',
103+
'app/components/Views/confirmations/hooks/gas/useCancelSpeedupGas/useCancelSpeedupGas.ts',
104+
'app/components/Views/confirmations/hooks/send/useBalance.ts',
105+
'app/components/Views/confirmations/hooks/send/useCurrencyConversions.ts',
106+
'app/components/Views/confirmations/hooks/send/usePercentageAmount.ts',
107+
'app/components/Views/confirmations/hooks/useTokenAmount.ts',
108+
'app/components/Views/confirmations/legacy/components/CustomNonceModal/index.js',
109+
'app/components/Views/confirmations/legacy/components/WatchAssetRequest/index.js',
110+
'app/components/Views/confirmations/utils/send.ts',
111+
'app/components/hooks/useAddressBalance/useAddressBalance.ts',
112+
'app/components/hooks/useGetFormattedTokensPerChain.tsx',
113+
'app/components/hooks/useGetTotalFiatBalanceCrossChains.tsx',
114+
'app/core/Engine/Engine.ts',
115+
'app/core/Engine/controllers/gas-fee-controller/gas-fee-controller-init.test.ts',
116+
'app/core/GasPolling/GasPolling.ts',
117+
'app/core/NotificationManager.js',
118+
'app/selectors/assets/assets-list.ts',
119+
'app/selectors/earnController/earn/index.ts',
120+
'app/selectors/multichain/evm.ts',
121+
// `app/util/**` importers of `./number` or `../number` (resolves to `index.js`);
122+
// same burndown contract as feature files — remove when migrated to
123+
// `../number/bigint` (or `./number/bigint` from `app/util/`).
124+
'app/util/confirm-tx.js',
125+
'app/util/conversions.js',
126+
'app/util/confirmation/gas.ts',
127+
'app/util/confirmation/transactions.ts',
128+
'app/util/custom-gas/index.js',
129+
'app/util/networks/index.js',
130+
'app/util/transactions/index.js',
131+
'app/util/transactions/index.test.ts',
132+
];
133+
2134
module.exports = {
3135
root: true,
4136
parser: '@typescript-eslint/parser',
@@ -42,6 +174,11 @@ module.exports = {
42174
'interface',
43175
],
44176
'@typescript-eslint/no-explicit-any': 'error',
177+
// Surface JSDoc @deprecated annotations at every use-site (warn for now;
178+
// ratchet to 'error' once the BN.js → BigInt migration is complete).
179+
// Pairs with the `import-x/no-restricted-paths` fence on
180+
// `app/util/number/index.js` in the app import-fence override below.
181+
'@typescript-eslint/no-deprecated': 'warn',
45182
// Under discussion
46183
'@typescript-eslint/no-duplicate-enum-values': 'off',
47184
'@typescript-eslint/no-shadow': [
@@ -248,6 +385,33 @@ module.exports = {
248385
],
249386
},
250387
},
388+
{
389+
files: ['**/*.test.{js,ts,tsx,jsx}', '**/*.spec.{js,ts,tsx,jsx}'],
390+
plugins: ['jest'],
391+
rules: {
392+
// Prevent new file-based snapshots. Inline snapshots (toMatchInlineSnapshot)
393+
// are still allowed as they keep assertions co-located with the test.
394+
'jest/no-restricted-matchers': [
395+
'error',
396+
{
397+
toMatchSnapshot:
398+
'Use toMatchInlineSnapshot() or an explicit assertion instead. File-based snapshots are being phased out.',
399+
},
400+
],
401+
},
402+
},
403+
{
404+
// Matches CODEOWNERS `**/snaps/**` and `**/Snaps/**` (@MetaMask/core-platform).
405+
// ESLint cannot read CODEOWNERS.
406+
files: [
407+
'**/snaps/**/*.{test,spec}.{js,ts,tsx,jsx}',
408+
'**/Snaps/**/*.{test,spec}.{js,ts,tsx,jsx}',
409+
],
410+
plugins: ['jest'],
411+
rules: {
412+
'jest/no-restricted-matchers': 'off',
413+
},
414+
},
251415
// ── Perps controller Core-alignment override ──
252416
// Enforces the same ESLint rules that Core's @metamask/eslint-config
253417
// applies to packages/perps-controller so that code written in mobile
@@ -466,18 +630,100 @@ module.exports = {
466630
},
467631
},
468632
{
469-
files: ['app/**/*.{ts,tsx}'],
470-
excludedFiles: ['app/controllers/perps/**/*.{ts,tsx}'],
633+
// Default app import fences (expo-haptics, perps, deprecated util/number/index.js).
634+
// `excludedFiles` applies to the whole override — listing burn-down paths
635+
// here would incorrectly skip expo/perps for those files, so burn-down is
636+
// excluded from *this* block only and picked up by the next override.
637+
files: ['app/**/*.{ts,tsx,js,jsx}'],
638+
excludedFiles: [
639+
// Perps controller is exempt from importing itself.
640+
'app/controllers/perps/**/*.{ts,tsx,js,jsx}',
641+
// Designated expo-haptics wrapper — only this tree may import expo-haptics.
642+
'app/util/haptics/**/*.{ts,tsx,js,jsx}',
643+
// Legacy number utils + parity tests.
644+
'app/util/number/**',
645+
// BN.js → BigInt burn-down: still allowed util/number imports; see next override.
646+
...utilNumberImportBurndownFiles,
647+
],
648+
rules: {
649+
'no-restricted-imports': [
650+
'error',
651+
{
652+
paths: [
653+
{
654+
name: 'expo-haptics',
655+
message:
656+
'Import from app/util/haptics instead of expo-haptics directly.',
657+
},
658+
],
659+
patterns: [
660+
{
661+
group: ['**/controllers/perps', '**/controllers/perps/**'],
662+
message:
663+
'Use @metamask/perps-controller instead of relative imports into app/controllers/perps/.',
664+
},
665+
{
666+
group: ['expo-haptics/*'],
667+
message:
668+
'Import from app/util/haptics instead of expo-haptics directly.',
669+
},
670+
],
671+
},
672+
],
673+
// Fences the deprecated `app/util/number/index.js` module. We use
674+
// `import-x/no-restricted-paths` (not `no-restricted-imports`) because
675+
// it resolves each import to its absolute file, which means a single
676+
// entry catches every spelling that lands on `index.js` — bare
677+
// (`from '../util/number'`), explicit (`'../util/number/index'`),
678+
// and explicit-with-extension. Sibling modules like `bigint`,
679+
// `bignumber`, and `subscriptNotation` resolve to different files
680+
// and are unaffected, so no negation list is needed. Inherits the
681+
// burn-down allowlist from this override's `excludedFiles`; the
682+
// burn-down override below intentionally does not re-declare this
683+
// rule, so allow-listed files remain exempt.
684+
'import-x/no-restricted-paths': [
685+
'error',
686+
{
687+
zones: [
688+
{
689+
target: 'app',
690+
from: 'app/util/number/index.js',
691+
message:
692+
'app/util/number/index.js is deprecated. Import the BigInt-based replacement from app/util/number/bigint instead. See app/util/number/bigint-migration-reference.test.ts for migration patterns.',
693+
},
694+
],
695+
},
696+
],
697+
},
698+
},
699+
{
700+
// Re-apply expo-haptics + perps only for burn-down files. A second
701+
// override is required because ESLint replaces `no-restricted-imports`
702+
// when the same rule is set again — we cannot use one override with only
703+
// `excludedFiles` for util/number without silently dropping other fences.
704+
files: utilNumberImportBurndownFiles,
471705
rules: {
472706
'no-restricted-imports': [
473707
'error',
474708
{
709+
paths: [
710+
{
711+
name: 'expo-haptics',
712+
message:
713+
'Import from app/util/haptics instead of expo-haptics directly.',
714+
},
715+
],
475716
patterns: [
476717
{
477718
group: ['**/controllers/perps', '**/controllers/perps/**'],
478719
message:
479720
'Use @metamask/perps-controller instead of relative imports into app/controllers/perps/.',
480721
},
722+
{
723+
group: ['expo-haptics/*'],
724+
message:
725+
'Import from app/util/haptics instead of expo-haptics directly.',
726+
},
481727
],
482728
},
483729
],

.github/CODEOWNERS

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ app/core/Engine/README.md @MetaMask/mobile-pla
4343
app/core/Engine/types.ts @MetaMask/mobile-platform
4444
app/core/Engine/controllers/remote-feature-flag-controller/ @MetaMask/mobile-platform
4545
app/core/DeeplinkManager @MetaMask/mobile-platform
46+
# Deprecated BN.js helpers. Gated to discourage adding new exports; consumers
47+
# should migrate to app/util/number/bigint. See .eslintrc.js for the import
48+
# fence and bigint-migration-reference.test.ts for migration patterns.
49+
app/util/number/index.js @MetaMask/mobile-platform
4650
scripts/build.sh @MetaMask/mobile-platform
4751
fingerprint.config.js @MetaMask/mobile-platform
4852
builds.yml @MetaMask/mobile-platform
@@ -334,9 +338,10 @@ tests/tools/ @MetaMask/qa
334338
tests/websocket/ @MetaMask/qa
335339

336340
# QA Team - CI
341+
.github/guidelines/E2E_DECISION_TREE.md @MetaMask/qa
337342
.github/actions/smart-e2e-selection/ @MetaMask/qa
338343
.github/workflows/ai-pr-risk-analysis.yml @MetaMask/qa
339-
.github/workflows/needs-e2e-build.yml @MetaMask/qa
344+
.github/workflows/auto-label-not-ready-for-e2e.yml @MetaMask/qa
340345
.github/workflows/run-e2e-workflow.yml @MetaMask/qa
341346
.github/workflows/run-e2e-api-specs.yml @MetaMask/qa
342347
.github/workflows/run-e2e-regression-tests-android.yml @MetaMask/qa

0 commit comments

Comments
 (0)