Skip to content

Commit

Permalink
from #24898
Browse files Browse the repository at this point in the history
  • Loading branch information
HowardBraham committed Jun 15, 2024
1 parent 513e8f2 commit 12f3dfa
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 42 deletions.
5 changes: 4 additions & 1 deletion test/e2e/tests/ppom/mocks/json-rpc-result.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
const MOCK_BLOCK_NUMBER = '0x1';

export type mockJsonRpcResultType = {
// TODO: Replace `any` with type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[methodName: string]: { [arbitraryVariantName: string]: any };
};

export const mockJsonRpcResult: mockJsonRpcResultType = {
eth_blockNumber: {
default: MOCK_BLOCK_NUMBER,
custom: '0x130E45F',
},

eth_estimateGas: {
Expand Down Expand Up @@ -387,4 +387,7 @@ export const mockJsonRpcResult: mockJsonRpcResultType = {
BUSD_STORAGE_2:
'0x000000000000000000000000137dcd97872de27a4d3bf36a4643c5e18fa40713',
},
net_version: {
default: '1',
},
};
198 changes: 177 additions & 21 deletions test/e2e/tests/settings/ipfs-ens-resolution.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,151 @@
const { buildWebDriver } = require('../../webdriver');
const { withFixtures, tinyDelayMs, unlockWallet } = require('../../helpers');
const {
defaultGanacheOptions,
tinyDelayMs,
unlockWallet,
withFixtures,
} = require('../../helpers');
const FixtureBuilder = require('../../fixture-builder');
const { mockServerJsonRpc } = require('../ppom/mocks/mock-server-json-rpc');

const BALANCE_CHECKER = '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39';
const ENS_PUBLIC_RESOLVER = '0x4976fb03c32e5b8cfe2b6ccb31c09ba78ebaba41';
const ENS_REGISTRY_WITH_FALLBACK = '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e';

async function mockInfura(mockServer) {
await mockServerJsonRpc(mockServer, [
[
'eth_blockNumber',
{
methodResultVariant: 'custom',
},
],
['eth_estimateGas'],
['eth_feeHistory'],
['eth_gasPrice'],
['eth_getBalance'],
['eth_getBlockByNumber'],
['eth_getTransactionCount'],
['net_version'],
]);

// Resolver Call
await mockServer
.forPost()
.withJsonBodyIncluding({
method: 'eth_call',
params: [
{
to: ENS_REGISTRY_WITH_FALLBACK,
},
],
})
.thenCallback(async (req) => {
return {
statusCode: 200,
json: {
jsonrpc: '2.0',
id: (await req.body.getJson()).id,
result:
'0x0000000000000000000000004976fb03c32e5b8cfe2b6ccb31c09ba78ebaba41',
},
};
});

// Supports Interface Call
await mockServer
.forPost()
.withJsonBodyIncluding({
method: 'eth_call',
params: [
{
data: '0x01ffc9a7bc1c58d100000000000000000000000000000000000000000000000000000000',
to: ENS_PUBLIC_RESOLVER,
},
],
})
.thenCallback(async (req) => {
return {
statusCode: 200,
json: {
jsonrpc: '2.0',
id: (await req.body.getJson()).id,
result:
'0x0000000000000000000000000000000000000000000000000000000000000001',
},
};
});

// Supports Interface Call
await mockServer
.forPost()
.withJsonBodyIncluding({
method: 'eth_call',
params: [
{
data: '0x01ffc9a7d8389dc500000000000000000000000000000000000000000000000000000000',
to: ENS_PUBLIC_RESOLVER,
},
],
})
.thenCallback(async (req) => {
return {
statusCode: 200,
json: {
jsonrpc: '2.0',
id: (await req.body.getJson()).id,
result:
'0x0000000000000000000000000000000000000000000000000000000000000000',
},
};
});

// Content Hash Call
await mockServer
.forPost()
.withJsonBodyIncluding({
method: 'eth_call',
params: [
{
data: '0xbc1c58d1e650784434622eeb4ffbbb3220ebb371e26ad1a77f388680d42d8b1624baa6df',
to: ENS_PUBLIC_RESOLVER,
},
],
})
.thenCallback(async (req) => {
return {
statusCode: 200,
json: {
jsonrpc: '2.0',
id: (await req.body.getJson()).id,
result:
'0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000',
},
};
});

// Token Balance Call
await mockServer
.forPost()
.withJsonBodyIncluding({
method: 'eth_call',
params: [
{
to: BALANCE_CHECKER,
},
],
})
.thenCallback(async (req) => {
return {
statusCode: 200,
json: {
jsonrpc: '2.0',
id: (await req.body.getJson()).id,
result:
'0x0000000000000000000000000000000000000000000000000000000000000000',
},
};
});
}

describe('Settings', function () {
const ENS_NAME = 'metamask.eth';
Expand All @@ -10,25 +155,36 @@ describe('Settings', function () {
it('Redirects to ENS domains when user inputs ENS into address bar', async function () {
// Using proxy port that doesn't resolve so that the browser can error out properly
// on the ".eth" hostname. The proxy does too much interference with 8000.
const { driver } = await buildWebDriver({ proxyUrl: '127.0.0.1:8001' });
await driver.navigate();

// The setting defaults to "on" so we can simply enter an ENS address
// into the address bar and listen for address change
try {
await driver.openNewPage(ENS_NAME_URL);
} catch (e) {
// Ignore ERR_PROXY_CONNECTION_FAILED error
// since all we care about is getting to the correct URL
}

// Ensure that the redirect to ENS Domains has happened
await driver.wait(async () => {
const currentUrl = await driver.getCurrentUrl();
return currentUrl === ENS_DESTINATION_URL;
}, tinyDelayMs);

await driver.quit();

await withFixtures(
{
fixtures: new FixtureBuilder().withNetworkControllerOnMainnet().build(),
ganacheOptions: defaultGanacheOptions,
title: this.test.title,
testSpecificMock: mockInfura,
driverOptions: {
proxyPort: '8001',
},
},
async ({ driver }) => {
await driver.navigate();

// The setting defaults to "on" so we can simply enter an ENS address
// into the address bar and listen for address change
try {
await driver.openNewPage(ENS_NAME_URL);
} catch (e) {
// Ignore ERR_PROXY_CONNECTION_FAILED error
// since all we care about is getting to the correct URL
}

// Ensure that the redirect to ENS Domains has happened
await driver.wait(async () => {
const currentUrl = await driver.getCurrentUrl();
return currentUrl === ENS_DESTINATION_URL;
}, tinyDelayMs);
},
);
});

it('Does not fetch ENS data for ENS Domain when ENS and IPFS switched off', async function () {
Expand Down
23 changes: 14 additions & 9 deletions test/e2e/webdriver/chrome.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
const { Builder } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const { ThenableWebDriver } = require('selenium-webdriver'); // eslint-disable-line no-unused-vars -- this is imported for JSDoc
const { isHeadless } = require('../../helpers/env');

/**
* Proxy host to use for HTTPS requests
* Determine the appropriate proxy server value to use
*
* @type {string}
* @param {string|number} [proxyPort] - The proxy port to use
* @returns {string} The proxy server address
*/
const HTTPS_PROXY_HOST = `${
process.env.SELENIUM_HTTPS_PROXY || '127.0.0.1:8000'
}`;
function getProxyServer(proxyPort) {
const DEFAULT_PROXY_HOST = '127.0.0.1:8000';
const { SELENIUM_HTTPS_PROXY } = process.env;
if (proxyPort) {
return `127.0.0.1:${proxyPort}`;
}
return SELENIUM_HTTPS_PROXY || DEFAULT_PROXY_HOST;
}

/**
* A wrapper around a {@code WebDriver} instance exposing Chrome-specific functionality
*/
class ChromeDriver {
static async build({ openDevToolsForTabs, port }) {
static async build({ openDevToolsForTabs, port, proxyPort }) {
const args = [
`--proxy-server=${HTTPS_PROXY_HOST}`, // Set proxy in the way that doesn't interfere with Selenium Manager
`--proxy-server=${getProxyServer(proxyPort)}`, // Set proxy in the way that doesn't interfere with Selenium Manager
'--disable-features=OptimizationGuideModelDownloading,OptimizationHintsFetching,OptimizationTargetPrediction,OptimizationHints,NetworkTimeServiceQuerying', // Stop chrome from calling home so much (auto-downloads of AI models; time sync)
'--disable-component-update', // Stop chrome from calling home so much (auto-update)
'--disable-dev-shm-usage',
Expand All @@ -43,7 +48,7 @@ class ChromeDriver {
args.push('--disable-gpu');
}

if (isHeadless('SELENIUM')) {
if (process.env.SELENIUM_HEADLESS) {
// TODO: Remove notice and consider non-experimental when results are consistent
console.warn(
'*** Running e2e tests in headless mode is experimental and some tests are known to fail for unknown reasons',
Expand Down
29 changes: 20 additions & 9 deletions test/e2e/webdriver/firefox.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const {
} = require('selenium-webdriver');
const firefox = require('selenium-webdriver/firefox');
const { retry } = require('../../../development/lib/retry');
const { isHeadless } = require('../../helpers/env');

/**
* The prefix for temporary Firefox profiles. All Firefox profiles used for e2e tests
Expand All @@ -20,11 +19,20 @@ const { isHeadless } = require('../../helpers/env');
const TEMP_PROFILE_PATH_PREFIX = path.join(os.tmpdir(), 'MetaMask-Fx-Profile');

/**
* Proxy host to use for HTTPS requests
* Determine the appropriate proxy server value to use
*
* @param {string|number} [proxyPort] - The proxy port to use
* @returns {string} The proxy server URL
*/
const HTTPS_PROXY_HOST = new URL(
process.env.SELENIUM_HTTPS_PROXY || 'http://127.0.0.1:8000',
);
function getProxyServerURL(proxyPort) {
const DEFAULT_PROXY_HOST = 'http://127.0.0.1:8000';
const { SELENIUM_HTTPS_PROXY } = process.env;

if (proxyPort) {
return new URL(`http://127.0.0.1:${proxyPort}`);
}
return new URL(SELENIUM_HTTPS_PROXY || DEFAULT_PROXY_HOST);
}

/**
* A wrapper around a {@code WebDriver} instance exposing Firefox-specific functionality
Expand All @@ -36,18 +44,21 @@ class FirefoxDriver {
* @param {object} options - the options for the build
* @param options.responsive
* @param options.port
* @param options.proxyPort
* @returns {Promise<{driver: !ThenableWebDriver, extensionUrl: string, extensionId: string}>}
*/
static async build({ responsive, port }) {
static async build({ responsive, port, proxyPort }) {
const templateProfile = fs.mkdtempSync(TEMP_PROFILE_PATH_PREFIX);
const options = new firefox.Options().setProfile(templateProfile);

const proxyServerURL = getProxyServerURL(proxyPort);

// Set proxy in the way that doesn't interfere with Selenium Manager
options.setPreference('network.proxy.type', 1);
options.setPreference('network.proxy.ssl', HTTPS_PROXY_HOST.hostname);
options.setPreference('network.proxy.ssl', proxyServerURL.hostname);
options.setPreference(
'network.proxy.ssl_port',
parseInt(HTTPS_PROXY_HOST.port, 10),
parseInt(proxyServerURL.port, 10),
);

options.setAcceptInsecureCerts(true);
Expand All @@ -59,7 +70,7 @@ class FirefoxDriver {
if (process.env.CI === 'true') {
options.setBinary('/opt/firefox/firefox');
}
if (isHeadless('SELENIUM')) {
if (process.env.SELENIUM_HEADLESS) {
// TODO: Remove notice and consider non-experimental when results are consistent
console.warn(
'*** Running e2e tests in headless mode is experimental and some tests are known to fail for unknown reasons',
Expand Down
13 changes: 11 additions & 2 deletions test/e2e/webdriver/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,23 @@ const { Driver } = require('./driver');
const ChromeDriver = require('./chrome');
const FirefoxDriver = require('./firefox');

async function buildWebDriver({ openDevToolsForTabs, port, timeOut } = {}) {
async function buildWebDriver({
openDevToolsForTabs,
port,
timeOut,
proxyPort,
} = {}) {
const browser = process.env.SELENIUM_BROWSER;

const {
driver: seleniumDriver,
extensionId,
extensionUrl,
} = await buildBrowserWebDriver(browser, { openDevToolsForTabs, port });
} = await buildBrowserWebDriver(browser, {
openDevToolsForTabs,
port,
proxyPort,
});
const driver = new Driver(seleniumDriver, browser, extensionUrl, timeOut);

return {
Expand Down

0 comments on commit 12f3dfa

Please sign in to comment.