Skip to content

Comments

chore: replace hardcoded strings with i18n message references in tests#39859

Open
DDDDDanica wants to merge 40 commits intomainfrom
chore/6395-i18n
Open

chore: replace hardcoded strings with i18n message references in tests#39859
DDDDDanica wants to merge 40 commits intomainfrom
chore/6395-i18n

Conversation

@DDDDDanica
Copy link
Contributor

@DDDDDanica DDDDDanica commented Feb 6, 2026

Description

1. i18n Test Robustness
Test files were using hardcoded plaintext strings in assertions (getByText('Cancel'), getByRole('button', { name: 'Confirm' }), etc.) instead of referencing the actual i18n locale messages. This makes tests fragile and harder to maintain when translations change.

2. Unused fireEvent Import Cleanup
Some test files import { fireEvent } from ../../../../../test/jest but can be simplified to import directly from @testing-library/react.

What is the improvement/solution?

i18n Changes (214 files):

  • Added enLocale export to test/lib/i18n-helpers.js for easy importing
  • Replaced direct app/_locales/en/messages.json imports with import { enLocale as messages } from 'test/lib/i18n-helpers'
  • Removed eslint-disable-next-line import/no-restricted-paths comments for locale imports
  • Updated string assertions to use messages.<key>.message pattern
  • Handled parameterized i18n strings with .replace('$1', value) syntax
  • Add fitness fun
Screenshot 2026-02-11 at 15 04 20 ction to quality gate the new added assertions

fireEvent Cleanup:

  • Simplified imports from import { fireEvent } from '../../../../../test/jest' to import { fireEvent } from '@testing-library/react'
  • Removed unused re-export from test/jest/index.js

Open in GitHub Codespaces

Changelog

CHANGELOG entry: null

Related issues

Fixes:

Manual testing steps

  1. Go to this page...

Screenshots/Recordings

Before

After

Pre-merge author checklist

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.

Note

Low Risk
Test-only changes that mainly adjust assertions/imports and add a new test gate; low runtime risk but may cause CI failures if the new fitness rules are too strict or the baseline misses existing cases.

Overview
Migrates many E2E/integration/unit tests away from hardcoded English strings and as string casts, instead asserting against shared i18n message sources (via new test/lib/i18n-helpers.ts exports like enLocale and stricter tEn).

Adds a new global “fitness function” test (locale-query-mismatch.test.ts) that scans UI test files to prevent (1) querying locale messages when the UI is hardcoded, and (2) hardcoding query strings that match locale values beyond an explicit per-file baseline.

Cleans up test utilities by removing unused re-exports (test/jest/index.js) and switching some tests to import fireEvent directly from @testing-library/react; also updates RewardsErrorBanner to use i18n (t('dismiss')/t('confirm')) for button labels and adjusts its tests accordingly.

Written by Cursor Bugbot for commit 1ae22cc. This will update automatically on new commits. Configure here.

@DDDDDanica DDDDDanica requested review from a team as code owners February 6, 2026 01:59
@github-actions
Copy link
Contributor

github-actions bot commented Feb 6, 2026

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@DDDDDanica DDDDDanica requested review from a team and HowardBraham as code owners February 6, 2026 02:04
@DDDDDanica DDDDDanica force-pushed the chore/6395-i18n branch 2 times, most recently from 3615649 to 3ec08ca Compare February 6, 2026 02:18
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 6, 2026

✨ Files requiring CODEOWNER review ✨

💎 @MetaMask/metamask-assets (5 files, +41 -19)
  • 📁 ui/
    • 📁 components/
      • 📁 app/
        • 📁 assets/
          • 📁 asset-list/
            • 📁 asset-list-control-bar/
              • 📄 asset-list-control-bar.test.tsx +1 -1
          • 📁 defi-list/
            • 📄 defi-list.test.tsx +9 -4
            • 📄 defi-tab.test.tsx +5 -2
          • 📁 nfts/
            • 📁 nft-empty-state/
              • 📄 nft-empty-state.test.tsx +4 -5
            • 📁 nfts-tab/
              • 📄 nfts-tab.test.js +22 -7

🧪 @MetaMask/qa (4 files, +18 -20)
  • 📁 test/
    • 📁 e2e/
      • 📁 page-objects/
        • 📁 pages/
          • 📁 confirmations/
            • 📄 erc20-approve-transaction-confirmation.ts +8 -8
            • 📄 set-approval-for-all-transaction-confirmation.ts +3 -3
            • 📄 token-transfer-confirmation.ts +3 -3
            • 📄 transaction-confirmation.ts +4 -6

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

// Report ALL violations for this file so the developer can identify
// which ones are new (we can't know positionally which are "old").
newViolations.push(...violations);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Locale fitness test misses non-UI tests

Medium Severity

The Rule 2 fitness function claims to scan all test files, but it only searches under ui/ (uiDir) when collecting testFiles. This can let new hardcoded-locale query strings slip into non-UI tests without being caught, weakening the intended quality gate.

Fix in Cursor Fix in Web

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests outside ui/ almost never use getByText with locale-matching strings. So this comment is okay to ignore

import { getMessage } from '../../ui/helpers/utils/i18n-helper';
import en from '../../app/_locales/en/messages.json';

const enMessages = en as unknown as I18NMessageDict;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like a type assertion is needed here, especially not one from unknown

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, dropped the double assertion entirely here: 147df35

export const enLocale = enMessages;

export function tEn(key: string, substitutions: string[] = []): string {
return getMessage('en', enMessages, key, substitutions) as string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type assertion doesn't seem to be correct. getMessage can return a React component or null according to the type definition. We know this will never return a React component in this case (because we never pass in one as a substitution), but null is a real possibility.

We should either check for null here, or update the return type of tEn to include null. We can also get rid of the type violation about the React component return type by using the underlying shared getMessage function instead (from shared/modules/i18n.ts)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! switched to the shared getMessage from shared/modules/i18n.ts and updated the return type to string | null. No more type assertion now. Addressed in 147df35

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 24, 2026

Builds ready [41bac7b]
⚡ Performance Benchmarks (1466 ± 151 ms)
👆 Interaction Benchmarks
ActionMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account2573256262
total2573256262
Confirm Txconfirm_tx60441660576063
total60441660576063
Bridge User Actionsbridge_load_page2004204205
bridge_load_asset_picker1882189192
bridge_search_token6943696699
total1083510881089
🔌 Startup Benchmarks
BuildMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
Chrome Browserify Startup Standard HomeuiStartup14661163211115115711690
load1259992183014013501487
domContentLoaded1251975182013813411479
domInteractive2815141212579
firstPaint1536542386205336
backgroundConnect20918329718213243
firstReactRender18114051926
initialActions104112
loadScripts1060781160913611481286
setupStore1273551420
numNetworkReqs312291192284
Chrome Browserify Startup Power User HomeuiStartup17251348227916217881971
load11511038174013811401563
domContentLoaded11351031166512911281514
domInteractive3318140223385
firstPaint201711689196253372
backgroundConnect28525736421294326
firstReactRender23144262635
initialActions106113
loadScripts93083314701279191294
setupStore17983111833
numNetworkReqs58391542559122
Chrome Webpack Startup Standard HomeuiStartup86571613481099021078
load734616108395780896
domContentLoaded728612107994775888
domInteractive2916124232492
firstPaint1156135556138223
backgroundConnect27195873140
firstReactRender1912124122132
initialActions103112
loadScripts726610107293773883
setupStore1152231218
numNetworkReqs312294202587
Chrome Webpack Startup Power User HomeuiStartup1261872214920313321649
load71262314411316931023
domContentLoaded70361714191306831014
domInteractive35171623132122
firstPaint1376250385184281
backgroundConnect19015138656187329
firstReactRender24173942732
initialActions102111
loadScripts70161514101296811007
setupStore1455481433
numNetworkReqs1073926655140253
Firefox Browserify Startup Standard HomeuiStartup16261333240420216332141
load13671135210116713941646
domContentLoaded13661135210116713931646
domInteractive81342604293153
firstPaint------
backgroundConnect6027345416282
firstReactRender13112111315
initialActions102112
loadScripts13401120207116213721580
setupStore207191321546
numNetworkReqs311996212592
Firefox Browserify Startup Power User HomeuiStartup27622068466648128993673
load15661274238026316732198
domContentLoaded15651274237926316732198
domInteractive11737508107112414
firstPaint------
backgroundConnect2761091363242239855
firstReactRender19146781822
initialActions103122
loadScripts15271254235424416422043
setupStore119879918399594
numNetworkReqs59281473278122
Firefox Webpack Startup Standard HomeuiStartup16091347202812516651847
load1357114015869014151477
domContentLoaded1355113915859114151477
domInteractive912825846131167
firstPaint------
backgroundConnect55252122961103
firstReactRender15122531522
initialActions102012
loadScripts1333112515568813961451
setupStore217178271556
numNetworkReqs312095182779
Firefox Webpack Startup Power User HomeuiStartup27081930389943927833722
load15541187257028217112043
domContentLoaded15541187257028317102043
domInteractive14730765183115665
firstPaint------
backgroundConnect263108976207246823
firstReactRender23166882532
initialActions217122
loadScripts15221170255428016851986
setupStore13191185197134562
numNetworkReqs59291543688135
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2182220221
srpButtonToSrpForm94395100
confirmSrpToPwForm2312324
pwFormToMetricsScreen1832023
metricsToWalletReadyScreen1711819
doneButtonToHomeScreen99125211811256
openAccountMenuToAccountListLoaded711360776527852
total847446388819021
Onboarding New WalletcreateWalletToSocialScreen2192220221
srpButtonToPwForm1021104105
createPwToRecoveryScreen8088
skipBackupToMetricsScreen3403435
agreeButtonToOnboardingSuccess1611717
doneButtonToAssetList84027911761187
total122328515531589
Asset DetailsassetClickToPriceChart46155274
total46155274
Solana Asset DetailsassetClickToPriceChart4714849
total4714849
Import Srp HomeloginToHomeScreen19956820202106
openAccountMenuAfterLogin4224444
homeAfterImportWithNewWallet231112224092420
total434415643404584
Send TransactionsopenSendPageFromHome1721719
selectTokenToSendFormLoaded1912121
reviewTransactionToConfirmationPage8555859861
total8978895910
SwapopenSwapPageFromHome12216122147
fetchAndDisplaySwapQuotes45821345944595
total4713347164716
🌐 Dapp Page Load Benchmarks

Current Commit: 41bac7b | Date: 2/24/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.05s (±116ms) 🟡 | historical mean value: 1.04s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 737ms (±139ms) 🟢 | historical mean value: 724ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 98ms (±208ms) 🟢 | historical mean value: 77ms ⬆️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.05s 116ms 1.01s 2.18s 1.08s 2.18s
domContentLoaded 737ms 139ms 703ms 2.10s 757ms 2.10s
firstPaint 98ms 208ms 60ms 2.16s 88ms 2.16s
firstContentfulPaint 98ms 208ms 60ms 2.16s 88ms 2.16s
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs
  • background: 58 Bytes (0%)
  • ui: 57 Bytes (0%)
  • common: 20 Bytes (0%)


const enLocale: Record<string, { message: string }> =
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
require('../../app/_locales/en/messages.json');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use require here? We should be able to import it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed to work when I tried it locally. Initially it caused a type error because the type was too exact, and it didn't know how to handle keys of type string. But this was easily fixed by loosening the type so that it treats all keys the same, e.g.

import enLocaleLiteral from '../../app/_locales/en/messages.json';

// Loosen locale type to simplify access via `string` key
const enLocale: Record<string, { message: string }> = enLocaleLiteral;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to an import now: 147df35

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 25, 2026

Builds ready [147df35]
⚡ Performance Benchmarks (1377 ± 94 ms)
👆 Interaction Benchmarks
ActionMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account27413275293
total27413275293
Confirm Txconfirm_tx60523060686093
total60523060686093
Bridge User Actionsbridge_load_page2136221221
bridge_load_asset_picker21441245255
bridge_search_token7273727731
total1173411751179
🔌 Startup Benchmarks
BuildMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
Chrome Browserify Startup Standard HomeuiStartup1377117616099414081581
load117197814239011981363
domContentLoaded116497313588711931346
domInteractive2817102202488
firstPaint178671381201215372
backgroundConnect20919127316209247
firstReactRender19123852030
initialActions107113
loadScripts97378211698710011156
setupStore1372851723
numNetworkReqs312290202387
Chrome Browserify Startup Power User HomeuiStartup17171408220415117522061
load11261014170815411081554
domContentLoaded11111005165714810961544
domInteractive35171782931112
firstPaint181671471156236379
backgroundConnect28725360438292328
firstReactRender23154362535
initialActions103111
loadScripts90879714401438931299
setupStore1574771727
numNetworkReqs61351522859146
Chrome Webpack Startup Standard HomeuiStartup86171511861039121082
load72761295789775894
domContentLoaded72160894888771887
domInteractive2915177262489
firstPaint1156144669133231
backgroundConnect27206273039
firstReactRender1912113112036
initialActions105112
loadScripts71960694087769878
setupStore1264251320
numNetworkReqs312292202585
Chrome Webpack Startup Power User HomeuiStartup1213915193916912761580
load7136281249112705986
domContentLoaded7036231242112691979
domInteractive36191482836115
firstPaint1386240174164281
backgroundConnect17512930946169292
firstReactRender23173542529
initialActions108111
loadScripts7006211222109689972
setupStore1355081420
numNetworkReqs1054126252141239
Firefox Browserify Startup Standard HomeuiStartup16431382252619316612085
load13801184186613114201625
domContentLoaded13781184186613114201625
domInteractive79362174098139
firstPaint------
backgroundConnect66284295959155
firstReactRender13112121316
initialActions103112
loadScripts13481166166611213941566
setupStore2381943615109
numNetworkReqs3220102212792
Firefox Browserify Startup Power User HomeuiStartup26721956425440927423533
load15501309287626516272069
domContentLoaded15491308287626516262065
domInteractive129351353162113350
firstPaint------
backgroundConnect2621091461236233852
firstReactRender1914130131722
initialActions102122
loadScripts15121286285325715822011
setupStore1366828193129602
numNetworkReqs62311383281124
Firefox Webpack Startup Standard HomeuiStartup18101472386346917582789
load15181257348939414961770
domContentLoaded15171257348939414951764
domInteractive1003338056134192
firstPaint------
backgroundConnect65292894166147
firstReactRender16132931723
initialActions115122
loadScripts14911231337538914721747
setupStore43821022083057
numNetworkReqs312089172775
Firefox Webpack Startup Power User HomeuiStartup26771932440545129283525
load15461273236827917612138
domContentLoaded15461272236727917602138
domInteractive11831749140100489
firstPaint------
backgroundConnect2491141477214219678
firstReactRender20163032128
initialActions103122
loadScripts14991238216525317052045
setupStore1758842226259743
numNetworkReqs61291923778142
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2182219220
srpButtonToSrpForm8908989
confirmSrpToPwForm2002121
pwFormToMetricsScreen1511416
metricsToWalletReadyScreen1501515
doneButtonToHomeScreen86426411621199
openAccountMenuToAccountListLoaded70739772097209
total826245087348856
Onboarding New WalletcreateWalletToSocialScreen2246230233
srpButtonToPwForm1082108110
createPwToRecoveryScreen9099
skipBackupToMetricsScreen3803838
agreeButtonToOnboardingSuccess1701717
doneButtonToAssetList7492499221148
total114224813391526
Asset DetailsassetClickToPriceChart54156577
total54156577
Solana Asset DetailsassetClickToPriceChart5045257
total5045257
Import Srp HomeloginToHomeScreen19776620252041
openAccountMenuAfterLogin4534648
homeAfterImportWithNewWallet227116323042525
total429312743904442
Send TransactionsopenSendPageFromHome1811919
selectTokenToSendFormLoaded2122023
reviewTransactionToConfirmationPage924889451085
total93237951983
SwapopenSwapPageFromHome13835162182
fetchAndDisplaySwapQuotes46716447344737
total48077848474899
🌐 Dapp Page Load Benchmarks

Current Commit: 147df35 | Date: 2/25/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 973ms (±37ms) 🟢 | historical mean value: 1.04s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 676ms (±34ms) 🟢 | historical mean value: 724ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 75ms (±9ms) 🟢 | historical mean value: 77ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 973ms 37ms 940ms 1.23s 1000ms 1.23s
domContentLoaded 676ms 34ms 649ms 922ms 697ms 922ms
firstPaint 75ms 9ms 60ms 152ms 84ms 152ms
firstContentfulPaint 75ms 9ms 60ms 152ms 84ms 152ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs
  • background: 58 Bytes (0%)
  • ui: 57 Bytes (0%)
  • common: 20 Bytes (0%)

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

const HARDCODED_QUERY_OPTIONS_PATTERN_R2 = new RegExp(
`(?:${QUERY_FN_GROUP})\\s*\\([^)]*\\{\\s*name:\\s*(?:'([^']{3,})'|"([^"]{3,})")`,
'gu',
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fitness function Rule 2 regex misses template literal queries

Low Severity

The Rule 2 HARDCODED_QUERY_DIRECT_PATTERN_R2 and HARDCODED_QUERY_OPTIONS_PATTERN_R2 regexes only match single-quoted or double-quoted strings. They miss template literal strings (backtick-delimited), such as getByText(`${messages.tokenAddress.message}:`), which are used in this very PR (e.g., detected-token-address.test.js). More importantly, they also miss backtick-based hardcoded strings like getByText(`Token address:`) that a developer might add in the future. This means the fitness function won't catch all hardcoded query strings that match locale values.

Fix in Cursor Fix in Web

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch ! added 1ae22cc

@sonarqubecloud
Copy link

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 25, 2026

Builds ready [b1b7da9]
⚡ Performance Benchmarks (1362 ± 101 ms)
👆 Interaction Benchmarks
ActionMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account2592260262
total2592260262
Confirm Txconfirm_tx6046860486058
total6046860486058
Bridge User Actionsbridge_load_page20411200223
bridge_load_asset_picker19153206277
bridge_search_token6984701702
total10921410981108
🔌 Startup Benchmarks
BuildMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
Chrome Browserify Startup Standard HomeuiStartup13621156170710113971558
load115597714118611981325
domContentLoaded114997213968511941314
domInteractive2715101182477
firstPaint162671253164205318
backgroundConnect20518740524204234
firstReactRender20126272231
initialActions104113
loadScripts96179112028410041120
setupStore1365061520
numNetworkReqs312290202286
Chrome Browserify Startup Power User HomeuiStartup17671369234616018122064
load11741050178915111731591
domContentLoaded11601041174714511561546
domInteractive38182133636118
firstPaint1857249791245326
backgroundConnect29626437822300340
firstReactRender26164882842
initialActions105112
loadScripts94582415211429421334
setupStore1784372130
numNetworkReqs58221572758123
Chrome Webpack Startup Standard HomeuiStartup84769311421059071093
load72560796192771903
domContentLoaded71960295291765898
domInteractive2715116212380
firstPaint1166028253142228
backgroundConnect26195673039
firstReactRender19124172135
initialActions107112
loadScripts71660094190763891
setupStore1162741218
numNetworkReqs312296202590
Chrome Webpack Startup Power User HomeuiStartup1249965178416313311597
load74865312591197341073
domContentLoaded73864512511177261060
domInteractive38181582837121
firstPaint1486845384189315
backgroundConnect17813435549184291
firstReactRender24174142631
initialActions102011
loadScripts73464412411157241044
setupStore1555281535
numNetworkReqs83402494289192
Firefox Browserify Startup Standard HomeuiStartup15811360221317715921925
load13321149197614913641617
domContentLoaded13301149197214913631616
domInteractive73332444286138
firstPaint------
backgroundConnect5526212265674
firstReactRender13111711315
initialActions102012
loadScripts13061127194914613301535
setupStore177150251432
numNetworkReqs312096212591
Firefox Browserify Startup Power User HomeuiStartup27092045432842827513591
load15801264270330516672269
domContentLoaded15791263270230616672269
domInteractive13236756141122480
firstPaint------
backgroundConnect2361071249219205867
firstReactRender18147381921
initialActions203122
loadScripts15481242264029616162224
setupStore1568807219145662
numNetworkReqs60291553283117
Firefox Webpack Startup Standard HomeuiStartup16821407323920917172017
load14121169289917514561545
domContentLoaded14111169289817514561544
domInteractive983029651131210
firstPaint------
backgroundConnect63253064265141
firstReactRender15122731524
initialActions103112
loadScripts13871144287317214251516
setupStore237182311661
numNetworkReqs311990172781
Firefox Webpack Startup Power User HomeuiStartup25991886363939427193488
load15591287233527116892054
domContentLoaded15581287233427116892053
domInteractive13335728154110542
firstPaint------
backgroundConnect227101886186209817
firstReactRender21156772230
initialActions214123
loadScripts15211264228725416581994
setupStore16781076223195691
numNetworkReqs60291433688135
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2171217219
srpButtonToSrpForm9119192
confirmSrpToPwForm2102222
pwFormToMetricsScreen1401515
metricsToWalletReadyScreen1511616
doneButtonToHomeScreen685100783814
openAccountMenuToAccountListLoaded756452980578068
total861051189929103
Onboarding New WalletcreateWalletToSocialScreen2191220221
srpButtonToPwForm1030103103
createPwToRecoveryScreen8088
skipBackupToMetricsScreen3513535
agreeButtonToOnboardingSuccess1501515
doneButtonToAssetList58079612682
total961779921062
Asset DetailsassetClickToPriceChart3844144
total3844144
Solana Asset DetailsassetClickToPriceChart4614647
total4614647
Import Srp HomeloginToHomeScreen19038219062032
openAccountMenuAfterLogin3853845
homeAfterImportWithNewWallet233912124312486
total436327244614843
Send TransactionsopenSendPageFromHome2593637
selectTokenToSendFormLoaded2112121
reviewTransactionToConfirmationPage85610864866
total9117921921
SwapopenSwapPageFromHome1172119120
fetchAndDisplaySwapQuotes45851245924600
total47021447124719
🌐 Dapp Page Load Benchmarks

Current Commit: b1b7da9 | Date: 2/25/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.02s (±44ms) 🟡 | historical mean value: 1.04s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 713ms (±38ms) 🟢 | historical mean value: 725ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 75ms (±13ms) 🟢 | historical mean value: 77ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.02s 44ms 999ms 1.34s 1.05s 1.34s
domContentLoaded 713ms 38ms 690ms 991ms 731ms 991ms
firstPaint 75ms 13ms 56ms 184ms 84ms 184ms
firstContentfulPaint 75ms 13ms 56ms 184ms 84ms 184ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs
  • background: 58 Bytes (0%)
  • ui: 57 Bytes (0%)
  • common: 20 Bytes (0%)

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

`(?:${QUERY_FN_GROUP})\\s*\\([^)]*\\{\\s*name:\\s*(?:'([^']{3,})'` +
'|`([^`$]{3,})`)',
'gu',
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fitness function regex misses double-quoted hardcoded strings

Low Severity

HARDCODED_QUERY_DIRECT_PATTERN_R2 and HARDCODED_QUERY_OPTIONS_PATTERN_R2 match single-quoted and backtick strings but omit double-quoted strings entirely. While Prettier currently enforces singleQuote: true, any test file that bypasses formatting or uses a different config would silently pass the fitness function despite having hardcoded locale-matching strings in double quotes. Adding a "([^"]{3,})" branch would close the gap.

Additional Locations (1)

Fix in Cursor Fix in Web

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 25, 2026

Builds ready [1ae22cc]
⚡ Performance Benchmarks (1332 ± 97 ms)
👆 Interaction Benchmarks
ActionMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account26911265288
total26911265288
Confirm Txconfirm_tx60361260476050
total60361260476050
Bridge User Actionsbridge_load_page18811192203
bridge_load_asset_picker20711203225
bridge_search_token71221727745
total11365911941218
🔌 Startup Benchmarks
BuildMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
Chrome Browserify Startup Standard HomeuiStartup1332116215879713661525
load113696313558611731296
domContentLoaded112995613488611681289
domInteractive2715147222385
firstPaint152621139122197279
backgroundConnect19918425314201232
firstReactRender18123132023
initialActions107113
loadScripts9457731160859821111
setupStore1262751523
numNetworkReqs312289192280
Chrome Browserify Startup Power User HomeuiStartup16971400219515317431985
load11331022165113211171486
domContentLoaded11211016163913011071449
domInteractive3419168233572
firstPaint1647346983214311
backgroundConnect28525136022291325
firstReactRender24155982638
initialActions107112
loadScripts91580314111288991229
setupStore1786191833
numNetworkReqs61381572558122
Chrome Webpack Startup Standard HomeuiStartup8447021146898751040
load71761194282758866
domContentLoaded71260792881753860
domInteractive2715111202478
firstPaint1126136060128245
backgroundConnect27196873039
firstReactRender2111205202136
initialActions103112
loadScripts70960592380751852
setupStore1263561424
numNetworkReqs3122101212586
Chrome Webpack Startup Power User HomeuiStartup1224933204716712951566
load71962612791247051042
domContentLoaded71062012661246961038
domInteractive39191913734142
firstPaint145651280136165330
backgroundConnect18113242255209300
firstReactRender23173632529
initialActions102111
loadScripts70761812561216941029
setupStore1364461424
numNetworkReqs1073826454138245
Firefox Browserify Startup Standard HomeuiStartup16221374258619216421954
load13691138223215914121690
domContentLoaded13681134223216014121690
domInteractive84352975193180
firstPaint------
backgroundConnect59282243161114
firstReactRender13111911415
initialActions102012
loadScripts13411117220215013881579
setupStore197152231660
numNetworkReqs311997192585
Firefox Browserify Startup Power User HomeuiStartup25691899363538726633392
load15121198219625715832152
domContentLoaded15111198219625715822152
domInteractive1053650183104305
firstPaint------
backgroundConnect226104893186197728
firstReactRender1914115131826
initialActions106122
loadScripts14691182217224815282089
setupStore104769314996425
numNetworkReqs61301503482131
Firefox Webpack Startup Standard HomeuiStartup17001419316024217491998
load14121211284117014501566
domContentLoaded14121209284017014501566
domInteractive973123644131166
firstPaint------
backgroundConnect7423142214068135
firstReactRender16122731625
initialActions103012
loadScripts13871165281216814231537
setupStore247169321676
numNetworkReqs312094172778
Firefox Webpack Startup Power User HomeuiStartup26971884397348228363683
load15351220251230016852272
domContentLoaded15351220251230016842272
domInteractive11831730136101478
firstPaint------
backgroundConnect24062986186230745
firstReactRender22156892429
initialActions218122
loadScripts15001199249428916592230
setupStore20981237267358736
numNetworkReqs58301483575140
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2170217217
srpButtonToSrpForm8818990
confirmSrpToPwForm2102121
pwFormToMetricsScreen1401415
metricsToWalletReadyScreen1501515
doneButtonToHomeScreen64991613805
openAccountMenuToAccountListLoaded734257178257831
total845741787768846
Onboarding New WalletcreateWalletToSocialScreen2204223226
srpButtonToPwForm1041104105
createPwToRecoveryScreen8088
skipBackupToMetricsScreen3733942
agreeButtonToOnboardingSuccess1601616
doneButtonToAssetList60211606615
total997510041004
Asset DetailsassetClickToPriceChart51146073
total51146073
Solana Asset DetailsassetClickToPriceChart4714748
total4714748
Import Srp HomeloginToHomeScreen18883119191926
openAccountMenuAfterLogin3954347
homeAfterImportWithNewWallet221213022812430
total413912341604360
Send TransactionsopenSendPageFromHome32143852
selectTokenToSendFormLoaded2002020
reviewTransactionToConfirmationPage8558859866
total90818923924
SwapopenSwapPageFromHome1251126126
fetchAndDisplaySwapQuotes567480763746381
total579380665006542
🌐 Dapp Page Load Benchmarks

Current Commit: 1ae22cc | Date: 2/25/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.02s (±37ms) 🟡 | historical mean value: 1.04s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 709ms (±35ms) 🟢 | historical mean value: 725ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 74ms (±12ms) 🟢 | historical mean value: 77ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.02s 37ms 995ms 1.30s 1.04s 1.30s
domContentLoaded 709ms 35ms 690ms 973ms 729ms 973ms
firstPaint 74ms 12ms 56ms 180ms 84ms 180ms
firstContentfulPaint 74ms 12ms 56ms 180ms 84ms 180ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs
  • background: 58 Bytes (0%)
  • ui: 57 Bytes (0%)
  • common: 20 Bytes (0%)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size-XL team-extension-platform Extension Platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.