Skip to content

perf(predict): remove GTM onboarding modal#33384

Draft
ghgoodreau wants to merge 2 commits into
mainfrom
pred-977
Draft

perf(predict): remove GTM onboarding modal#33384
ghgoodreau wants to merge 2 commits into
mainfrom
pred-977

Conversation

@ghgoodreau

@ghgoodreau ghgoodreau commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Description

The Predict GTM onboarding modal decoded a 4096 x 3175 PNG after users reached wallet home, creating an estimated 52 MB decoded-memory spike and adding approximately 1.85 MB to the bundle. Following the product decision to retire this onboarding experience instead of resizing its asset, this removes the complete modal flow: wallet startup navigation, route and navigation types, app-side feature-flag selection, storage and analytics constants, localized copy, modal assets, and test suppression/dismissal logic. Onboarding and performance flows now proceed directly to wallet home. The remote flag remains listed only in the production feature-flag registry until it is deleted server-side; the app no longer consumes it.

Changelog

CHANGELOG entry: Removed the Predict onboarding modal to improve wallet startup performance

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/PRED-977
Closes: #31302

Manual testing steps

Feature: Wallet onboarding without the Predict GTM modal

  Scenario: Complete new-wallet onboarding
    Given the user is completing onboarding for a new wallet
    And Predict trading is enabled

    When the user completes onboarding
    Then wallet home is displayed
    And the Predict GTM onboarding modal is not displayed

  Scenario: Import an existing wallet
    Given the user is importing an existing wallet

    When the user completes the import flow
    Then wallet home is displayed
    And the Predict GTM onboarding modal is not displayed

  Scenario: Open Predict after onboarding
    Given the user has completed onboarding

    When the user opens Predict
    Then the prediction markets experience is displayed

Screenshots/Recordings

Before

N/A - No screenshot or recording was captured for the retired Predict GTM onboarding modal.

After

N/A - No screenshot or recording was captured; users now proceed directly to the existing wallet home UI.

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • N/A: The oversized decode path and modal were removed; no manual Android test was performed.
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • N/A: The removed modal did not depend on account, token, or activity volume.
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics
    • N/A: The performance-sensitive operation was deleted rather than instrumented.
    • See trace() for usage and addToken for an example

For performance guidelines and tooling, see the Performance Guide.

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.

@github-actions

Copy link
Copy Markdown
Contributor

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.

@metamask-ci metamask-ci Bot added the team-predict Predict team label Jul 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Feature Flag Registry Check

Possibly unused flags

This PR removes the last codebase references to the following registered flags.
Consider removing them from the registry or marking them as deprecated.

  • predictGtmOnboardingModalEnabled

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeAccounts, SmokeConfirmations, SmokeNetworkAbstractions, SmokeNetworkExpansion, SmokeSwap, SmokeStake, SmokeWalletPlatform, SmokeMoney, SmokePerps, SmokeMultiChainAPI, SmokePredictions, SmokeSeedlessOnboarding, SmokeBrowser, SmokeSnaps
  • Selected Performance tags: @PerformanceOnboarding
  • Risk Level: high
  • AI Confidence: 100%
click to see 🤖 AI reasoning details

E2E Test Selection:
Hard rule (test-framework-infra-change): Test framework infrastructure changed: tests/framework/fixtures/json/default-fixture.json. Running all tests.

Performance Test Selection:
Four performance spec files were directly modified to remove Predict GTM modal handling: import-wallet.spec.ts, new-wallet-account-creation.spec.ts, seedless-apple-onboarding.spec.ts, and seedless-google-onboarding.spec.ts — all tagged with @PerformanceOnboarding. The timer structure was changed (timer6 removed from seedless specs, timer6 removed from import-wallet spec), and the flow logic was simplified by removing modal dismissal steps. These performance tests need to run to validate the updated timing measurements and flow logic are correct.

View GitHub Actions results

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Flaky unit test detection

Run history flaky detection

View recent run history

Historical failure rate is a hint, not proof — review each suggestion in context. See the flaky-test-detection skill for the full pattern reference and manual audit workflow.

Failures / runs sampled per window:

File 7d 15d 30d
app/components/UI/Predict/routes/index.test.tsx 0/118 0/170 0/375
app/components/Views/Wallet/index.test.tsx 0/118 0/170 0/375

AI-detected flaky patterns

app/components/UI/Predict/routes/index.test.tsx

  • J9 — Module-level mutable let bindings not reset in beforeEach (high)
    • Four module-level let bindings control which screens are rendered. The PredictScreenStack describe block resets all four in its beforeEach, but the PredictModalStack describe block's beforeEach only calls jest.clearAllMocks() and resets navigationRef — it never resets the flag variables. If a PredictScreenStack test mutates a flag (e.g. mockWorldCupHubV2Enabled = true or mockPayWithAnyTokenEnabled = true) and Jest runs PredictModalStack tests immediately after, those stale values persist. Because Jest does not guarantee test-file execution order within a describe suite, this is an order-dependent failure.
    • Suggested fix in app/components/UI/Predict/routes/index.test.tsx:10:
      -let mockPayWithAnyTokenEnabled = false;
      -let mockPredictPortfolioEnabled = true;
      -let mockPredictHomeRedesignEnabled = false;
      -let mockWorldCupHubV2Enabled = false;
      +describe('PredictModalStack', () => {
      +  beforeEach(() => {
      +    jest.clearAllMocks();
      +    // Reset all module-level flag bindings so PredictModalStack tests
      +    // are never affected by mutations made in PredictScreenStack tests.
      +    mockPayWithAnyTokenEnabled = false;
      +    mockPredictPortfolioEnabled = true;
      +    mockPredictHomeRedesignEnabled = false;
      +    mockWorldCupHubV2Enabled = false;
      +    navigationRef = React.createRef();
      +  });

app/components/Views/Wallet/index.test.tsx

  • J2 — Real timers where fake timers are needed (fake timers leak between tests) (high)
    • Three tests inside HomepageDiscoveryTabs AB test call jest.useFakeTimers() inline, but the describe block's afterEach only calls jest.clearAllMocks() — it never calls jest.useRealTimers(). Fake timers installed by one test therefore leak into every subsequent test in the same describe block and into the following HomepageDiscoveryPills AB test describe block. Tests that run after a fake-timer test and rely on real async behaviour (e.g. act(async () => { ... }), waitFor, or any real setTimeout) will hang or produce non-deterministic results. The useHomeDeepLinkEffects describe block correctly pairs jest.useFakeTimers() in beforeEach with jest.useRealTimers() in afterEach — the same pattern should be applied here.
    • Suggested fix in app/components/Views/Wallet/index.test.tsx:1:
      -describe('HomepageDiscoveryTabs AB test', () => {
      -  // ...
      -  afterEach(() => {
      -    mockDiscoveryTabsVariantName = 'control';
      -    jest.clearAllMocks();
      -  });
      -  // ...
      -  it('selects the Perps discovery tab for Perps deeplinks in treatment', () => {
      -    jest.useFakeTimers();
      -    // ...
      -  });
      -  it('navigates to Perps screen for Perps deeplinks in control', () => {
      -    jest.useFakeTimers();
      -    // ...
      -  });
      -  it('navigates to network selector from deeplink params', () => {
      -    jest.useFakeTimers();
      -    // ...
      -  });
      +describe('HomepageDiscoveryTabs AB test', () => {
      +  let mockNavigation: NavigationProp<ParamListBase>;
      +  beforeEach(() => {
      +    jest.clearAllMocks();
      +    mockDiscoveryTabsVariantName = 'control';
      +    mockHomepageDiscoveryTabs.mockClear();
      +    mockHomepageDiscoveryTabsRefresh.mockClear();
      +    // ... other setup ...
      +  });
      +  afterEach(() => {
      +    mockDiscoveryTabsVariantName = 'control';
      +    jest.runOnlyPendingTimers(); // drain any pending fake timers
      +    jest.useRealTimers();        // always restore real timers
      +    jest.clearAllMocks();
      +  });
      +  // ...
      +  it('selects the Perps discovery tab for Perps deeplinks in treatment', () => {
      +    jest.useFakeTimers();
      +    // ... rest of test unchanged ...
      +  });
      +  it('navigates to Perps screen for Perps deeplinks in control', () => {
      +    jest.useFakeTimers();
      +    // ... rest of test unchanged ...
      +  });
      +  it('navigates to network selector from deeplink params', () => {
      +    jest.useFakeTimers();
      +    // ... rest of test unchanged ...
      +  });

This check is informational only and does not block merging.

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

⚡ Performance Test Results

ℹ️ Performance test results are currently non-blocking and will not block this PR.

3 tests failed · 6 tests · 1 device

📱 Devices tested (1)

Android: Google Pixel 8 Pro (v14.0)

❌ Failed Tests (3)

@metamask-onboarding-team

Test Platform Device Reason Recording
Account creation after fresh install Android Google Pixel 8 Pro (v14.0) Quality gates exceeded 📹 Watch
Seedless Onboarding: Apple Login New User Android Google Pixel 8 Pro (v14.0) Quality gates exceeded 📹 Watch
Seedless Onboarding: Google Login New User Android Google Pixel 8 Pro (v14.0) Quality gates exceeded 📹 Watch
✅ Passed Tests (3)
Test Platform Device Duration Team Recording
Measure Cold Start To Onboarding Screen Android Google Pixel 8 Pro (v14.0) 3.86s @metamask-mobile-platform 📹 Watch
Onboarding Import SRP with +50 accounts, SRP 3 Android Google Pixel 8 Pro (v14.0) 6.52s @metamask-onboarding-team 📹 Watch
Cold Start after importing a wallet Android Google Pixel 8 Pro (v14.0) 1.98s @metamask-mobile-platform 📹 Watch

Branch: pred-977 · Build: Normal · Commit: 2f848a3 · View full run

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Downsize 4096px predict-marketing.png bundled asset (oversized decode)

1 participant