Skip to content

Commit

Permalink
test: add wallet_invokeMethod end to end test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
ffmcgee725 committed Jan 8, 2025
1 parent 3f87444 commit 31f7406
Show file tree
Hide file tree
Showing 5 changed files with 298 additions and 27 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@
"@metamask/preferences-controller": "^15.0.1",
"@metamask/test-bundler": "^1.0.0",
"@metamask/test-dapp": "8.13.0",
"@metamask/test-dapp-multichain": "^0.5.0",
"@metamask/test-dapp-multichain": "^0.6.0",
"@octokit/core": "^3.6.0",
"@open-rpc/meta-schema": "^1.14.6",
"@open-rpc/mock-server": "^1.7.5",
Expand Down
30 changes: 13 additions & 17 deletions test/e2e/flask/multichain-api/create-session.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { strict as assert } from 'assert';
import { By } from 'selenium-webdriver';
import { largeDelayMs, WINDOW_TITLES, withFixtures } from '../../helpers';
import {
largeDelayMs,
WINDOW_TITLES,
withFixtures,
ACCOUNT_1,
ACCOUNT_2,
} from '../../helpers';
import { Driver } from '../../webdriver/driver';
import FixtureBuilder from '../../fixture-builder';
import { DEFAULT_FIXTURE_ACCOUNT } from '../../constants';
import {
initCreateSessionScopes,
DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS,
Expand All @@ -15,11 +20,6 @@ import {
} from './testHelpers';

describe('Multichain API', function () {
/**
* check {@link FixtureBuilder.withPreferencesControllerAdditionalAccountIdentities} for second injected account address.
*/
const SECOND_INJECTED_ACCOUNT = '0x09781764c08de8ca82e156bbf156a3ca217c7950';

describe('Connect wallet to the multichain dapp via `externally_connectable`, call `wallet_createSession` with requested EVM scope that does NOT match one of the user’s enabled networks', function () {
it("the specified EVM scopes that do not match the user's configured networks should be treated as if they were not requested", async function () {
await withFixtures(
Expand Down Expand Up @@ -219,7 +219,7 @@ describe('Multichain API', function () {
await initCreateSessionScopes(
driver,
['eip155:1337', 'eip155:1338'],
[DEFAULT_FIXTURE_ACCOUNT],
[ACCOUNT_1],
);

await addAccountInWalletAndAuthorize(driver);
Expand All @@ -241,11 +241,9 @@ describe('Multichain API', function () {

assert.deepEqual(
getSessionScopesResult.sessionScopes['eip155:1337'].accounts,
getExpectedSessionScope('eip155:1337', [
DEFAULT_FIXTURE_ACCOUNT,
SECOND_INJECTED_ACCOUNT,
]).accounts,
`Should add account ${SECOND_INJECTED_ACCOUNT} to scope`,
getExpectedSessionScope('eip155:1337', [ACCOUNT_1, ACCOUNT_2])
.accounts,
`Should add account ${ACCOUNT_2} to scope`,
);
},
);
Expand Down Expand Up @@ -331,10 +329,8 @@ describe('Multichain API', function () {

assert.deepEqual(
getSessionScopesResult.sessionScopes['eip155:1'].accounts,
getExpectedSessionScope('eip155:1', [
DEFAULT_FIXTURE_ACCOUNT,
SECOND_INJECTED_ACCOUNT,
]).accounts,
getExpectedSessionScope('eip155:1', [ACCOUNT_1, ACCOUNT_2])
.accounts,
'The dapp should receive a response that includes permissions for the accounts that were selected for sharing',
);
},
Expand Down
275 changes: 275 additions & 0 deletions test/e2e/flask/multichain-api/invoke-method.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
import { strict as assert } from 'assert';
import {
ACCOUNT_1,
ACCOUNT_2,
largeDelayMs,
WINDOW_TITLES,
withFixtures,
} from '../../helpers';
import { Driver } from '../../webdriver/driver';
import FixtureBuilder from '../../fixture-builder';
import {
initCreateSessionScopes,
DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS,
openMultichainDappAndConnectWalletWithExternallyConnectable,
addAccountInWalletAndAuthorize,
} from './testHelpers';

describe('Multichain API', function () {
const GANACHE_SCOPES = ['eip155:1337', 'eip155:1338', 'eip155:1000'];
const ACCOUNTS = [ACCOUNT_1, ACCOUNT_2];
const DEFAULT_INITIAL_BALANCE_HEX = '0x15af1d78b58c40000';

describe('Calling `wallet_invokeMethod` on the same dapp across three different connected chains', function () {
describe('Read operations: calling different methods on each connected scope', function () {
it('Should match selected method to the expected output', async function () {
await withFixtures(
{
title: this.test?.fullTitle(),
fixtures: new FixtureBuilder()
.withNetworkControllerTripleGanache()
.build(),
...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS,
},
async ({
driver,
extensionId,
}: {
driver: Driver;
extensionId: string;
}) => {
await openMultichainDappAndConnectWalletWithExternallyConnectable(
driver,
extensionId,
);
await initCreateSessionScopes(driver, GANACHE_SCOPES, ACCOUNTS);
await addAccountInWalletAndAuthorize(driver);
await driver.clickElement({ text: 'Connect', tag: 'button' });
await driver.delay(largeDelayMs);
await driver.switchToWindowWithTitle(
WINDOW_TITLES.MultichainTestDApp,
);

const TEST_METHODS = {
[GANACHE_SCOPES[0]]: 'eth_chainId',
[GANACHE_SCOPES[1]]: 'eth_getBalance',
[GANACHE_SCOPES[2]]: 'eth_gasPrice',
};
const EXPECTED_RESULTS = {
[GANACHE_SCOPES[0]]: '0x539',
[GANACHE_SCOPES[1]]: DEFAULT_INITIAL_BALANCE_HEX,
[GANACHE_SCOPES[2]]: '0x77359400',
};

const scopeCards = await driver.findElements('.scope-card');

for (const i of scopeCards.keys()) {
const scope = GANACHE_SCOPES[i];
const invokeMethod = TEST_METHODS[GANACHE_SCOPES[i]];
await driver.clickElementSafe(
`[data-testid="${scope}-${invokeMethod}-option"]`,
);

await driver.clickElementSafe(
`[data-testid="invoke-method-${scope}-btn"]`,
);

/**
* We need to escape colon character on the scope, otherwise selenium will treat this as an invalid selector
*/
const resultElement = await driver.findElement(
`#invoke-method-${scope.replace(
':',
'\\:',
)}-${invokeMethod}-result-0`,
);

const result = await resultElement.getText();

assert.strictEqual(
result,
`"${EXPECTED_RESULTS[scope]}"`,
`${scope} method ${invokeMethod} expected "${EXPECTED_RESULTS[scope]}", got ${result} instead`,
);
}
},
);
});
});

describe('Write operations: calling `eth_sendTransaction` on each connected scope', function () {
const INDEX_FOR_ALTERNATE_ACCOUNT = 1;

it('should match chosen addresses in each chain to the selected address per scope in extension window', async function () {
await withFixtures(
{
title: this.test?.fullTitle(),
fixtures: new FixtureBuilder()
.withNetworkControllerTripleGanache()
.build(),
...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS,
},
async ({
driver,
extensionId,
}: {
driver: Driver;
extensionId: string;
}) => {
await openMultichainDappAndConnectWalletWithExternallyConnectable(
driver,
extensionId,
);
await initCreateSessionScopes(driver, GANACHE_SCOPES, ACCOUNTS);
await addAccountInWalletAndAuthorize(driver);
await driver.clickElement({ text: 'Connect', tag: 'button' });

await driver.delay(largeDelayMs);
await driver.switchToWindowWithTitle(
WINDOW_TITLES.MultichainTestDApp,
);

const scopeCards = await driver.findElements('.scope-card');
for (const i of scopeCards.keys()) {
const scope = GANACHE_SCOPES[i];
await driver.clickElementSafe(
`[data-testid="${scope}-eth_sendTransaction-option"]`,
);

i === INDEX_FOR_ALTERNATE_ACCOUNT &&
(await driver.clickElementSafe(
`[data-testid="${scope}:${ACCOUNT_2}-option"]`,
));
}

await driver.clickElement({
text: 'Invoke All Selected Methods',
tag: 'button',
});

// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const i of GANACHE_SCOPES.keys()) {
await driver.delay(largeDelayMs);
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);

const accountWebElement = await driver.findElement(
'[data-testid="sender-address"]',
);
const accountText = await accountWebElement.getText();
const expectedAccount =
i === INDEX_FOR_ALTERNATE_ACCOUNT ? 'Account 2' : 'Account 1';

assert.strictEqual(
accountText,
expectedAccount,
`Should have ${expectedAccount} selected, got ${accountText}`,
);

await driver.clickElement({
text: 'Confirm',
tag: 'button',
});
}
},
);
});

it('should have less balance due to gas after transaction is sent', async function () {
await withFixtures(
{
title: this.test?.fullTitle(),
fixtures: new FixtureBuilder()
.withNetworkControllerTripleGanache()
.build(),
...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS,
},
async ({
driver,
extensionId,
}: {
driver: Driver;
extensionId: string;
}) => {
await openMultichainDappAndConnectWalletWithExternallyConnectable(
driver,
extensionId,
);
await initCreateSessionScopes(driver, GANACHE_SCOPES, ACCOUNTS);
await addAccountInWalletAndAuthorize(driver);
await driver.clickElement({ text: 'Connect', tag: 'button' });

await driver.delay(largeDelayMs);
await driver.switchToWindowWithTitle(
WINDOW_TITLES.MultichainTestDApp,
);

const scopeCards = await driver.findElements('.scope-card');

for (const i of scopeCards.keys()) {
const scope = GANACHE_SCOPES[i];
await driver.clickElementSafe(
`[data-testid="${scope}-eth_sendTransaction-option"]`,
);

i === INDEX_FOR_ALTERNATE_ACCOUNT &&
(await driver.clickElementSafe(
`[data-testid="${scope}:${ACCOUNT_2}-option"]`,
));
}

await driver.clickElement({
text: 'Invoke All Selected Methods',
tag: 'button',
});

// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const _ of GANACHE_SCOPES) {
await driver.delay(largeDelayMs);
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
await driver.clickElement({
text: 'Confirm',
tag: 'button',
});
}

await driver.delay(largeDelayMs);
await driver.switchToWindowWithTitle(
WINDOW_TITLES.MultichainTestDApp,
);

await driver.clickElementSafe({
text: 'Clear Results',
tag: 'button',
});

for (const i of scopeCards.keys()) {
const scope = GANACHE_SCOPES[i];
await driver.clickElementSafe(
`[data-testid="${scope}-eth_getBalance-option"]`,
);

await driver.delay(largeDelayMs);
await driver.clickElementSafe(
`[data-testid="invoke-method-${scope}-btn"]`,
);

const resultWebElement = await driver.findElement(
`#invoke-method-${scope.replace(
':',
'\\:',
)}-eth_getBalance-result-0`,
);
const currentBalance = await resultWebElement.getText();

assert.notStrictEqual(
currentBalance,
`"${DEFAULT_INITIAL_BALANCE_HEX}"`, // default initial hex balance
`${scope} scope balance should be different after eth_sendTransaction due to gas`,
);
}
},
);
});
});
});
});
8 changes: 4 additions & 4 deletions test/e2e/flask/multichain-api/testHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import {
} from '@metamask/multichain';
import {
DAPP_URL,
defaultGanacheOptions,
largeDelayMs,
multipleGanacheOptions,
openDapp,
regularDelayMs,
unlockWallet,
Expand All @@ -32,17 +32,17 @@ export const DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS = {
),
],
ganacheOptions: {
...defaultGanacheOptions,
...multipleGanacheOptions,
concurrent: [
{
port: 8546,
chainId: 1338,
ganacheOptions2: defaultGanacheOptions,
ganacheOptions2: multipleGanacheOptions,
},
{
port: 7777,
chainId: 1000,
ganacheOptions2: defaultGanacheOptions,
ganacheOptions2: multipleGanacheOptions,
},
],
},
Expand Down
Loading

0 comments on commit 31f7406

Please sign in to comment.