diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index 380da4c272ba..9432f8c4e7af 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -246,6 +246,7 @@ export const SENTRY_BACKGROUND_STATE = { preferences: { autoLockTimeLimit: true, hideZeroBalanceTokens: true, + redesignedConfirmationsEnabled: true, isRedesignedConfirmationsDeveloperEnabled: false, showExtensionInFullSizeView: true, showFiatInTestnets: true, diff --git a/app/scripts/migrations/122.test.ts b/app/scripts/migrations/122.test.ts new file mode 100644 index 000000000000..0cfeb025150d --- /dev/null +++ b/app/scripts/migrations/122.test.ts @@ -0,0 +1,74 @@ +import { migrate, version } from './122'; + +const oldVersion = 121; + +describe('migration #122', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + it('updates the version metadata', async () => { + const oldStorage = { + meta: { + version: oldVersion, + }, + data: {}, + }; + + const newStorage = await migrate(oldStorage); + + expect(newStorage.meta).toStrictEqual({ version }); + }); + + describe('set redesignedConfirmationsEnabled to true in PreferencesController', () => { + it('sets redesignedConfirmationsEnabled to true', async () => { + const oldStorage = { + PreferencesController: { + preferences: { + redesignedConfirmationsEnabled: false, + }, + }, + }; + + const expectedState = { + PreferencesController: { + preferences: { + redesignedConfirmationsEnabled: true, + }, + }, + }; + + const transformedState = await migrate({ + meta: { version: oldVersion }, + data: oldStorage, + }); + + expect(transformedState.data).toEqual(expectedState); + }); + + it( + 'sets redesignedConfirmationsEnabled to true even with original preferences object in the' + + 'state', + async () => { + const oldStorage = { + PreferencesController: {}, + }; + + const expectedState = { + PreferencesController: { + preferences: { + redesignedConfirmationsEnabled: true, + }, + }, + }; + + const transformedState = await migrate({ + meta: { version: oldVersion }, + data: oldStorage, + }); + + expect(transformedState.data).toEqual(expectedState); + }, + ); + }); +}); diff --git a/app/scripts/migrations/122.ts b/app/scripts/migrations/122.ts new file mode 100644 index 000000000000..cb0b2090472b --- /dev/null +++ b/app/scripts/migrations/122.ts @@ -0,0 +1,50 @@ +import { cloneDeep } from 'lodash'; +import { hasProperty, isObject } from '@metamask/utils'; + +type VersionedData = { + meta: { version: number }; + data: Record; +}; + +export const version = 122; + +/** + * This migration sets preference redesignedConfirmationsEnabled to true + * + * @param originalVersionedData - Versioned MetaMask extension state, exactly what we persist to dist. + * @param originalVersionedData.meta - State metadata. + * @param originalVersionedData.meta.version - The current state version. + * @param originalVersionedData.data - The persisted MetaMask state, keyed by controller. + * @returns Updated versioned MetaMask extension state. + */ +export async function migrate( + originalVersionedData: VersionedData, +): Promise { + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + transformState(versionedData.data); + return versionedData; +} + +// TODO: Replace `any` with specific type +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function transformState(state: Record) { + if (!hasProperty(state, 'PreferencesController')) { + return; + } + + if (!isObject(state.PreferencesController)) { + const controllerType = typeof state.PreferencesController; + global.sentry?.captureException?.( + new Error(`state.PreferencesController is type: ${controllerType}`), + ); + } + + if (!isObject(state.PreferencesController?.preferences)) { + state.PreferencesController = { + preferences: {}, + }; + } + + state.PreferencesController.preferences.redesignedConfirmationsEnabled = true; +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 1b680645a331..a12285ac441d 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -133,7 +133,7 @@ const migrations = [ require('./120'), require('./120.1'), require('./121'), - + require('./122'), require('./123'), ]; diff --git a/test/e2e/accounts/snap-account-signatures-and-disconnects.spec.ts b/test/e2e/accounts/snap-account-signatures-and-disconnects.spec.ts index d00540360317..24e996671da9 100644 --- a/test/e2e/accounts/snap-account-signatures-and-disconnects.spec.ts +++ b/test/e2e/accounts/snap-account-signatures-and-disconnects.spec.ts @@ -1,6 +1,10 @@ import { Suite } from 'mocha'; import FixtureBuilder from '../fixture-builder'; -import { withFixtures, multipleGanacheOptions } from '../helpers'; +import { + withFixtures, + multipleGanacheOptions, + tempToggleSettingRedesignedConfirmations, +} from '../helpers'; import { Driver } from '../webdriver/driver'; import { installSnapSimpleKeyring, @@ -27,6 +31,8 @@ describe('Snap Account Signatures and Disconnects', function (this: Suite) { const newPublicKey = await makeNewAccountAndSwitch(driver); + await tempToggleSettingRedesignedConfirmations(driver); + // open the Test Dapp and connect Account 2 to it await connectAccountToTestDapp(driver); diff --git a/test/e2e/accounts/snap-account-signatures.spec.ts b/test/e2e/accounts/snap-account-signatures.spec.ts index 5c1a00a2c00c..8a5af361c029 100644 --- a/test/e2e/accounts/snap-account-signatures.spec.ts +++ b/test/e2e/accounts/snap-account-signatures.spec.ts @@ -1,5 +1,9 @@ import { Suite } from 'mocha'; -import { openDapp, withFixtures } from '../helpers'; +import { + openDapp, + tempToggleSettingRedesignedConfirmations, + withFixtures, +} from '../helpers'; import { Driver } from '../webdriver/driver'; import { accountSnapFixtures, @@ -27,6 +31,8 @@ describe('Snap Account Signatures', function (this: Suite) { const newPublicKey = await makeNewAccountAndSwitch(driver); + await tempToggleSettingRedesignedConfirmations(driver); + await openDapp(driver); // Run all 6 signature types diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index e492e714b00a..eba12c90984e 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -1160,6 +1160,39 @@ async function getSelectedAccountAddress(driver) { return accountAddress; } +/** + * Rather than using the FixtureBuilder#withPreferencesController to set the setting + * we need to manually set the setting because the migration #122 overrides this. + * We should be able to remove this when we delete the redesignedConfirmationsEnabled setting. + * + * @param driver + */ +async function tempToggleSettingRedesignedConfirmations(driver) { + // Ensure we are on the extension window + await driver.switchToWindowWithTitle(WINDOW_TITLES.ExtensionInFullScreenView); + + // Open settings menu button + const accountOptionsMenuSelector = + '[data-testid="account-options-menu-button"]'; + await driver.waitForSelector(accountOptionsMenuSelector); + await driver.clickElement(accountOptionsMenuSelector); + + // Click settings from dropdown menu + await driver.clickElement('[data-testid="global-menu-settings"]'); + + // Click Experimental tab + const experimentalTabRawLocator = { + text: 'Experimental', + tag: 'div', + }; + await driver.clickElement(experimentalTabRawLocator); + + // Click redesignedConfirmationsEnabled toggle + await driver.clickElement( + '[data-testid="toggle-redesigned-confirmations-container"]', + ); +} + module.exports = { DAPP_HOST_ADDRESS, DAPP_URL, @@ -1229,4 +1262,5 @@ module.exports = { defaultGanacheOptionsForType2Transactions, removeSelectedAccount, getSelectedAccountAddress, + tempToggleSettingRedesignedConfirmations, }; diff --git a/test/e2e/snaps/test-snap-siginsights.spec.js b/test/e2e/snaps/test-snap-siginsights.spec.js index 6b43551ac182..2e69d08cd547 100644 --- a/test/e2e/snaps/test-snap-siginsights.spec.js +++ b/test/e2e/snaps/test-snap-siginsights.spec.js @@ -5,6 +5,7 @@ const { openDapp, unlockWallet, switchToNotificationWindow, + tempToggleSettingRedesignedConfirmations, WINDOW_TITLES, } = require('../helpers'); const FixtureBuilder = require('../fixture-builder'); @@ -29,6 +30,7 @@ describe('Test Snap Signature Insights', function () { }, async ({ driver }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); // navigate to test snaps page and connect await driver.openNewPage(TEST_SNAPS_WEBSITE_URL); diff --git a/test/e2e/tests/dapp-interactions/signin-with-ethereum.spec.js b/test/e2e/tests/dapp-interactions/signin-with-ethereum.spec.js index 5c6e3bb4803c..b2fe384f9523 100644 --- a/test/e2e/tests/dapp-interactions/signin-with-ethereum.spec.js +++ b/test/e2e/tests/dapp-interactions/signin-with-ethereum.spec.js @@ -4,6 +4,7 @@ const { withFixtures, openDapp, DAPP_URL, + tempToggleSettingRedesignedConfirmations, unlockWallet, WINDOW_TITLES, } = require('../../helpers'); @@ -28,6 +29,7 @@ describe('Sign in with ethereum', function () { }, async ({ driver }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); // Create a signin with ethereum request in test dapp await openDapp(driver); diff --git a/test/e2e/tests/metrics/signature-approved.spec.js b/test/e2e/tests/metrics/signature-approved.spec.js index c5b4a2ac1165..065c1e792a54 100644 --- a/test/e2e/tests/metrics/signature-approved.spec.js +++ b/test/e2e/tests/metrics/signature-approved.spec.js @@ -8,6 +8,7 @@ const { unlockWallet, getEventPayloads, clickSignOnSignatureConfirmation, + tempToggleSettingRedesignedConfirmations, validateContractDetails, } = require('../../helpers'); const FixtureBuilder = require('../../fixture-builder'); @@ -65,6 +66,7 @@ describe('Signature Approved Event @no-mmi', function () { }, async ({ driver, mockedEndpoint: mockedEndpoints }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); // creates a sign typed data signature request @@ -116,6 +118,7 @@ describe('Signature Approved Event @no-mmi', function () { }, async ({ driver, mockedEndpoint: mockedEndpoints }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); // creates a sign typed data signature request @@ -163,6 +166,7 @@ describe('Signature Approved Event @no-mmi', function () { }, async ({ driver, mockedEndpoint: mockedEndpoints }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); // creates a sign typed data signature request @@ -209,6 +213,7 @@ describe('Signature Approved Event @no-mmi', function () { }, async ({ driver, mockedEndpoint: mockedEndpoints }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); // creates a sign typed data signature request @@ -260,6 +265,7 @@ describe('Signature Approved Event @no-mmi', function () { }, async ({ driver, mockedEndpoint: mockedEndpoints }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); // creates a sign typed data signature request diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json index e5e6a217f42f..391224338a39 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json @@ -204,6 +204,7 @@ "useNativeCurrencyAsPrimaryCurrency": true, "petnamesEnabled": true, "showTokenAutodetectModal": "boolean", + "redesignedConfirmationsEnabled": true, "isRedesignedConfirmationsDeveloperEnabled": "boolean" }, "ipfsGateway": "string", @@ -268,14 +269,14 @@ "errorKey": "", "topAggId": "object", "routeState": "", - "swapsFeatureFlags": {}, "swapsFeatureIsLive": true, "saveFetchedQuotes": false, "swapsQuoteRefreshTime": 60000, "swapsQuotePrefetchingRefreshTime": 60000, "swapsStxBatchStatusRefreshTime": 10000, "swapsStxGetTransactionsRefreshTime": 10000, - "swapsStxMaxFeeMultiplier": 2 + "swapsStxMaxFeeMultiplier": 2, + "swapsFeatureFlags": {} } }, "TokenListController": { diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json index bf71f9095fbb..4d3f7779e456 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json @@ -35,6 +35,7 @@ "useNativeCurrencyAsPrimaryCurrency": true, "petnamesEnabled": true, "showTokenAutodetectModal": "boolean", + "redesignedConfirmationsEnabled": true, "isRedesignedConfirmationsDeveloperEnabled": "boolean" }, "firstTimeFlowType": "import", @@ -62,11 +63,6 @@ }, "connectedStatusPopoverHasBeenShown": true, "defaultHomeActiveTabName": null, - "bridgeState": { - "bridgeFeatureFlags": { - "extensionSupport": "boolean" - } - }, "browserEnvironment": { "os": "string", "browser": "string" }, "popupGasPollTokens": "object", "notificationGasPollTokens": "object", @@ -121,9 +117,9 @@ "useRequestQueue": true, "openSeaEnabled": false, "securityAlertsEnabled": "boolean", - "addSnapAccountEnabled": "boolean", "bitcoinSupportEnabled": "boolean", "bitcoinTestnetSupportEnabled": "boolean", + "addSnapAccountEnabled": "boolean", "advancedGasFee": {}, "incomingTransactionsPreferences": {}, "identities": "object", @@ -248,15 +244,16 @@ "errorKey": "", "topAggId": "object", "routeState": "", - "swapsFeatureFlags": {}, "swapsFeatureIsLive": true, "saveFetchedQuotes": false, "swapsQuoteRefreshTime": 60000, "swapsQuotePrefetchingRefreshTime": 60000, "swapsStxBatchStatusRefreshTime": 10000, "swapsStxGetTransactionsRefreshTime": 10000, - "swapsStxMaxFeeMultiplier": 2 + "swapsStxMaxFeeMultiplier": 2, + "swapsFeatureFlags": {} }, + "bridgeState": { "bridgeFeatureFlags": { "extensionSupport": "boolean" } }, "ensEntries": "object", "ensResolutionsByAddress": "object", "pendingApprovals": "object", diff --git a/test/e2e/tests/petnames/petnames-signatures.spec.js b/test/e2e/tests/petnames/petnames-signatures.spec.js index ecc972ca9f6b..ba6cf7642c59 100644 --- a/test/e2e/tests/petnames/petnames-signatures.spec.js +++ b/test/e2e/tests/petnames/petnames-signatures.spec.js @@ -2,6 +2,7 @@ const { openDapp, switchToNotificationWindow, withFixtures, + tempToggleSettingRedesignedConfirmations, unlockWallet, defaultGanacheOptions, } = require('../../helpers'); @@ -108,6 +109,7 @@ describe('Petnames - Signatures', function () { }, async ({ driver }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); await createSignatureRequest(driver, SIGNATURE_TYPE.TYPED_V3); await switchToNotificationWindow(driver, 3); @@ -144,6 +146,7 @@ describe('Petnames - Signatures', function () { }, async ({ driver }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); await createSignatureRequest(driver, SIGNATURE_TYPE.TYPED_V4); await switchToNotificationWindow(driver, 3); @@ -185,6 +188,7 @@ describe('Petnames - Signatures', function () { }, async ({ driver }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); await openTestSnaps(driver); await installNameLookupSnap(driver); diff --git a/test/e2e/tests/request-queuing/dapp1-send-dapp2-signTypedData.spec.js b/test/e2e/tests/request-queuing/dapp1-send-dapp2-signTypedData.spec.js index cd197970baea..4a6bbec462ab 100644 --- a/test/e2e/tests/request-queuing/dapp1-send-dapp2-signTypedData.spec.js +++ b/test/e2e/tests/request-queuing/dapp1-send-dapp2-signTypedData.spec.js @@ -7,6 +7,7 @@ const { DAPP_ONE_URL, regularDelayMs, defaultGanacheOptions, + tempToggleSettingRedesignedConfirmations, WINDOW_TITLES, } = require('../../helpers'); @@ -42,6 +43,7 @@ describe('Request Queuing Dapp 1, Switch Tx -> Dapp 2 Send Tx', function () { }, async ({ driver }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); // Open Dapp One await openDapp(driver, undefined, DAPP_URL); diff --git a/test/e2e/tests/request-queuing/ui.spec.js b/test/e2e/tests/request-queuing/ui.spec.js index cea9e045ceed..ae84d7125d02 100644 --- a/test/e2e/tests/request-queuing/ui.spec.js +++ b/test/e2e/tests/request-queuing/ui.spec.js @@ -11,6 +11,7 @@ const { WINDOW_TITLES, defaultGanacheOptions, switchToNotificationWindow, + tempToggleSettingRedesignedConfirmations, veryLargeDelayMs, DAPP_TWO_URL, } = require('../../helpers'); @@ -635,6 +636,7 @@ describe('Request-queue UI changes', function () { }, async ({ driver, ganacheServer, secondaryGanacheServer }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); // Navigate to extension home screen await driver.navigate(PAGES.HOME); diff --git a/test/e2e/tests/signature/personal-sign.spec.js b/test/e2e/tests/signature/personal-sign.spec.js index a9ca117d5fe7..e4864a84db47 100644 --- a/test/e2e/tests/signature/personal-sign.spec.js +++ b/test/e2e/tests/signature/personal-sign.spec.js @@ -4,6 +4,7 @@ const { withFixtures, openDapp, regularDelayMs, + tempToggleSettingRedesignedConfirmations, unlockWallet, WINDOW_TITLES, } = require('../../helpers'); @@ -24,6 +25,7 @@ describe('Personal sign', function () { const addresses = await ganacheServer.getAccounts(); const publicAddress = addresses[0]; await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); await driver.clickElement('#personalSign'); @@ -47,6 +49,7 @@ describe('Personal sign', function () { }, ); }); + it('can queue multiple personal signs and confirm', async function () { await withFixtures( { @@ -61,6 +64,7 @@ describe('Personal sign', function () { const addresses = await ganacheServer.getAccounts(); const publicAddress = addresses[0]; await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); // Create personal sign diff --git a/test/e2e/tests/signature/signature-request.spec.js b/test/e2e/tests/signature/signature-request.spec.js index 5a623b683f8c..99fcb61c5067 100644 --- a/test/e2e/tests/signature/signature-request.spec.js +++ b/test/e2e/tests/signature/signature-request.spec.js @@ -5,6 +5,7 @@ const { openDapp, DAPP_URL, defaultGanacheOptions, + tempToggleSettingRedesignedConfirmations, unlockWallet, WINDOW_TITLES, } = require('../../helpers'); @@ -77,6 +78,7 @@ describe('Sign Typed Data Signature Request', function () { const addresses = await ganacheServer.getAccounts(); const publicAddress = addresses[0]; await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); @@ -137,6 +139,7 @@ describe('Sign Typed Data Signature Request', function () { const addresses = await ganacheServer.getAccounts(); const publicAddress = addresses[0]; await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); @@ -212,6 +215,7 @@ describe('Sign Typed Data Signature Request', function () { }, async ({ driver }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); @@ -237,6 +241,8 @@ describe('Sign Typed Data Signature Request', function () { // switch to the Dapp and verify the rejection was successful await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles); + + await driver.waitForSelector(data.verifyRejectionResultId); const rejectionResult = await driver.findElement( data.verifyRejectionResultId, ); @@ -263,6 +269,7 @@ describe('Sign Typed Data Signature Request', function () { }, async ({ driver }) => { await unlockWallet(driver); + await tempToggleSettingRedesignedConfirmations(driver); await openDapp(driver); @@ -306,6 +313,8 @@ describe('Sign Typed Data Signature Request', function () { // switch to the Dapp and verify the rejection was successful await driver.switchToWindowWithTitle('E2E Test Dapp'); + + await driver.waitForSelector(data.verifyRejectionResultId); const rejectionResult = await driver.findElement( data.verifyRejectionResultId, ); diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index e6620daee024..9f5a048e3d69 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -881,7 +881,10 @@ class Driver { await this.delay(delayStep); timeElapsed += delayStep; } - throw new Error('waitUntilXWindowHandles timed out polling window handles'); + + throw new Error( + `waitUntilXWindowHandles timed out polling window handles. Expected: ${x}, Actual: ${windowHandles.length}`, + ); } /** diff --git a/ui/pages/settings/experimental-tab/experimental-tab.component.tsx b/ui/pages/settings/experimental-tab/experimental-tab.component.tsx index c1dcdf7d0397..ca1345cffd1e 100644 --- a/ui/pages/settings/experimental-tab/experimental-tab.component.tsx +++ b/ui/pages/settings/experimental-tab/experimental-tab.component.tsx @@ -153,6 +153,7 @@ export default class ExperimentalTab extends PureComponent description: t('redesignedConfirmationsToggleDescription'), toggleValue: redesignedConfirmationsEnabled, toggleCallback: (value) => setRedesignedConfirmationsEnabled(!value), + toggleContainerDataTestId: 'toggle-redesigned-confirmations-container', toggleDataTestId: 'toggle-redesigned-confirmations', toggleOffLabel: t('off'), toggleOnLabel: t('on'),