diff --git a/package.json b/package.json index 1672e6845873..921472a1c27e 100644 --- a/package.json +++ b/package.json @@ -466,7 +466,7 @@ "@metamask/phishing-warning": "^4.1.0", "@metamask/preferences-controller": "^13.0.2", "@metamask/test-bundler": "^1.0.0", - "@metamask/test-dapp": "8.7.0", + "@metamask/test-dapp": "8.13.0", "@octokit/core": "^3.6.0", "@open-rpc/meta-schema": "^1.14.6", "@open-rpc/mock-server": "^1.7.5", diff --git a/privacy-snapshot.json b/privacy-snapshot.json index 589504ea2cc7..6e041ea3d71b 100644 --- a/privacy-snapshot.json +++ b/privacy-snapshot.json @@ -32,6 +32,7 @@ "localhost:8000", "localhost:8545", "mainnet.infura.io", + "metamask-sdk.api.cx.metamask.io", "metamask.eth", "metamask.github.io", "metametrics.metamask.test", diff --git a/test/e2e/tests/confirmations/signatures/nft-permit.spec.ts b/test/e2e/tests/confirmations/signatures/nft-permit.spec.ts new file mode 100644 index 000000000000..383a3bd6b924 --- /dev/null +++ b/test/e2e/tests/confirmations/signatures/nft-permit.spec.ts @@ -0,0 +1,187 @@ +import { strict as assert } from 'assert'; +import { TransactionEnvelopeType } from '@metamask/transaction-controller'; +import { Suite } from 'mocha'; +import { MockedEndpoint } from 'mockttp'; +import { DAPP_HOST_ADDRESS, WINDOW_TITLES } from '../../../helpers'; +import { Ganache } from '../../../seeder/ganache'; +import { Driver } from '../../../webdriver/driver'; +import { + mockSignatureApproved, + mockSignatureRejected, + scrollAndConfirmAndAssertConfirm, + withRedesignConfirmationFixtures, +} from '../helpers'; +import { TestSuiteArguments } from '../transactions/shared'; +import { + assertAccountDetailsMetrics, + assertPastedAddress, + assertSignatureConfirmedMetrics, + assertSignatureRejectedMetrics, + clickHeaderInfoBtn, + copyAddressAndPasteWalletAddress, + openDappAndTriggerDeploy, + SignatureType, + triggerSignature, +} from './signature-helpers'; + +describe('Confirmation Signature - NFT Permit @no-mmi', function (this: Suite) { + it('initiates and confirms and emits the correct events', async function () { + await withRedesignConfirmationFixtures( + this.test?.fullTitle(), + TransactionEnvelopeType.legacy, + async ({ + driver, + ganacheServer, + mockedEndpoint: mockedEndpoints, + }: TestSuiteArguments) => { + const addresses = await (ganacheServer as Ganache).getAccounts(); + const publicAddress = addresses?.[0] as string; + + await openDappAndTriggerDeploy(driver); + await driver.delay(1000); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + await driver.clickElement('[data-testid="confirm-footer-button"]'); + + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); + await driver.delay(1000); + await triggerSignature(driver, SignatureType.NFTPermit); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + + await clickHeaderInfoBtn(driver); + await copyAddressAndPasteWalletAddress(driver); + await assertPastedAddress(driver); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + + await assertInfoValues(driver); + await scrollAndConfirmAndAssertConfirm(driver); + await driver.delay(1000); + + await assertAccountDetailsMetrics( + driver, + mockedEndpoints as MockedEndpoint[], + 'eth_signTypedData_v4', + ); + + await assertSignatureConfirmedMetrics({ + driver, + mockedEndpoints: mockedEndpoints as MockedEndpoint[], + signatureType: 'eth_signTypedData_v4', + primaryType: 'Permit', + uiCustomizations: ['redesigned_confirmation', 'permit'], + }); + + await assertVerifiedResults(driver, publicAddress); + }, + mockSignatureApproved, + ); + }); + + it('initiates and rejects and emits the correct events', async function () { + await withRedesignConfirmationFixtures( + this.test?.fullTitle(), + TransactionEnvelopeType.legacy, + async ({ + driver, + mockedEndpoint: mockedEndpoints, + }: TestSuiteArguments) => { + await openDappAndTriggerDeploy(driver); + await driver.delay(1000); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + await driver.clickElement('[data-testid="confirm-footer-button"]'); + + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); + await driver.delay(1000); + await triggerSignature(driver, SignatureType.NFTPermit); + + await driver.clickElementAndWaitForWindowToClose( + '[data-testid="confirm-footer-cancel-button"]', + ); + + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); + + await driver.waitForSelector({ + tag: 'span', + text: 'Error: User rejected the request.', + }); + + await assertSignatureRejectedMetrics({ + driver, + mockedEndpoints: mockedEndpoints as MockedEndpoint[], + signatureType: 'eth_signTypedData_v4', + primaryType: 'Permit', + uiCustomizations: ['redesigned_confirmation', 'permit'], + location: 'confirmation', + }); + }, + mockSignatureRejected, + ); + }); +}); + +async function assertInfoValues(driver: Driver) { + await driver.clickElement('[data-testid="sectionCollapseButton"]'); + const origin = driver.findElement({ text: DAPP_HOST_ADDRESS }); + const contractPetName = driver.findElement({ + css: '.name__value', + text: '0x581c3...45947', + }); + + const title = driver.findElement({ text: 'Withdrawal request' }); + const description = driver.findElement({ + text: 'This site wants permission to withdraw your NFTs', + }); + const primaryType = driver.findElement({ text: 'Permit' }); + const spender = driver.findElement({ + css: '.name__value', + text: '0x581c3...45947', + }); + const tokenId = driver.findElement({ text: '3606393' }); + const nonce = driver.findElement({ text: '0' }); + const deadline = driver.findElement({ text: '23 December 2024, 23:03' }); + + assert.ok(await origin, 'origin'); + assert.ok(await contractPetName, 'contractPetName'); + assert.ok(await title, 'title'); + assert.ok(await description, 'description'); + assert.ok(await primaryType, 'primaryType'); + assert.ok(await spender, 'spender'); + assert.ok(await tokenId, 'tokenId'); + assert.ok(await nonce, 'nonce'); + assert.ok(await deadline, 'deadline'); +} + +async function assertVerifiedResults(driver: Driver, publicAddress: string) { + await driver.waitUntilXWindowHandles(2); + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); + await driver.clickElement('#sign721PermitVerify'); + + await driver.waitForSelector({ + css: '#sign721PermitVerifyResult', + text: publicAddress, + }); + + await driver.waitForSelector({ + css: '#sign721PermitResult', + text: '0x572bc6300f6aa669e85e0a7792bc0b0803fb70c3c492226b30007ff7030b03600e390ef295a5a525d19f444943ae82697f0e5b5b0d77cc382cb2ea9486ec27801c', + }); + + await driver.waitForSelector({ + css: '#sign721PermitResultR', + text: 'r: 0x572bc6300f6aa669e85e0a7792bc0b0803fb70c3c492226b30007ff7030b0360', + }); + + await driver.waitForSelector({ + css: '#sign721PermitResultS', + text: 's: 0x0e390ef295a5a525d19f444943ae82697f0e5b5b0d77cc382cb2ea9486ec2780', + }); + + await driver.waitForSelector({ + css: '#sign721PermitResultV', + text: 'v: 28', + }); + + await driver.waitForSelector({ + css: '#sign721PermitVerifyResult', + text: publicAddress, + }); +} diff --git a/test/e2e/tests/confirmations/signatures/signature-helpers.ts b/test/e2e/tests/confirmations/signatures/signature-helpers.ts index 9b87e5b4e9cc..5242be3f3c20 100644 --- a/test/e2e/tests/confirmations/signatures/signature-helpers.ts +++ b/test/e2e/tests/confirmations/signatures/signature-helpers.ts @@ -14,6 +14,7 @@ export const WALLET_ETH_BALANCE = '25'; export enum SignatureType { PersonalSign = '#personalSign', Permit = '#signPermit', + NFTPermit = '#sign721Permit', SignTypedDataV3 = '#signTypedDataV3', SignTypedDataV4 = '#signTypedDataV4', SignTypedData = '#signTypedData', @@ -240,12 +241,23 @@ export async function assertPastedAddress(driver: Driver) { assert.equal(await formFieldEl.getAttribute('value'), WALLET_ADDRESS); } +export async function triggerSignature(driver: Driver, type: string) { + await driver.clickElement(type); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); +} + export async function openDappAndTriggerSignature( driver: Driver, type: string, ) { await unlockWallet(driver); await openDapp(driver); - await driver.clickElement(type); + await triggerSignature(driver, type); +} + +export async function openDappAndTriggerDeploy(driver: Driver) { + await unlockWallet(driver); + await openDapp(driver); + await driver.clickElement('#deployNFTsButton'); await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); } diff --git a/test/e2e/tests/tokens/add-multiple-tokens.spec.js b/test/e2e/tests/tokens/add-multiple-tokens.spec.js index 490460e770cb..8be2a430b622 100644 --- a/test/e2e/tests/tokens/add-multiple-tokens.spec.js +++ b/test/e2e/tests/tokens/add-multiple-tokens.spec.js @@ -28,6 +28,11 @@ describe('Multiple ERC20 Watch Asset', function () { await openDapp(driver, undefined, DAPP_URL); // Create Token 1 + const createToken = await driver.findElement({ + text: 'Create Token', + tag: 'button', + }); + await driver.scrollToElement(createToken); await driver.clickElement({ text: 'Create Token', tag: 'button' }); await switchToNotificationWindow(driver); await driver.findClickableElement({ text: 'Confirm', tag: 'button' }); @@ -37,7 +42,7 @@ describe('Multiple ERC20 Watch Asset', function () { await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); await driver.wait(async () => { const tokenAddressesElement = await driver.findElement( - '#tokenAddresses', + '#erc20TokenAddresses', ); const tokenAddresses = await tokenAddressesElement.getText(); return tokenAddresses !== ''; @@ -53,7 +58,7 @@ describe('Multiple ERC20 Watch Asset', function () { await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); await driver.wait(async () => { const tokenAddressesElement = await driver.findElement( - '#tokenAddresses', + '#erc20TokenAddresses', ); const tokenAddresses = await tokenAddressesElement.getText(); return tokenAddresses.split(',').length === 2; @@ -69,7 +74,7 @@ describe('Multiple ERC20 Watch Asset', function () { await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); await driver.wait(async () => { const tokenAddressesElement = await driver.findElement( - '#tokenAddresses', + '#erc20TokenAddresses', ); const tokenAddresses = await tokenAddressesElement.getText(); return tokenAddresses.split(',').length === 3; diff --git a/ui/pages/confirmations/components/confirm/info/base-transaction-info/base-transaction-info.tsx b/ui/pages/confirmations/components/confirm/info/base-transaction-info/base-transaction-info.tsx index 08329536b524..23629ee5096c 100644 --- a/ui/pages/confirmations/components/confirm/info/base-transaction-info/base-transaction-info.tsx +++ b/ui/pages/confirmations/components/confirm/info/base-transaction-info/base-transaction-info.tsx @@ -22,6 +22,7 @@ const BaseTransactionInfo = () => { diff --git a/ui/pages/confirmations/components/confirm/info/native-transfer/native-transfer.tsx b/ui/pages/confirmations/components/confirm/info/native-transfer/native-transfer.tsx index a2dd3ceaaa05..c098936989dd 100644 --- a/ui/pages/confirmations/components/confirm/info/native-transfer/native-transfer.tsx +++ b/ui/pages/confirmations/components/confirm/info/native-transfer/native-transfer.tsx @@ -24,6 +24,7 @@ const NativeTransferInfo = () => { )} diff --git a/ui/pages/confirmations/components/confirm/info/nft-token-transfer/nft-token-transfer.tsx b/ui/pages/confirmations/components/confirm/info/nft-token-transfer/nft-token-transfer.tsx index b5d579994ef9..113920a6aec2 100644 --- a/ui/pages/confirmations/components/confirm/info/nft-token-transfer/nft-token-transfer.tsx +++ b/ui/pages/confirmations/components/confirm/info/nft-token-transfer/nft-token-transfer.tsx @@ -24,6 +24,7 @@ const NFTTokenTransferInfo = () => { )} diff --git a/ui/pages/confirmations/components/confirm/info/token-transfer/token-transfer.tsx b/ui/pages/confirmations/components/confirm/info/token-transfer/token-transfer.tsx index df1136ec5213..50e9d85936f0 100644 --- a/ui/pages/confirmations/components/confirm/info/token-transfer/token-transfer.tsx +++ b/ui/pages/confirmations/components/confirm/info/token-transfer/token-transfer.tsx @@ -24,6 +24,7 @@ const TokenTransferInfo = () => { )} diff --git a/yarn.lock b/yarn.lock index 9ac1b7409679..4c3305e98b13 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6386,10 +6386,10 @@ __metadata: languageName: node linkType: hard -"@metamask/test-dapp@npm:8.7.0": - version: 8.7.0 - resolution: "@metamask/test-dapp@npm:8.7.0" - checksum: 10/c2559179d3372e5fc8d67a60c1e4056fad9809486eaff6a2aa9c351a2a613eeecc15885a5fd9b71b8f4139058fe168abeac06bd6bdb6d4a47fe0b9b4146923ab +"@metamask/test-dapp@npm:8.13.0": + version: 8.13.0 + resolution: "@metamask/test-dapp@npm:8.13.0" + checksum: 10/b588e562ce81d94e22e8c19b6b160b6dc1c5f68314edaeeb3c886a0676d4bd21205c741d039a1a8ad2dfc1e87109239d18da17c322fbaa99f527b543b0032786 languageName: node linkType: hard @@ -26470,7 +26470,7 @@ __metadata: "@metamask/snaps-sdk": "npm:^6.10.0" "@metamask/snaps-utils": "npm:^8.5.1" "@metamask/test-bundler": "npm:^1.0.0" - "@metamask/test-dapp": "npm:8.7.0" + "@metamask/test-dapp": "npm:8.13.0" "@metamask/transaction-controller": "npm:^38.1.0" "@metamask/user-operation-controller": "npm:^13.0.0" "@metamask/utils": "npm:^9.3.0"