diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js index 8c23a8eee2c6..a43bdb72108b 100644 --- a/test/e2e/fixture-builder.js +++ b/test/e2e/fixture-builder.js @@ -494,7 +494,7 @@ class FixtureBuilder { }); } - withPermissionControllerConnectedToTestDappMultichain({ + withPermissionControllerConnectedToMultichainTestDapp({ account = '', useLocalhostHostname = false, } = {}) { @@ -541,7 +541,7 @@ class FixtureBuilder { }); } - withPermissionControllerConnectedToTestDappMultichainWithTwoAccounts({ + withPermissionControllerConnectedToMultichainTestDappWithTwoAccounts({ scopes = ['eip155:1337'], }) { const optionalScopes = scopes diff --git a/test/e2e/flask/multichain-api/connect.spec.ts b/test/e2e/flask/multichain-api/connect.spec.ts index 835df1e32098..16ab380e913c 100644 --- a/test/e2e/flask/multichain-api/connect.spec.ts +++ b/test/e2e/flask/multichain-api/connect.spec.ts @@ -8,9 +8,9 @@ import { WINDOW_TITLES, withFixtures, } from '../../helpers'; -import { Driver } from '../../webdriver/driver'; import FixtureBuilder from '../../fixture-builder'; +import type { FixtureCallbackArgs } from './testHelpers'; describe('Multichain API', function () { it('should connect the wallet to the multichain test dapp via `externally_connectable` and successfully create a session with the requested chains', async function () { @@ -30,13 +30,7 @@ describe('Multichain API', function () { fixtures: new FixtureBuilder().withPopularNetworks().build(), title: this.test?.fullTitle(), }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await unlockWallet(driver); await openDapp(driver, undefined, DAPP_URL); diff --git a/test/e2e/flask/multichain-api/password-locked.spec.ts b/test/e2e/flask/multichain-api/password-locked.spec.ts new file mode 100644 index 000000000000..578c2d567913 --- /dev/null +++ b/test/e2e/flask/multichain-api/password-locked.spec.ts @@ -0,0 +1,189 @@ +import { strict as assert } from 'assert'; +import { + ACCOUNT_1, + WALLET_PASSWORD, + WINDOW_TITLES, + withFixtures, +} from '../../helpers'; +import { Driver } from '../../webdriver/driver'; +import FixtureBuilder from '../../fixture-builder'; +import { + DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, + escapeColon, + type FixtureCallbackArgs, + getExpectedSessionScope, + getSessionScopes, + openMultichainDappAndConnectWalletWithExternallyConnectable, + passwordLockMetamaskExtension, +} from './testHelpers'; + +describe("A dapp is connected with account and chain permissions previously granted via `wallet_createSession`, user's extension becomes password locked", function () { + describe('the dapp sends a request through the Multichain API that requires user confirmation on the permitted account', function () { + it('should prompts the user to unlock MetaMask before showing the request confirmation', async function () { + await withFixtures( + { + title: this.test?.fullTitle(), + fixtures: new FixtureBuilder() + .withNetworkControllerTripleGanache() + .withPermissionControllerConnectedToMultichainTestDapp() + .build(), + ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, + }, + async ({ driver, extensionId }: FixtureCallbackArgs) => { + await openMultichainDappAndConnectWalletWithExternallyConnectable( + driver, + extensionId, + ); + await passwordLockMetamaskExtension(driver); + await driver.switchToWindowWithTitle( + WINDOW_TITLES.MultichainTestDApp, + ); + + await driver.clickElementSafe( + '[data-testid="eip155:1337-eth_sendTransaction-option"]', + ); + await driver.clickElement( + '[data-testid="invoke-method-eip155:1337-btn"]', + ); + + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + + const unlockExtensionPageWebElement0 = await driver.findElement( + '[data-testid="unlock-page"]', + ); + + assert.ok( + unlockExtensionPageWebElement0, + 'Should prompt user to unlock Metamask Extension', + ); + + /** + * We unlock metamask extension to assert a transfer request is being made + */ + await driver.fill('[data-testid="unlock-password"]', WALLET_PASSWORD); + await driver.clickElementSafe('[data-testid="unlock-submit"]'); + + const transferRequestWebElement = await driver.findElement({ + text: 'Transfer request', + type: 'h3', + }); + + assert.ok( + transferRequestWebElement, + 'Should be attempting to make via wallet extension transfer', + ); + + await driver.clickElementSafe( + '[data-testid="confirm-footer-cancel-button"]', + ); + + /** + * We lock extension again to repeat action and assertion for `wallet_addEthereumChain` + */ + await passwordLockMetamaskExtension(driver); + + await driver.switchToWindowWithTitle( + WINDOW_TITLES.MultichainTestDApp, + ); + + await driver.clickElementSafe( + '[data-testid="wallet:eip155-wallet_addEthereumChain-option"]', + ); + await driver.clickElement( + '[data-testid="invoke-method-wallet:eip155-btn"]', + ); + + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + + const unlockExtensionPageWebElement1 = await driver.findElement( + '[data-testid="unlock-page"]', + ); + + assert.ok( + unlockExtensionPageWebElement1, + 'Should prompt user to unlock Metamask Extension', + ); + + /** + * We unlock metamask extension to assert a request for adding chain is being made + */ + await driver.fill('[data-testid="unlock-password"]', WALLET_PASSWORD); + await driver.clickElementSafe('[data-testid="unlock-submit"]'); + + const addChainWebElement = await driver.findElement({ + text: 'Add Gnosis', + type: 'h3', + }); + + assert.ok( + addChainWebElement, + 'Should be attempting to add Gnosis Chain', + ); + }, + ); + }); + }); + + describe('the dapp sends requests through the Multichain API that do NOT require user confirmation', function () { + const SCOPE = 'eip155:1337'; + const CHAIN_ID = '0x539'; + it('should handle the requests without prompting the user to unlock the wallet', async function () { + await withFixtures( + { + title: this.test?.fullTitle(), + fixtures: new FixtureBuilder() + .withNetworkControllerTripleGanache() + .withPermissionControllerConnectedToMultichainTestDapp() + .build(), + ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, + }, + async ({ + driver, + extensionId, + }: { + driver: Driver; + extensionId: string; + }) => { + await openMultichainDappAndConnectWalletWithExternallyConnectable( + driver, + extensionId, + ); + await passwordLockMetamaskExtension(driver); + + await driver.switchToWindowWithTitle( + WINDOW_TITLES.MultichainTestDApp, + ); + + const parsedResult = await getSessionScopes(driver); + const sessionScope = parsedResult.sessionScopes[SCOPE]; + const expectedSessionScope = getExpectedSessionScope(SCOPE, [ + ACCOUNT_1, + ]); + + await driver.clickElementSafe( + `[data-testid="${SCOPE}-eth_chainId-option"]`, + ); + await driver.clickElementSafe( + `[data-testid="invoke-method-${SCOPE}-btn"]`, + ); + const chainIdResultWebElement = await driver.findElement( + `#invoke-method-${escapeColon(SCOPE)}-eth_chainId-result-0`, + ); + const chainId = await chainIdResultWebElement.getText(); + + assert.deepStrictEqual( + sessionScope, + expectedSessionScope, + `Should receive result that specifies expected session scopes for ${SCOPE}`, + ); + + assert.deepStrictEqual( + chainId, + `"${CHAIN_ID}"`, + 'Should get expected result from calling eth_chainId', + ); + }, + ); + }); + }); +}); diff --git a/test/e2e/flask/multichain-api/testHelpers.ts b/test/e2e/flask/multichain-api/testHelpers.ts index 76c261caccc0..1128a48fa0cf 100644 --- a/test/e2e/flask/multichain-api/testHelpers.ts +++ b/test/e2e/flask/multichain-api/testHelpers.ts @@ -16,6 +16,8 @@ import { } from '../../helpers'; import { Driver } from '../../webdriver/driver'; +export type FixtureCallbackArgs = { driver: Driver; extensionId: string }; + /** * Default options for setting up Multichain E2E test environment */ @@ -197,6 +199,19 @@ export const updateNetworkCheckboxes = async ( await driver.clickElement({ text: 'Update', tag: 'button' }); }; +/** + * Password locks user's metamask extension. + * + * @param driver - E2E test driver {@link Driver}, wrapping the Selenium WebDriver. + */ +export const passwordLockMetamaskExtension = async ( + driver: Driver, +): Promise => { + await driver.switchToWindowWithTitle(WINDOW_TITLES.ExtensionInFullScreenView); + await driver.clickElementSafe('[data-testid="account-options-menu-button"]'); + await driver.clickElementSafe('[data-testid="global-menu-lock"]'); +}; + /** * Sometimes we need to escape colon character when using {@link Driver.findElement}, otherwise selenium will treat this as an invalid selector. * diff --git a/test/e2e/flask/multichain-api/wallet_createSession.spec.ts b/test/e2e/flask/multichain-api/wallet_createSession.spec.ts index 790931e962ab..33a282d73759 100644 --- a/test/e2e/flask/multichain-api/wallet_createSession.spec.ts +++ b/test/e2e/flask/multichain-api/wallet_createSession.spec.ts @@ -8,7 +8,6 @@ import { ACCOUNT_1, ACCOUNT_2, } from '../../helpers'; -import { Driver } from '../../webdriver/driver'; import FixtureBuilder from '../../fixture-builder'; import { initCreateSessionScopes, @@ -18,6 +17,7 @@ import { getExpectedSessionScope, addAccountInWalletAndAuthorize, updateNetworkCheckboxes, + type FixtureCallbackArgs, } from './testHelpers'; describe('Multichain API', function () { @@ -31,13 +31,7 @@ describe('Multichain API', function () { .build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { const scopesToIgnore = ['eip155:1338', 'eip155:1000']; await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, @@ -77,13 +71,7 @@ describe('Multichain API', function () { .build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { const REQUEST_SCOPE = 'eip155:1337'; /** * check {@link FixtureBuilder.withTrezorAccount} for second injected account address. @@ -136,13 +124,7 @@ describe('Multichain API', function () { fixtures: new FixtureBuilder().withPopularNetworks().build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { const requestScopesToNetworkMap = { 'eip155:1': 'Ethereum Mainnet', 'eip155:59141': 'Linea Sepolia', @@ -204,13 +186,7 @@ describe('Multichain API', function () { .build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, extensionId, @@ -259,13 +235,7 @@ describe('Multichain API', function () { fixtures: new FixtureBuilder().build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, extensionId, @@ -304,13 +274,7 @@ describe('Multichain API', function () { .build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, extensionId, @@ -346,13 +310,7 @@ describe('Multichain API', function () { fixtures: new FixtureBuilder().build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, extensionId, @@ -400,7 +358,7 @@ describe('Multichain API', function () { title: this.test?.fullTitle(), fixtures: new FixtureBuilder() .withNetworkControllerTripleGanache() - .withPermissionControllerConnectedToTestDappMultichainWithTwoAccounts( + .withPermissionControllerConnectedToMultichainTestDappWithTwoAccounts( { scopes: OLD_SCOPES, }, @@ -409,13 +367,7 @@ describe('Multichain API', function () { .build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, extensionId, diff --git a/test/e2e/flask/multichain-api/wallet_getSession.spec.ts b/test/e2e/flask/multichain-api/wallet_getSession.spec.ts index c4c1da5f7a53..065829eb48be 100644 --- a/test/e2e/flask/multichain-api/wallet_getSession.spec.ts +++ b/test/e2e/flask/multichain-api/wallet_getSession.spec.ts @@ -1,6 +1,5 @@ import { strict as assert } from 'assert'; import { withFixtures } from '../../helpers'; -import { Driver } from '../../webdriver/driver'; import FixtureBuilder from '../../fixture-builder'; import { DEFAULT_FIXTURE_ACCOUNT } from '../../constants'; import { @@ -8,6 +7,7 @@ import { getExpectedSessionScope, getSessionScopes, openMultichainDappAndConnectWalletWithExternallyConnectable, + type FixtureCallbackArgs, } from './testHelpers'; describe('Multichain API', function () { @@ -19,13 +19,7 @@ describe('Multichain API', function () { fixtures: new FixtureBuilder().withPopularNetworks().build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, extensionId, @@ -53,13 +47,7 @@ describe('Multichain API', function () { .build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { /** * check {@link FixtureBuilder.withPermissionControllerConnectedToTestDapp} for default scopes returned */ diff --git a/test/e2e/flask/multichain-api/wallet_invokeMethod.spec.ts b/test/e2e/flask/multichain-api/wallet_invokeMethod.spec.ts index 9d8e19753221..172f029ac463 100644 --- a/test/e2e/flask/multichain-api/wallet_invokeMethod.spec.ts +++ b/test/e2e/flask/multichain-api/wallet_invokeMethod.spec.ts @@ -7,7 +7,6 @@ import { WINDOW_TITLES, withFixtures, } from '../../helpers'; -import { Driver } from '../../webdriver/driver'; import FixtureBuilder from '../../fixture-builder'; import { DEFAULT_GANACHE_ETH_BALANCE_DEC } from '../../constants'; import { @@ -16,6 +15,7 @@ import { openMultichainDappAndConnectWalletWithExternallyConnectable, addAccountInWalletAndAuthorize, escapeColon, + type FixtureCallbackArgs, } from './testHelpers'; describe('Multichain API', function () { @@ -36,13 +36,7 @@ describe('Multichain API', function () { .build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, extensionId, @@ -105,13 +99,7 @@ describe('Multichain API', function () { .build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, extensionId, @@ -176,13 +164,7 @@ describe('Multichain API', function () { .build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, extensionId, diff --git a/test/e2e/flask/multichain-api/wallet_notify.spec.ts b/test/e2e/flask/multichain-api/wallet_notify.spec.ts index d640c0f1ff54..e0d8e699d916 100644 --- a/test/e2e/flask/multichain-api/wallet_notify.spec.ts +++ b/test/e2e/flask/multichain-api/wallet_notify.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; import { withFixtures } from '../../helpers'; -import { Driver } from '../../webdriver/driver'; import FixtureBuilder from '../../fixture-builder'; import { DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, + type FixtureCallbackArgs, openMultichainDappAndConnectWalletWithExternallyConnectable, } from './testHelpers'; @@ -13,17 +13,11 @@ describe('Calling `eth_subscribe` on a particular network event', function () { { title: this.test?.fullTitle(), fixtures: new FixtureBuilder() - .withPermissionControllerConnectedToTestDappMultichain() + .withPermissionControllerConnectedToMultichainTestDapp() .build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, extensionId, diff --git a/test/e2e/flask/multichain-api/wallet_revokeSession.spec.ts b/test/e2e/flask/multichain-api/wallet_revokeSession.spec.ts index 1793f0e30f83..dcef54de2cd2 100644 --- a/test/e2e/flask/multichain-api/wallet_revokeSession.spec.ts +++ b/test/e2e/flask/multichain-api/wallet_revokeSession.spec.ts @@ -7,7 +7,6 @@ import { WINDOW_TITLES, withFixtures, } from '../../helpers'; -import { Driver } from '../../webdriver/driver'; import FixtureBuilder from '../../fixture-builder'; import { initCreateSessionScopes, @@ -15,6 +14,7 @@ import { openMultichainDappAndConnectWalletWithExternallyConnectable, addAccountInWalletAndAuthorize, getSessionScopes, + type FixtureCallbackArgs, } from './testHelpers'; describe('Initializing a session w/ several scopes and accounts, then calling `wallet_revokeSession`', function () { @@ -29,13 +29,7 @@ describe('Initializing a session w/ several scopes and accounts, then calling `w .build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, extensionId, @@ -82,13 +76,7 @@ describe('Initializing a session w/ several scopes and accounts, then calling `w .build(), ...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS, }, - async ({ - driver, - extensionId, - }: { - driver: Driver; - extensionId: string; - }) => { + async ({ driver, extensionId }: FixtureCallbackArgs) => { await openMultichainDappAndConnectWalletWithExternallyConnectable( driver, extensionId, diff --git a/test/e2e/run-api-specs-multichain.ts b/test/e2e/run-api-specs-multichain.ts index 39a73069e398..155c62e16274 100644 --- a/test/e2e/run-api-specs-multichain.ts +++ b/test/e2e/run-api-specs-multichain.ts @@ -289,7 +289,7 @@ async function main() { { dapp: true, fixtures: new FixtureBuilder() - .withPermissionControllerConnectedToTestDappMultichain() + .withPermissionControllerConnectedToMultichainTestDapp() .build(), disableGanache: true, title: 'api-specs-multichain coverage (wallet_invokeMethod)',