1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-13 21:27:12 +01:00
metamask-extension/app/scripts/controllers/network/provider-api-tests/shared-tests.js

3664 lines
141 KiB
JavaScript
Raw Normal View History

Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
/* eslint-disable jest/require-top-level-describe, jest/no-export, jest/no-identical-title */
import { fill } from 'lodash';
import {
withMockedCommunications,
withNetworkClient,
buildMockParams,
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
buildRequestWithReplacedBlockParam,
} from './helpers';
const originalSetTimeout = setTimeout;
/**
* Constructs an error message that the Infura client would produce in the event
* that it has attempted to retry the request to Infura and has failed.
*
* @param reason - The exact reason for failure.
* @returns The error message.
*/
function buildInfuraClientRetriesExhaustedErrorMessage(reason) {
return new RegExp(
`^InfuraProvider - cannot complete request. All retries exhausted\\..+${reason}`,
'us',
);
}
/**
* Constructs an error message that JsonRpcEngine would produce in the event
* that the response object is empty as it leaves the middleware.
*
* @param method - The RPC method.
* @returns The error message.
*/
function buildJsonRpcEngineEmptyResponseErrorMessage(method) {
return new RegExp(
`^JsonRpcEngine: Response has no error or result for request:.+"method": "${method}"`,
'us',
);
}
/**
* Constructs an error message that `fetch` with throw if it cannot make a
* request.
*
* @param url - The URL being fetched
* @param reason - The reason.
* @returns The error message.
*/
function buildFetchFailedErrorMessage(url, reason) {
return new RegExp(
`^request to ${url}(/[^/ ]*)+ failed, reason: ${reason}`,
'us',
);
}
/**
* Some middleware contain logic which retries the request if some condition
* applies. This retrying always happens out of band via `setTimeout`, and
* because we are stubbing time via Jest's fake timers, we have to manually
* advance the clock so that the `setTimeout` handlers get fired. We don't know
* when these timers will get created, however, so we have to keep advancing
* timers until the request has been made an appropriate number of times.
* Unfortunately we don't have a good way to know how many times a request has
* been retried, but the good news is that the middleware won't end, and thus
* the promise which the RPC call returns won't get fulfilled, until all retries
* have been made.
*
* @param promise - The promise which is returned by the RPC call.
* @param clock - A Sinon clock object which can be used to advance to the next
* `setTimeout` handler.
*/
async function waitForPromiseToBeFulfilledAfterRunningAllTimers(
promise,
clock,
) {
let hasPromiseBeenFulfilled = false;
let numTimesClockHasBeenAdvanced = 0;
promise
.catch(() => {
// This is used to silence Node.js warnings about the rejection
// being handled asynchronously. The error is handled later when
// `promise` is awaited.
})
.finally(() => {
hasPromiseBeenFulfilled = true;
});
// `isPromiseFulfilled` is modified asynchronously.
/* eslint-disable-next-line no-unmodified-loop-condition */
while (!hasPromiseBeenFulfilled && numTimesClockHasBeenAdvanced < 15) {
clock.runAll();
await new Promise((resolve) => originalSetTimeout(resolve, 10));
numTimesClockHasBeenAdvanced += 1;
}
return promise;
}
/**
* Defines tests that are common to both the Infura and JSON-RPC network client.
*
* @param providerType - The type of provider being tested, which determines
* which suite of middleware is being tested. If `infura`, then the middleware
* exposed by `createInfuraClient` is tested; if `custom`, then the middleware
* exposed by `createJsonRpcClient` will be tested.
*/
/* eslint-disable-next-line jest/no-export */
export function testsForProviderType(providerType) {
// Ethereum JSON-RPC spec: <https://ethereum.github.io/execution-apis/api-documentation/>
// Infura documentation: <https://docs.infura.io/infura/networks/ethereum/json-rpc-methods>
describe('methods included in the Ethereum JSON-RPC spec', () => {
describe('methods not handled by middleware', () => {
const notHandledByMiddleware = [
{ name: 'eth_accounts', numberOfParameters: 0 },
{ name: 'eth_coinbase', numberOfParameters: 0 },
{ name: 'eth_createAccessList', numberOfParameters: 2 },
{ name: 'eth_feeHistory', numberOfParameters: 3 },
{ name: 'eth_getFilterChanges', numberOfParameters: 1 },
{ name: 'eth_getLogs', numberOfParameters: 1 },
{ name: 'eth_getProof', numberOfParameters: 3 },
{ name: 'eth_getWork', numberOfParameters: 0 },
{ name: 'eth_hashrate', numberOfParameters: 0 },
{ name: 'eth_maxPriorityFeePerGas', numberOfParameters: 0 },
{ name: 'eth_mining', numberOfParameters: 0 },
{ name: 'eth_newBlockFilter', numberOfParameters: 0 },
{ name: 'eth_newFilter', numberOfParameters: 1 },
{ name: 'eth_newPendingTransactionFilter', numberOfParameters: 0 },
{ name: 'eth_sendRawTransaction', numberOfParameters: 1 },
{ name: 'eth_signTransaction', numberOfParameters: 1 },
{ name: 'eth_sendTransaction', numberOfParameters: 1 },
{ name: 'eth_sign', numberOfParameters: 2 },
{ name: 'eth_submitHashRate', numberOfParameters: 2 },
{ name: 'eth_submitWork', numberOfParameters: 3 },
{ name: 'eth_syncing', numberOfParameters: 0 },
{ name: 'eth_uninstallFilter', numberOfParameters: 1 },
{ name: 'debug_getRawHeader', numberOfParameters: 1 },
{ name: 'debug_getRawBlock', numberOfParameters: 1 },
{ name: 'debug_getRawTransaction', numberOfParameters: 1 },
{ name: 'debug_getRawReceipts', numberOfParameters: 1 },
{ name: 'debug_getBadBlocks', numberOfParameters: 0 },
];
notHandledByMiddleware.forEach(({ name, numberOfParameters }) => {
describe(`method name: ${name}`, () => {
testsForRpcMethodNotHandledByMiddleware(name, {
providerType,
numberOfParameters,
});
});
});
});
describe('methods that have a param to specify the block', () => {
const supportingBlockParam = [
{
name: 'eth_call',
blockParamIndex: 1,
numberOfParameters: 2,
},
{
name: 'eth_getBalance',
blockParamIndex: 1,
numberOfParameters: 2,
},
{
name: 'eth_getBlockByNumber',
blockParamIndex: 0,
numberOfParameters: 2,
},
{ name: 'eth_getCode', blockParamIndex: 1, numberOfParameters: 2 },
{
name: 'eth_getStorageAt',
blockParamIndex: 2,
numberOfParameters: 3,
},
{
name: 'eth_getTransactionCount',
blockParamIndex: 1,
numberOfParameters: 2,
},
];
supportingBlockParam.forEach(
({ name, blockParamIndex, numberOfParameters }) => {
describe(`method name: ${name}`, () => {
testsForRpcMethodSupportingBlockParam(name, {
providerType,
blockParamIndex,
numberOfParameters,
});
});
},
);
});
describe('methods that assume there is no block param', () => {
const assumingNoBlockParam = [
{ name: 'eth_blockNumber', numberOfParameters: 0 },
{ name: 'eth_estimateGas', numberOfParameters: 2 },
{ name: 'eth_gasPrice', numberOfParameters: 0 },
{ name: 'eth_getBlockByHash', numberOfParameters: 2 },
// NOTE: eth_getBlockTransactionCountByNumber does take a block param at
// the 0th index, but this is not handled by our cache middleware
// currently
{
name: 'eth_getBlockTransactionCountByNumber',
numberOfParameters: 1,
},
// NOTE: eth_getTransactionByBlockNumberAndIndex does take a block param
// at the 0th index, but this is not handled by our cache middleware
// currently
{
name: 'eth_getTransactionByBlockNumberAndIndex',
numberOfParameters: 2,
},
{
name: 'eth_getBlockTransactionCountByHash',
numberOfParameters: 1,
},
{ name: 'eth_getFilterLogs', numberOfParameters: 1 },
{
name: 'eth_getTransactionByBlockHashAndIndex',
numberOfParameters: 2,
},
{ name: 'eth_getUncleByBlockHashAndIndex', numberOfParameters: 2 },
// NOTE: eth_getUncleByBlockNumberAndIndex does take a block param at
// the 0th index, but this is not handled by our cache middleware
// currently
{ name: 'eth_getUncleByBlockNumberAndIndex', numberOfParameters: 2 },
{ name: 'eth_getUncleCountByBlockHash', numberOfParameters: 1 },
// NOTE: eth_getUncleCountByBlockNumber does take a block param at the
// 0th index, but this is not handled by our cache middleware currently
{ name: 'eth_getUncleCountByBlockNumber', numberOfParameters: 1 },
];
assumingNoBlockParam.forEach(({ name, numberOfParameters }) =>
describe(`method name: ${name}`, () => {
testsForRpcMethodAssumingNoBlockParam(name, {
providerType,
numberOfParameters,
});
}),
);
});
describe('methods with block hashes in their result', () => {
const methodsWithBlockHashInResponse = [
{ name: 'eth_getTransactionByHash', numberOfParameters: 1 },
{ name: 'eth_getTransactionReceipt', numberOfParameters: 1 },
];
methodsWithBlockHashInResponse.forEach(({ name, numberOfParameters }) => {
describe(`method name: ${name}`, () => {
testsForRpcMethodsThatCheckForBlockHashInResponse(name, {
numberOfParameters,
providerType,
});
});
});
});
describe('other methods', () => {
describe('eth_getTransactionByHash', () => {
it("refreshes the block tracker's current block if it is less than the block number that comes back in the response", async () => {
const method = 'eth_getTransactionByHash';
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// This is our request.
comms.mockRpcCall({
request,
response: {
result: {
blockNumber: '0x200',
},
},
});
comms.mockNextBlockTrackerRequest({ blockNumber: '0x300' });
await withNetworkClient(
{ providerType },
async ({ makeRpcCall, blockTracker }) => {
await makeRpcCall(request);
expect(blockTracker.getCurrentBlock()).toStrictEqual('0x300');
},
);
});
});
});
describe('eth_getTransactionReceipt', () => {
it("refreshes the block tracker's current block if it is less than the block number that comes back in the response", async () => {
const method = 'eth_getTransactionReceipt';
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// This is our request.
comms.mockRpcCall({
request,
response: {
result: {
blockNumber: '0x200',
},
},
});
comms.mockNextBlockTrackerRequest({ blockNumber: '0x300' });
await withNetworkClient(
{ providerType },
async ({ makeRpcCall, blockTracker }) => {
await makeRpcCall(request);
expect(blockTracker.getCurrentBlock()).toStrictEqual('0x300');
},
);
});
});
});
describe('eth_chainId', () => {
it('does not hit the RPC endpoint, instead returning the configured chain id', async () => {
const networkId = await withNetworkClient(
{ providerType: 'custom', customChainId: '0x1' },
({ makeRpcCall }) => {
return makeRpcCall({ method: 'eth_chainId' });
},
);
expect(networkId).toStrictEqual('0x1');
});
});
});
});
describe('methods not included in the Ethereum JSON-RPC spec', () => {
describe('methods not handled by middleware', () => {
const notHandledByMiddleware = [
{ name: 'custom_rpc_method', numberOfParameters: 1 },
{ name: 'eth_subscribe', numberOfParameters: 1 },
{ name: 'eth_unsubscribe', numberOfParameters: 1 },
{ name: 'net_listening', numberOfParameters: 0 },
{ name: 'net_peerCount', numberOfParameters: 0 },
{ name: 'parity_nextNonce', numberOfParameters: 1 },
];
notHandledByMiddleware.forEach(({ name, numberOfParameters }) => {
describe(`method name: ${name}`, () => {
testsForRpcMethodNotHandledByMiddleware(name, {
providerType,
numberOfParameters,
});
});
});
});
describe('methods that assume there is no block param', () => {
const assumingNoBlockParam = [
{ name: 'eth_protocolVersion', numberOfParameters: 0 },
{ name: 'web3_clientVersion', numberOfParameters: 0 },
];
assumingNoBlockParam.forEach(({ name, numberOfParameters }) =>
describe(`method name: ${name}`, () => {
testsForRpcMethodAssumingNoBlockParam(name, {
providerType,
numberOfParameters,
});
}),
);
});
describe('other methods', () => {
describe('net_version', () => {
// The Infura middleware includes `net_version` in its scaffold
// middleware, whereas the custom RPC middleware does not.
if (providerType === 'infura') {
it('does not hit Infura, instead returning the network ID that maps to the Infura network, as a decimal string', async () => {
const networkId = await withNetworkClient(
{ providerType: 'infura', infuraNetwork: 'goerli' },
({ makeRpcCall }) => {
return makeRpcCall({
method: 'net_version',
});
},
);
expect(networkId).toStrictEqual('5');
});
} else {
it('hits the RPC endpoint', async () => {
await withMockedCommunications(
{ providerType: 'custom' },
async (comms) => {
comms.mockRpcCall({
request: { method: 'net_version' },
response: { result: '1' },
});
const networkId = await withNetworkClient(
{ providerType: 'custom' },
({ makeRpcCall }) => {
return makeRpcCall({
method: 'net_version',
});
},
);
expect(networkId).toStrictEqual('1');
},
);
});
}
});
});
});
}
/**
* Defines tests which exercise the behavior exhibited by an RPC method that
* is not handled specially by the network client middleware.
*
* @param method - The name of the RPC method under test.
* @param additionalArgs - Additional arguments.
* @param additionalArgs.providerType - The type of provider being tested;
* either `infura` or `custom`.
* @param additionalArgs.numberOfParameters - The number of parameters that this
* RPC method takes.
*/
/* eslint-disable-next-line jest/no-export */
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
export function testsForRpcMethodNotHandledByMiddleware(
method,
{ providerType, numberOfParameters },
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
) {
if (providerType !== 'infura' && providerType !== 'custom') {
throw new Error(
`providerType must be either "infura" or "custom", was "${providerType}" instead`,
);
}
it('attempts to pass the request off to the RPC endpoint', async () => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
const request = {
method,
params: fill(Array(numberOfParameters), 'some value'),
};
const expectedResult = 'the result';
await withMockedCommunications({ providerType }, async (comms) => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request,
response: { result: expectedResult },
});
const actualResult = await withNetworkClient(
{ providerType },
({ makeRpcCall }) => makeRpcCall(request),
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
);
expect(actualResult).toStrictEqual(expectedResult);
});
});
}
/**
* Defines tests which exercise the behavior exhibited by an RPC method which is
* assumed to not take a block parameter. Even if it does, the value of this
* parameter will not be used in determining how to cache the method.
*
* @param method - The name of the RPC method under test.
* @param additionalArgs - Additional arguments.
* @param additionalArgs.numberOfParameters - The number of parameters supported by the method under test.
* @param additionalArgs.providerType - The type of provider being tested;
* either `infura` or `custom` (default: "infura").
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
*/
export function testsForRpcMethodAssumingNoBlockParam(
method,
{ numberOfParameters, providerType },
) {
if (providerType !== 'infura' && providerType !== 'custom') {
throw new Error(
`providerType must be either "infura" or "custom", was "${providerType}" instead`,
);
}
it('does not hit the RPC endpoint more than once for identical requests', async () => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
const requests = [{ method }, { method }];
const mockResults = ['first result', 'second result'];
await withMockedCommunications({ providerType }, async (comms) => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[0],
response: { result: mockResults[0] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
);
expect(results).toStrictEqual([mockResults[0], mockResults[0]]);
});
});
for (const paramIndex of [...Array(numberOfParameters).keys()]) {
it(`does not reuse the result of a previous request if parameter at index "${paramIndex}" differs`, async () => {
const firstMockParams = [
...new Array(numberOfParameters).fill('some value'),
];
const secondMockParams = firstMockParams.slice();
secondMockParams[paramIndex] = 'another value';
const requests = [
{
method,
params: firstMockParams,
},
{ method, params: secondMockParams },
];
const mockResults = ['some result', 'another result'];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockRpcCall({
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual([mockResults[0], mockResults[1]]);
});
});
}
it('hits the RPC endpoint and does not reuse the result of a previous request if the latest block number was updated since', async () => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
const requests = [{ method }, { method }];
const mockResults = ['first result', 'second result'];
await withMockedCommunications({ providerType }, async (comms) => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// Note that we have to mock these requests in a specific order. The
// first block tracker request occurs because of the first RPC request.
// The second block tracker request, however, does not occur because of
// the second RPC request, but rather because we call `clock.runAll()`
// below.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x1' });
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockNextBlockTrackerRequest({ blockNumber: '0x2' });
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
async (client) => {
const firstResult = await client.makeRpcCall(requests[0]);
// Proceed to the next iteration of the block tracker so that a new
// block is fetched and the current block is updated.
client.clock.runAll();
const secondResult = await client.makeRpcCall(requests[1]);
return [firstResult, secondResult];
},
);
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
expect(results).toStrictEqual(mockResults);
});
});
for (const emptyValue of [null, undefined, '\u003cnil\u003e']) {
it(`does not retry an empty response of "${emptyValue}"`, async () => {
const request = { method };
const mockResult = emptyValue;
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
response: { result: mockResult },
});
const result = await withNetworkClient(
{ providerType },
({ makeRpcCall }) => makeRpcCall(request),
);
expect(result).toStrictEqual(mockResult);
});
});
it(`does not reuse the result of a previous request if it was "${emptyValue}"`, async () => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
const requests = [{ method }, { method }];
const mockResults = [emptyValue, 'some result'];
await withMockedCommunications({ providerType }, async (comms) => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
);
expect(results).toStrictEqual(mockResults);
});
});
}
it('queues requests while a previous identical call is still pending, then runs the queue when it finishes, reusing the result from the first request', async () => {
const requests = [{ method }, { method }, { method }];
const mockResults = ['first result', 'second result', 'third result'];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request: requests[0],
response: { result: mockResults[0] },
delay: 100,
});
comms.mockRpcCall({
request: requests[1],
response: { result: mockResults[1] },
});
comms.mockRpcCall({
request: requests[2],
response: { result: mockResults[2] },
});
const results = await withNetworkClient(
{ providerType },
async (client) => {
const resultPromises = [
client.makeRpcCall(requests[0]),
client.makeRpcCall(requests[1]),
client.makeRpcCall(requests[2]),
];
const firstResult = await resultPromises[0];
// The inflight cache middleware uses setTimeout to run the handlers,
// so run them now
client.clock.runAll();
const remainingResults = await Promise.all(resultPromises.slice(1));
return [firstResult, ...remainingResults];
},
);
expect(results).toStrictEqual([
mockResults[0],
mockResults[0],
mockResults[0],
]);
});
});
it('throws a custom error if the request to the RPC endpoint returns a 405 response', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
response: {
httpStatus: 405,
},
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
'The method does not exist / is not available',
);
});
});
// There is a difference in how we are testing the Infura middleware vs. the
// custom RPC middleware (or, more specifically, the fetch middleware) because
// of what both middleware treat as rate limiting errors. In this case, the
// fetch middleware treats a 418 response from the RPC endpoint as such an
// error, whereas to the Infura middleware, it is a 429 response.
if (providerType === 'infura') {
it('throws an undescriptive error if the request to the RPC endpoint returns a 418 response', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
response: {
httpStatus: 418,
},
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
'{"id":1,"jsonrpc":"2.0"}',
);
});
});
it('throws an error with a custom message if the request to the RPC endpoint returns a 429 response', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
response: {
httpStatus: 429,
},
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
'Request is being rate limited',
);
});
});
} else {
it('throws a custom error if the request to the RPC endpoint returns a 418 response', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
response: {
httpStatus: 418,
},
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
'Request is being rate limited.',
);
});
});
it('throws an undescriptive error if the request to the RPC endpoint returns a 429 response', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
response: {
httpStatus: 429,
},
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
"Non-200 status code: '429'",
);
});
});
}
it('throws a generic, undescriptive error if the request to the RPC endpoint returns a response that is not 405, 418, 429, 503, or 504', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
response: {
id: 12345,
jsonrpc: '2.0',
error: 'some error',
httpStatus: 420,
},
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall }) => makeRpcCall(request),
);
const errorMessage =
providerType === 'infura'
? '{"id":12345,"jsonrpc":"2.0","error":"some error"}'
: "Non-200 status code: '420'";
await expect(promiseForResult).rejects.toThrow(errorMessage);
});
});
[503, 504].forEach((httpStatus) => {
it(`retries the request to the RPC endpoint up to 5 times if it returns a ${httpStatus} response, returning the successful result if there is one on the 5th try`, async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
// Here we have the request fail for the first 4 tries, then succeed
// on the 5th try.
comms.mockRpcCall({
request,
response: {
error: 'Some error',
httpStatus,
},
times: 4,
});
comms.mockRpcCall({
request,
response: {
result: 'the result',
httpStatus: 200,
},
});
const result = await withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
expect(result).toStrictEqual('the result');
});
});
it(`causes a request to fail with a custom error if the request to the RPC endpoint returns a ${httpStatus} response 5 times in a row`, async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
response: {
error: 'Some error',
httpStatus,
},
times: 5,
});
comms.mockNextBlockTrackerRequest();
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
const err =
providerType === 'infura'
? buildInfuraClientRetriesExhaustedErrorMessage('Gateway timeout')
: buildJsonRpcEngineEmptyResponseErrorMessage(method);
await expect(promiseForResult).rejects.toThrow(err);
});
});
});
it('retries the request to the RPC endpoint up to 5 times if an "ETIMEDOUT" error is thrown while making the request, returning the successful result if there is one on the 5th try', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
// Here we have the request fail for the first 4 tries, then succeed
// on the 5th try.
comms.mockRpcCall({
request,
error: 'ETIMEDOUT: Some message',
times: 4,
});
comms.mockRpcCall({
request,
response: {
result: 'the result',
httpStatus: 200,
},
});
const result = await withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
expect(result).toStrictEqual('the result');
});
});
// Both the Infura and fetch middleware detect ETIMEDOUT errors and will
// automatically retry the request to the RPC endpoint in question, but both
// produce a different error if the number of retries is exhausted.
if (providerType === 'infura') {
it('causes a request to fail with a custom error if an "ETIMEDOUT" error is thrown while making the request to the RPC endpoint 5 times in a row', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'ETIMEDOUT: Some message';
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
error: errorMessage,
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
await expect(promiseForResult).rejects.toThrow(
buildInfuraClientRetriesExhaustedErrorMessage(errorMessage),
);
});
});
} else {
it('returns an empty response if an "ETIMEDOUT" error is thrown while making the request to the RPC endpoint 5 times in a row', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'ETIMEDOUT: Some message';
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
error: errorMessage,
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
await expect(promiseForResult).rejects.toThrow(
buildJsonRpcEngineEmptyResponseErrorMessage(method),
);
});
});
}
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The Infura middleware treats a response that contains an ECONNRESET message
// as an innocuous error that is likely to disappear on a retry. The custom
// RPC middleware, on the other hand, does not specially handle this error.
if (providerType === 'infura') {
it('retries the request to the RPC endpoint up to 5 times if an "ECONNRESET" error is thrown while making the request, returning the successful result if there is one on the 5th try', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
// Here we have the request fail for the first 4 tries, then succeed
// on the 5th try.
comms.mockRpcCall({
request,
error: 'ECONNRESET: Some message',
times: 4,
});
comms.mockRpcCall({
request,
response: {
result: 'the result',
httpStatus: 200,
},
});
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
const result = await withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
expect(result).toStrictEqual('the result');
});
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
it('causes a request to fail with a custom error if an "ECONNRESET" error is thrown while making the request to the RPC endpoint 5 times in a row', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'ECONNRESET: Some message';
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
error: errorMessage,
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
await expect(promiseForResult).rejects.toThrow(
buildInfuraClientRetriesExhaustedErrorMessage(errorMessage),
);
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
});
} else {
it('does not retry the request to the RPC endpoint, but throws immediately, if an "ECONNRESET" error is thrown while making the request', async () => {
const customRpcUrl = 'http://example.com';
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
await withMockedCommunications(
{ providerType, customRpcUrl },
async (comms) => {
const request = { method };
const errorMessage = 'ECONNRESET: Some message';
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
error: errorMessage,
});
const promiseForResult = withNetworkClient(
{ providerType, customRpcUrl },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
buildFetchFailedErrorMessage(customRpcUrl, errorMessage),
);
},
);
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
}
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// Both the Infura and fetch middleware will attempt to parse the response
// body as JSON, and if this step produces an error, both middleware will also
// attempt to retry the request. However, this error handling code is slightly
// different between the two. As the error in this case is a SyntaxError, the
// Infura middleware will catch it immediately, whereas the custom RPC
// middleware will catch it and re-throw a separate error, which it then
// catches later.
if (providerType === 'infura') {
it('retries the request to the RPC endpoint up to 5 times if an "SyntaxError" error is thrown while making the request, returning the successful result if there is one on the 5th try', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
// Here we have the request fail for the first 4 tries, then succeed
// on the 5th try.
comms.mockRpcCall({
request,
error: 'SyntaxError: Some message',
times: 4,
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
comms.mockRpcCall({
request,
response: {
result: 'the result',
httpStatus: 200,
},
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
const result = await withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
);
expect(result).toStrictEqual('the result');
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
});
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
it('causes a request to fail with a custom error if an "SyntaxError" error is thrown while making the request to the RPC endpoint 5 times in a row', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'SyntaxError: Some message';
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
error: errorMessage,
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
await expect(promiseForResult).rejects.toThrow(
buildInfuraClientRetriesExhaustedErrorMessage(errorMessage),
);
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
});
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
it('does not retry the request to the RPC endpoint, but throws immediately, if a "failed to parse response body" error is thrown while making the request', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'failed to parse response body: some message';
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
error: errorMessage,
});
const promiseForResult = withNetworkClient(
{ providerType, infuraNetwork: comms.infuraNetwork },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
buildFetchFailedErrorMessage(comms.rpcUrl, errorMessage),
);
});
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
} else {
it('does not retry the request to the RPC endpoint, but throws immediately, if a "SyntaxError" error is thrown while making the request', async () => {
const customRpcUrl = 'http://example.com';
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
await withMockedCommunications(
{ providerType, customRpcUrl },
async (comms) => {
const request = { method };
const errorMessage = 'SyntaxError: Some message';
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
error: errorMessage,
});
const promiseForResult = withNetworkClient(
{ providerType, customRpcUrl },
async ({ makeRpcCall }) => makeRpcCall(request),
);
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
await expect(promiseForResult).rejects.toThrow(
buildFetchFailedErrorMessage(customRpcUrl, errorMessage),
);
},
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
);
});
it('retries the request to the RPC endpoint up to 5 times if a "failed to parse response body" error is thrown while making the request, returning the successful result if there is one on the 5th try', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
// Here we have the request fail for the first 4 tries, then succeed
// on the 5th try.
comms.mockRpcCall({
request,
error: 'failed to parse response body: some message',
times: 4,
});
comms.mockRpcCall({
request,
response: {
result: 'the result',
httpStatus: 200,
},
});
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
const result = await withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
expect(result).toStrictEqual('the result');
});
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
it('returns an empty response if a "failed to parse response body" error is thrown while making the request to the RPC endpoint 5 times in a row', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'failed to parse response body: some message';
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
error: errorMessage,
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
await expect(promiseForResult).rejects.toThrow(
buildJsonRpcEngineEmptyResponseErrorMessage(method),
);
});
});
}
// Only the custom RPC middleware will detect a "Failed to fetch" error and
// attempt to retry the request to the RPC endpoint; the Infura middleware
// does not.
if (providerType === 'infura') {
it('does not retry the request to the RPC endpoint, but throws immediately, if a "Failed to fetch" error is thrown while making the request', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'Failed to fetch: some message';
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
error: errorMessage,
});
const promiseForResult = withNetworkClient(
{ providerType, infuraNetwork: comms.infuraNetwork },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
buildFetchFailedErrorMessage(comms.rpcUrl, errorMessage),
);
});
});
} else {
it('retries the request to the RPC endpoint up to 5 times if a "Failed to fetch" error is thrown while making the request, returning the successful result if there is one on the 5th try', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
// Here we have the request fail for the first 4 tries, then succeed
// on the 5th try.
comms.mockRpcCall({
request,
error: 'Failed to fetch: some message',
times: 4,
});
comms.mockRpcCall({
request,
response: {
result: 'the result',
httpStatus: 200,
},
});
const result = await withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
expect(result).toStrictEqual('the result');
});
});
it('returns an empty response if a "Failed to fetch" error is thrown while making the request to the RPC endpoint 5 times in a row', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'Failed to fetch: some message';
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
error: errorMessage,
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
await expect(promiseForResult).rejects.toThrow(
buildJsonRpcEngineEmptyResponseErrorMessage(method),
);
});
});
}
}
/**
* Defines tests which exercise the behavior exhibited by an RPC method that
* use `blockHash` in the response data to determine whether the response is
* cacheable.
*
* @param method - The name of the RPC method under test.
* @param additionalArgs - Additional arguments.
* @param additionalArgs.numberOfParameters - The number of parameters supported by the method under test.
* @param additionalArgs.providerType - The type of provider being tested;
* either `infura` or `custom` (default: "infura").
*/
export function testsForRpcMethodsThatCheckForBlockHashInResponse(
method,
{ numberOfParameters, providerType },
) {
if (providerType !== 'infura' && providerType !== 'custom') {
throw new Error(
`providerType must be either "infura" or "custom", was "${providerType}" instead`,
);
}
it('does not hit the RPC endpoint more than once for identical requests and it has a valid blockHash', async () => {
const requests = [{ method }, { method }];
const mockResult = { blockHash: '0x100' };
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request: requests[0],
response: { result: mockResult },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual([mockResult, mockResult]);
});
});
for (const paramIndex of [...Array(numberOfParameters).keys()]) {
it(`does not reuse the result of a previous request with a valid blockHash if parameter at index "${paramIndex}" differs`, async () => {
const firstMockParams = [
...new Array(numberOfParameters).fill('some value'),
];
const secondMockParams = firstMockParams.slice();
secondMockParams[paramIndex] = 'another value';
const requests = [
{
method,
params: firstMockParams,
},
{ method, params: secondMockParams },
];
const mockResults = [{ blockHash: '0x100' }, { blockHash: '0x200' }];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockRpcCall({
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual([mockResults[0], mockResults[1]]);
});
});
}
it('hits the RPC endpoint and does not reuse the result of a previous request if the latest block number was updated since', async () => {
const requests = [{ method }, { method }];
const mockResults = [{ blockHash: '0x100' }, { blockHash: '0x200' }];
await withMockedCommunications({ providerType }, async (comms) => {
// Note that we have to mock these requests in a specific order. The
// first block tracker request occurs because of the first RPC
// request. The second block tracker request, however, does not occur
// because of the second RPC request, but rather because we call
// `clock.runAll()` below.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x1' });
comms.mockRpcCall({
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockNextBlockTrackerRequest({ blockNumber: '0x2' });
comms.mockRpcCall({
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
async (client) => {
const firstResult = await client.makeRpcCall(requests[0]);
// Proceed to the next iteration of the block tracker so that a new
// block is fetched and the current block is updated.
client.clock.runAll();
const secondResult = await client.makeRpcCall(requests[1]);
return [firstResult, secondResult];
},
);
expect(results).toStrictEqual(mockResults);
});
});
for (const emptyValue of [null, undefined, '\u003cnil\u003e']) {
it(`does not retry an empty response of "${emptyValue}"`, async () => {
const request = { method };
const mockResult = emptyValue;
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
response: { result: mockResult },
});
const result = await withNetworkClient(
{ providerType },
({ makeRpcCall }) => makeRpcCall(request),
);
expect(result).toStrictEqual(mockResult);
});
});
it(`does not reuse the result of a previous request if it was "${emptyValue}"`, async () => {
const requests = [{ method }, { method }];
const mockResults = [emptyValue, { blockHash: '0x100' }];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockRpcCall({
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual(mockResults);
});
});
}
it('does not reuse the result of a previous request if result.blockHash was null', async () => {
const requests = [{ method }, { method }];
const mockResults = [
{ blockHash: null, extra: 'some value' },
{ blockHash: '0x100', extra: 'some other value' },
];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockRpcCall({
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual(mockResults);
});
});
it('does not reuse the result of a previous request if result.blockHash was undefined', async () => {
const requests = [{ method }, { method }];
const mockResults = [
{ extra: 'some value' },
{ blockHash: '0x100', extra: 'some other value' },
];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockRpcCall({
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual(mockResults);
});
});
it('does not reuse the result of a previous request if result.blockHash was "0x0000000000000000000000000000000000000000000000000000000000000000"', async () => {
const requests = [{ method }, { method }];
const mockResults = [
{
blockHash:
'0x0000000000000000000000000000000000000000000000000000000000000000',
extra: 'some value',
},
{ blockHash: '0x100', extra: 'some other value' },
];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockRpcCall({
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual(mockResults);
});
});
}
/**
* Defines tests which exercise the behavior exhibited by an RPC method that
* takes a block parameter. The value of this parameter can be either a block
* number or a block tag ("latest", "earliest", or "pending") and affects how
* the method is cached.
*
* @param method - The name of the RPC method under test.
* @param additionalArgs - Additional arguments.
* @param additionalArgs.blockParamIndex - The index of the block parameter.
* @param additionalArgs.numberOfParameters - The number of parameters supported by the method under test.
* @param additionalArgs.providerType - The type of provider being tested.
* either `infura` or `custom` (default: "infura").
*/
/* eslint-disable-next-line jest/no-export */
export function testsForRpcMethodSupportingBlockParam(
method,
{ blockParamIndex, numberOfParameters, providerType },
) {
describe.each([
['given no block tag', undefined],
['given a block tag of "latest"', 'latest'],
])('%s', (_desc, blockParam) => {
it('does not hit the RPC endpoint more than once for identical requests', async () => {
const requests = [
{
method,
params: buildMockParams({ blockParamIndex, blockParam }),
},
{ method, params: buildMockParams({ blockParamIndex, blockParam }) },
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
];
const mockResults = ['first result', 'second result'];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the block-cache
// middleware will request the latest block number through the block
// tracker to determine the cache key. Later, the block-ref
// middleware will request the latest block number again to resolve
// the value of "latest", but the block number is cached once made,
// so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[0],
blockParamIndex,
'0x100',
),
response: { result: mockResults[0] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual([mockResults[0], mockResults[0]]);
});
});
for (const paramIndex of [...Array(numberOfParameters).keys()]) {
if (paramIndex === blockParamIndex) {
// testing changes in block param is covered under later tests
continue;
}
it(`does not reuse the result of a previous request if parameter at index "${paramIndex}" differs`, async () => {
const firstMockParams = [
...new Array(numberOfParameters).fill('some value'),
];
firstMockParams[blockParamIndex] = blockParam;
const secondMockParams = firstMockParams.slice();
secondMockParams[paramIndex] = 'another value';
const requests = [
{
method,
params: firstMockParams,
},
{ method, params: secondMockParams },
];
const mockResults = ['first result', 'second result'];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the block-cache
// middleware will request the latest block number through the block
// tracker to determine the cache key. Later, the block-ref
// middleware will request the latest block number again to resolve
// the value of "latest", but the block number is cached once made,
// so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[0],
blockParamIndex,
'0x100',
),
response: { result: mockResults[0] },
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[1],
blockParamIndex,
'0x100',
),
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual([mockResults[0], mockResults[1]]);
});
});
}
it('hits the RPC endpoint and does not reuse the result of a previous request if the latest block number was updated since', async () => {
const requests = [
{ method, params: buildMockParams({ blockParamIndex, blockParam }) },
{ method, params: buildMockParams({ blockParamIndex, blockParam }) },
];
const mockResults = ['first result', 'second result'];
await withMockedCommunications({ providerType }, async (comms) => {
// Note that we have to mock these requests in a specific order.
// The first block tracker request occurs because of the first RPC
// request. The second block tracker request, however, does not
// occur because of the second RPC request, but rather because we
// call `clock.runAll()` below.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[0],
blockParamIndex,
'0x100',
),
response: { result: mockResults[0] },
});
comms.mockNextBlockTrackerRequest({ blockNumber: '0x200' });
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[1],
blockParamIndex,
'0x200',
),
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
async (client) => {
const firstResult = await client.makeRpcCall(requests[0]);
// Proceed to the next iteration of the block tracker so that a
// new block is fetched and the current block is updated.
client.clock.runAll();
const secondResult = await client.makeRpcCall(requests[1]);
return [firstResult, secondResult];
},
);
expect(results).toStrictEqual(mockResults);
});
});
for (const emptyValue of [null, undefined, '\u003cnil\u003e']) {
it(`does not retry an empty response of "${emptyValue}"`, async () => {
const request = {
method,
params: buildMockParams({ blockParamIndex, blockParam }),
};
const mockResult = emptyValue;
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: { result: mockResult },
});
const result = await withNetworkClient(
{ providerType },
({ makeRpcCall }) => makeRpcCall(request),
);
expect(result).toStrictEqual(mockResult);
});
});
it(`does not reuse the result of a previous request if it was "${emptyValue}"`, async () => {
const requests = [
{ method, params: buildMockParams({ blockParamIndex, blockParam }) },
{ method, params: buildMockParams({ blockParamIndex, blockParam }) },
];
const mockResults = [emptyValue, 'some result'];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[0],
blockParamIndex,
'0x100',
),
response: { result: mockResults[0] },
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[1],
blockParamIndex,
'0x100',
),
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual(mockResults);
});
});
}
it('queues requests while a previous identical call is still pending, then runs the queue when it finishes, reusing the result from the first request', async () => {
const requests = [{ method }, { method }, { method }];
const mockResults = ['first result', 'second result', 'third result'];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number, and we delay it.
comms.mockRpcCall({
delay: 100,
request: buildRequestWithReplacedBlockParam(
requests[0],
blockParamIndex,
'0x100',
),
response: { result: mockResults[0] },
});
// The previous two requests will happen again, in the same order.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[1],
blockParamIndex,
'0x100',
),
response: { result: mockResults[1] },
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[2],
blockParamIndex,
'0x100',
),
response: { result: mockResults[2] },
});
const results = await withNetworkClient(
{ providerType },
async (client) => {
const resultPromises = [
client.makeRpcCall(requests[0]),
client.makeRpcCall(requests[1]),
client.makeRpcCall(requests[2]),
];
const firstResult = await resultPromises[0];
// The inflight cache middleware uses setTimeout to run the
// handlers, so run them now
client.clock.runAll();
const remainingResults = await Promise.all(resultPromises.slice(1));
return [firstResult, ...remainingResults];
},
);
expect(results).toStrictEqual([
mockResults[0],
mockResults[0],
mockResults[0],
]);
});
});
it('throws an error with a custom message if the request to the RPC endpoint returns a 405 response', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
httpStatus: 405,
},
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
'The method does not exist / is not available',
);
});
});
// There is a difference in how we are testing the Infura middleware vs. the
// custom RPC middleware (or, more specifically, the fetch middleware)
// because of what both middleware treat as rate limiting errors. In this
// case, the fetch middleware treats a 418 response from the RPC endpoint as
// such an error, whereas to the Infura middleware, it is a 429 response.
if (providerType === 'infura') {
it('throws a generic, undescriptive error if the request to the RPC endpoint returns a 418 response', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
httpStatus: 418,
},
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
'{"id":1,"jsonrpc":"2.0"}',
);
});
});
it('throws an error with a custom message if the request to the RPC endpoint returns a 429 response', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
httpStatus: 429,
},
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
'Request is being rate limited',
);
});
});
} else {
it('throws an error with a custom message if the request to the RPC endpoint returns a 418 response', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
httpStatus: 418,
},
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
'Request is being rate limited.',
);
});
});
it('throws an undescriptive error if the request to the RPC endpoint returns a 429 response', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
httpStatus: 429,
},
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
"Non-200 status code: '429'",
);
});
});
}
it('throws an undescriptive error message if the request to the RPC endpoint returns a response that is not 405, 418, 429, 503, or 504', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
id: 12345,
jsonrpc: '2.0',
error: 'some error',
httpStatus: 420,
},
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall }) => makeRpcCall(request),
);
const msg =
providerType === 'infura'
? '{"id":12345,"jsonrpc":"2.0","error":"some error"}'
: "Non-200 status code: '420'";
await expect(promiseForResult).rejects.toThrow(msg);
});
});
[503, 504].forEach((httpStatus) => {
it(`retries the request to the RPC endpoint up to 5 times if it returns a ${httpStatus} response, returning the successful result if there is one on the 5th try`, async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
//
// Here we have the request fail for the first 4 tries, then succeed
// on the 5th try.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
error: 'some error',
httpStatus,
},
times: 4,
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
result: 'the result',
httpStatus: 200,
},
});
const result = await withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
expect(result).toStrictEqual('the result');
});
});
// Both the Infura middleware and custom RPC middleware detect a 503 or 504
// response and retry the request to the RPC endpoint automatically but
// differ in what sort of response is returned when the number of retries is
// exhausted.
if (providerType === 'infura') {
it(`causes a request to fail with a custom error if the request to the RPC endpoint returns a ${httpStatus} response 5 times in a row`, async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
error: 'Some error',
httpStatus,
},
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
await expect(promiseForResult).rejects.toThrow(
buildInfuraClientRetriesExhaustedErrorMessage('Gateway timeout'),
);
});
});
} else {
it(`produces an empty response if the request to the RPC endpoint returns a ${httpStatus} response 5 times in a row`, async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
error: 'Some error',
httpStatus,
},
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
await expect(promiseForResult).rejects.toThrow(
buildJsonRpcEngineEmptyResponseErrorMessage(method),
);
});
});
}
});
it('retries the request to the RPC endpoint up to 5 times if an "ETIMEDOUT" error is thrown while making the request, returning the successful result if there is one on the 5th try', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
//
// Here we have the request fail for the first 4 tries, then
// succeed on the 5th try.
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: buildRequestWithReplacedBlockParam(
request,
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
blockParamIndex,
'0x100',
),
error: 'ETIMEDOUT: Some message',
times: 4,
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
result: 'the result',
httpStatus: 200,
},
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
const result = await withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
);
expect(result).toStrictEqual('the result');
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
});
// Both the Infura and fetch middleware detect ETIMEDOUT errors and will
// automatically retry the request to the RPC endpoint in question, but each
// produces a different error if the number of retries is exhausted.
if (providerType === 'infura') {
it('causes a request to fail with a custom error if an "ETIMEDOUT" error is thrown while making the request to the RPC endpoint 5 times in a row', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'ETIMEDOUT: Some message';
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: errorMessage,
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
await expect(promiseForResult).rejects.toThrow(
buildInfuraClientRetriesExhaustedErrorMessage(errorMessage),
);
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
});
} else {
it('produces an empty response if an "ETIMEDOUT" error is thrown while making the request to the RPC endpoint 5 times in a row', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'ETIMEDOUT: Some message';
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: errorMessage,
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
await expect(promiseForResult).rejects.toThrow(
buildJsonRpcEngineEmptyResponseErrorMessage(method),
);
});
});
}
// The Infura middleware treats a response that contains an ECONNRESET
// message as an innocuous error that is likely to disappear on a retry. The
// custom RPC middleware, on the other hand, does not specially handle this
// error.
if (providerType === 'infura') {
it('retries the request to the RPC endpoint up to 5 times if an "ECONNRESET" error is thrown while making the request, returning the successful result if there is one on the 5th try', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
//
// Here we have the request fail for the first 4 tries, then
// succeed on the 5th try.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: 'ECONNRESET: Some message',
times: 4,
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
result: 'the result',
httpStatus: 200,
},
});
const result = await withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
expect(result).toStrictEqual('the result');
});
});
it('causes a request to fail with a custom error if an "ECONNRESET" error is thrown while making the request to the RPC endpoint 5 times in a row', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'ECONNRESET: Some message';
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: errorMessage,
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
await expect(promiseForResult).rejects.toThrow(
buildInfuraClientRetriesExhaustedErrorMessage(errorMessage),
);
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
});
} else {
it('does not retry the request to the RPC endpoint, but throws immediately, if an "ECONNRESET" error is thrown while making the request', async () => {
const customRpcUrl = 'http://example.com';
await withMockedCommunications(
{ providerType, customRpcUrl },
async (comms) => {
const request = { method };
const errorMessage = 'ECONNRESET: Some message';
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: errorMessage,
});
const promiseForResult = withNetworkClient(
{ providerType, customRpcUrl },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
buildFetchFailedErrorMessage(customRpcUrl, errorMessage),
);
},
);
});
}
// Both the Infura and fetch middleware will attempt to parse the response
// body as JSON, and if this step produces an error, both middleware will
// also attempt to retry the request. However, this error handling code is
// slightly different between the two. As the error in this case is a
// SyntaxError, the Infura middleware will catch it immediately, whereas the
// custom RPC middleware will catch it and re-throw a separate error, which
// it then catches later.
if (providerType === 'infura') {
it('retries the request to the RPC endpoint up to 5 times if a "SyntaxError" error is thrown while making the request, returning the successful result if there is one on the 5th try', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
//
// Here we have the request fail for the first 4 tries, then
// succeed on the 5th try.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: 'SyntaxError: Some message',
times: 4,
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
result: 'the result',
httpStatus: 200,
},
});
const result = await withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
expect(result).toStrictEqual('the result');
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
});
it('causes a request to fail with a custom error if a "SyntaxError" error is thrown while making the request to the RPC endpoint 5 times in a row', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'SyntaxError: Some message';
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: buildRequestWithReplacedBlockParam(
request,
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
blockParamIndex,
'0x100',
),
error: errorMessage,
times: 5,
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
);
await expect(promiseForResult).rejects.toThrow(
buildInfuraClientRetriesExhaustedErrorMessage(errorMessage),
);
});
});
it('does not retry the request to the RPC endpoint, but throws immediately, if a "failed to parse response body" error is thrown while making the request', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'failed to parse response body: Some message';
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: errorMessage,
});
const promiseForResult = withNetworkClient(
{ providerType, infuraNetwork: comms.infuraNetwork },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
buildFetchFailedErrorMessage(comms.rpcUrl, errorMessage),
);
});
});
} else {
it('does not retry the request to the RPC endpoint, but throws immediately, if a "SyntaxError" error is thrown while making the request', async () => {
const customRpcUrl = 'http://example.com';
await withMockedCommunications(
{ providerType, customRpcUrl },
async (comms) => {
const request = { method };
const errorMessage = 'SyntaxError: Some message';
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: errorMessage,
});
const promiseForResult = withNetworkClient(
{ providerType, customRpcUrl },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
buildFetchFailedErrorMessage(customRpcUrl, errorMessage),
);
},
);
});
it('retries the request to the RPC endpoint up to 5 times if a "failed to parse response body" error is thrown while making the request, returning the successful result if there is one on the 5th try', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
//
// Here we have the request fail for the first 4 tries, then
// succeed on the 5th try.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: 'failed to parse response body: Some message',
times: 4,
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
result: 'the result',
httpStatus: 200,
},
});
const result = await withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
expect(result).toStrictEqual('the result');
});
});
it('produces an empty response if a "failed to parse response body" error is thrown while making the request to the RPC endpoint 5 times in a row', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'failed to parse response body: some message';
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: errorMessage,
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
await expect(promiseForResult).rejects.toThrow(
buildJsonRpcEngineEmptyResponseErrorMessage(method),
);
});
});
}
// Only the custom RPC middleware will detect a "Failed to fetch" error and
// attempt to retry the request to the RPC endpoint; the Infura middleware
// does not.
if (providerType === 'infura') {
it('does not retry the request to the RPC endpoint, but throws immediately, if a "Failed to fetch" error is thrown while making the request', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'Failed to fetch: Some message';
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: errorMessage,
});
const promiseForResult = withNetworkClient(
{ providerType, infuraNetwork: comms.infuraNetwork },
async ({ makeRpcCall }) => makeRpcCall(request),
);
await expect(promiseForResult).rejects.toThrow(
buildFetchFailedErrorMessage(comms.rpcUrl, errorMessage),
);
});
});
} else {
it('retries the request to the RPC endpoint up to 5 times if a "Failed to fetch" error is thrown while making the request, returning the successful result if there is one on the 5th try', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
//
// Here we have the request fail for the first 4 tries, then
// succeed on the 5th try.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: 'Failed to fetch: Some message',
times: 4,
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: {
result: 'the result',
httpStatus: 200,
},
});
const result = await withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
expect(result).toStrictEqual('the result');
});
});
it('produces an empty response if a "Failed to fetch" error is thrown while making the request to the RPC endpoint 5 times in a row', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = { method };
const errorMessage = 'Failed to fetch: some message';
// The first time a block-cacheable request is made, the
// block-cache middleware will request the latest block number
// through the block tracker to determine the cache key. Later,
// the block-ref middleware will request the latest block number
// again to resolve the value of "latest", but the block number is
// cached once made, so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
error: errorMessage,
times: 5,
});
const promiseForResult = withNetworkClient(
{ providerType },
async ({ makeRpcCall, clock }) => {
return await waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
);
},
);
await expect(promiseForResult).rejects.toThrow(
buildJsonRpcEngineEmptyResponseErrorMessage(method),
);
});
});
}
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
});
describe.each([
['given a block tag of "earliest"', 'earliest', 'earliest'],
['given a block number', 'block number', '0x100'],
])('%s', (_desc, blockParamType, blockParam) => {
it('does not hit the RPC endpoint more than once for identical requests', async () => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
const requests = [
{
method,
params: buildMockParams({ blockParamIndex, blockParam }),
},
{
method,
params: buildMockParams({ blockParamIndex, blockParam }),
},
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
];
const mockResults = ['first result', 'second result'];
await withMockedCommunications({ providerType }, async (comms) => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the block-cache
// middleware will request the latest block number through the block
// tracker to determine the cache key. This block number doesn't
// matter.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[0],
response: { result: mockResults[0] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
);
expect(results).toStrictEqual([mockResults[0], mockResults[0]]);
});
});
for (const paramIndex of [...Array(numberOfParameters).keys()]) {
if (paramIndex === blockParamIndex) {
// testing changes in block param is covered under later tests
continue;
}
it(`does not reuse the result of a previous request if parameter at index "${paramIndex}" differs`, async () => {
const firstMockParams = [
...new Array(numberOfParameters).fill('some value'),
];
firstMockParams[blockParamIndex] = blockParam;
const secondMockParams = firstMockParams.slice();
secondMockParams[paramIndex] = 'another value';
const requests = [
{
method,
params: firstMockParams,
},
{ method, params: secondMockParams },
];
const mockResults = ['first result', 'second result'];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the block-cache
// middleware will request the latest block number through the block
// tracker to determine the cache key. Later, the block-ref
// middleware will request the latest block number again to resolve
// the value of "latest", but the block number is cached once made,
// so we only need to mock the request once.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' });
// The block-ref middleware will make the request as specified
// except that the block param is replaced with the latest block
// number.
comms.mockRpcCall({
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockRpcCall({
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual([mockResults[0], mockResults[1]]);
});
});
}
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
it('reuses the result of a previous request even if the latest block number was updated since', async () => {
const requests = [
{
method,
params: buildMockParams({ blockParamIndex, blockParam }),
},
{
method,
params: buildMockParams({ blockParamIndex, blockParam }),
},
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
];
const mockResults = ['first result', 'second result'];
await withMockedCommunications({ providerType }, async (comms) => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// Note that we have to mock these requests in a specific order. The
// first block tracker request occurs because of the first RPC
// request. The second block tracker request, however, does not
// occur because of the second RPC request, but rather because we
// call `clock.runAll()` below.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x1' });
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockNextBlockTrackerRequest({ blockNumber: '0x2' });
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
async (client) => {
const firstResult = await client.makeRpcCall(requests[0]);
// Proceed to the next iteration of the block tracker so that a
// new block is fetched and the current block is updated.
client.clock.runAll();
const secondResult = await client.makeRpcCall(requests[1]);
return [firstResult, secondResult];
},
);
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
expect(results).toStrictEqual([mockResults[0], mockResults[0]]);
});
});
if (blockParamType === 'earliest') {
it('treats "0x00" as a synonym for "earliest"', async () => {
const requests = [
{
method,
params: buildMockParams({ blockParamIndex, blockParam }),
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
},
{
method,
params: buildMockParams({ blockParamIndex, blockParam: '0x00' }),
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
},
];
const mockResults = ['first result', 'second result'];
await withMockedCommunications({ providerType }, async (comms) => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the latest
// block number is retrieved through the block tracker first. It
// doesn't matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[0],
response: { result: mockResults[0] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
);
expect(results).toStrictEqual([mockResults[0], mockResults[0]]);
});
});
for (const emptyValue of [null, undefined, '\u003cnil\u003e']) {
it(`does not retry an empty response of "${emptyValue}"`, async () => {
const request = {
method,
params: buildMockParams({ blockParamIndex, blockParam }),
};
const mockResult = emptyValue;
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request,
response: { result: mockResult },
});
const result = await withNetworkClient(
{ providerType },
({ makeRpcCall }) => makeRpcCall(request),
);
expect(result).toStrictEqual(mockResult);
});
});
it(`does not reuse the result of a previous request if it was "${emptyValue}"`, async () => {
const requests = [
{
method,
params: buildMockParams({ blockParamIndex, blockParam }),
},
{
method,
params: buildMockParams({ blockParamIndex, blockParam }),
},
];
const mockResults = [emptyValue, 'some result'];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockRpcCall({
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual(mockResults);
});
});
}
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
}
if (blockParamType === 'block number') {
it('does not reuse the result of a previous request if it was made with different arguments than this one', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
const requests = [
{
method,
params: buildMockParams({ blockParamIndex, blockParam: '0x100' }),
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
},
{
method,
params: buildMockParams({ blockParamIndex, blockParam: '0x200' }),
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
},
];
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first. It doesn't
// matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[0],
response: { result: 'first result' },
});
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[1],
response: { result: 'second result' },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
);
expect(results).toStrictEqual(['first result', 'second result']);
});
});
describe.each(
[
['less than the current block number', '0x200'],
['equal to the curent block number', '0x100'],
],
'%s',
(_nestedDesc, currentBlockNumber) => {
it('makes an additional request to the RPC endpoint', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = {
method,
// Note that `blockParam` is `0x100` here
params: buildMockParams({ blockParamIndex, blockParam }),
};
// The first time a block-cacheable request is made, the latest
// block number is retrieved through the block tracker first.
comms.mockNextBlockTrackerRequest({
blockNumber: currentBlockNumber,
});
comms.mockRpcCall({
request,
response: { result: 'the result' },
});
const result = await withNetworkClient(
{ providerType },
({ makeRpcCall }) => makeRpcCall(request),
);
expect(result).toStrictEqual('the result');
});
});
for (const emptyValue of [null, undefined, '\u003cnil\u003e']) {
if (providerType === 'infura') {
it(`retries up to 10 times if a "${emptyValue}" response is returned, returning successful non-empty response if there is one on the 10th try`, async () => {
const request = {
method,
// Note that `blockParam` is `0x100` here
params: buildMockParams({ blockParamIndex, blockParam }),
};
await withMockedCommunications(
{ providerType },
async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first.
comms.mockNextBlockTrackerRequest({
blockNumber: currentBlockNumber,
});
comms.mockRpcCall({
request,
response: { result: emptyValue },
times: 9,
});
comms.mockRpcCall({
request,
response: { result: 'some value' },
});
const result = await withNetworkClient(
{ providerType },
({ makeRpcCall, clock }) =>
waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
),
);
expect(result).toStrictEqual('some value');
},
);
});
it(`retries up to 10 times if a "${emptyValue}" response is returned, failing after the 10th try`, async () => {
const request = {
method,
// Note that `blockParam` is `0x100` here
params: buildMockParams({ blockParamIndex, blockParam }),
};
const mockResult = emptyValue;
await withMockedCommunications(
{ providerType },
async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first.
comms.mockNextBlockTrackerRequest({
blockNumber: currentBlockNumber,
});
comms.mockRpcCall({
request,
response: { result: mockResult },
times: 10,
});
const promiseForResult = withNetworkClient(
{ providerType },
({ makeRpcCall, clock }) =>
waitForPromiseToBeFulfilledAfterRunningAllTimers(
makeRpcCall(request),
clock,
),
);
await expect(promiseForResult).rejects.toThrow(
'RetryOnEmptyMiddleware - retries exhausted',
);
},
);
});
} else {
it(`does not retry an empty response of "${emptyValue}"`, async () => {
const request = {
method,
// Note that `blockParam` is `0x100` here
params: buildMockParams({ blockParamIndex, blockParam }),
};
const mockResult = emptyValue;
await withMockedCommunications(
{ providerType },
async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first.
comms.mockNextBlockTrackerRequest({
blockNumber: currentBlockNumber,
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: { result: mockResult },
});
const result = await withNetworkClient(
{ providerType },
({ makeRpcCall }) => makeRpcCall(request),
);
expect(result).toStrictEqual(mockResult);
},
);
});
it(`does not reuse the result of a previous request if it was "${emptyValue}"`, async () => {
const requests = [
{
method,
// Note that `blockParam` is `0x100` here
params: buildMockParams({ blockParamIndex, blockParam }),
},
{
method,
// Note that `blockParam` is `0x100` here
params: buildMockParams({ blockParamIndex, blockParam }),
},
];
const mockResults = [emptyValue, { blockHash: '0x100' }];
await withMockedCommunications(
{ providerType },
async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first.
comms.mockNextBlockTrackerRequest({
blockNumber: currentBlockNumber,
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[0],
blockParamIndex,
'0x100',
),
response: { result: mockResults[0] },
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[1],
blockParamIndex,
'0x100',
),
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) =>
makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual(mockResults);
},
);
});
}
}
},
);
describe('greater than the current block number', () => {
it('makes an additional request to the RPC endpoint', async () => {
await withMockedCommunications({ providerType }, async (comms) => {
const request = {
method,
// Note that `blockParam` is `0x100` here
params: buildMockParams({ blockParamIndex, blockParam }),
};
// The first time a block-cacheable request is made, the latest
// block number is retrieved through the block tracker first.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x42' });
comms.mockRpcCall({
request,
response: { result: 'the result' },
});
const result = await withNetworkClient(
{ providerType },
({ makeRpcCall }) => makeRpcCall(request),
);
expect(result).toStrictEqual('the result');
});
});
for (const emptyValue of [null, undefined, '\u003cnil\u003e']) {
it(`does not retry an empty response of "${emptyValue}"`, async () => {
const request = {
method,
// Note that `blockParam` is `0x100` here
params: buildMockParams({ blockParamIndex, blockParam }),
};
const mockResult = emptyValue;
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x42' });
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
request,
blockParamIndex,
'0x100',
),
response: { result: mockResult },
});
const result = await withNetworkClient(
{ providerType },
({ makeRpcCall }) => makeRpcCall(request),
);
expect(result).toStrictEqual(mockResult);
});
});
it(`does not reuse the result of a previous request if it was "${emptyValue}"`, async () => {
const requests = [
{
method,
// Note that `blockParam` is `0x100` here
params: buildMockParams({ blockParamIndex, blockParam }),
},
{
method,
// Note that `blockParam` is `0x100` here
params: buildMockParams({ blockParamIndex, blockParam }),
},
];
const mockResults = [emptyValue, { blockHash: '0x100' }];
await withMockedCommunications({ providerType }, async (comms) => {
// The first time a block-cacheable request is made, the latest block
// number is retrieved through the block tracker first.
comms.mockNextBlockTrackerRequest({ blockNumber: '0x42' });
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[0],
blockParamIndex,
'0x100',
),
response: { result: mockResults[0] },
});
comms.mockRpcCall({
request: buildRequestWithReplacedBlockParam(
requests[1],
blockParamIndex,
'0x100',
),
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
);
expect(results).toStrictEqual(mockResults);
});
});
}
});
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
}
});
describe('given a block tag of "pending"', () => {
const params = buildMockParams({ blockParamIndex, blockParam: 'pending' });
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
it('hits the RPC endpoint on all calls and does not cache anything', async () => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
const requests = [
{ method, params },
{ method, params },
];
const mockResults = ['first result', 'second result'];
await withMockedCommunications({ providerType }, async (comms) => {
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
// The first time a block-cacheable request is made, the latest
// block number is retrieved through the block tracker first. It
// doesn't matter what this is — it's just used as a cache key.
comms.mockNextBlockTrackerRequest();
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[0],
response: { result: mockResults[0] },
});
comms.mockRpcCall({
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
request: requests[1],
response: { result: mockResults[1] },
});
const results = await withNetworkClient(
{ providerType },
({ makeRpcCallsInSeries }) => makeRpcCallsInSeries(requests),
Add initial provider API tests for Infura client (#15556) We are working on migrating the extension to a unified network controller, but before we do so we want to extract some of the existing pieces, specifically `createInfuraClient` and `createJsonRpcClient`, which provide the majority of the behavior exhibited within the provider API that the existing NetworkController exposes. This necessitates that we understand and test that behavior as a whole. With that in mind, this commit starts with the Infura-specific network client and adds some initial functional tests for `createInfuraClient`, specifically covering three pieces of middleware provided by `eth-json-rpc-middleware`: `createNetworkAndChainIdMiddleware`, `createBlockCacheMiddleware`, and `createBlockRefMiddleware`. These tests exercise logic that originate from multiple different places and combine in sometimes surprising ways, and as a result, understanding the nature of the tests can be tricky. I've tried to explain the logic (both of the implementation and the tests) via comments. Additionally, debugging why a certain test is failing is not the most fun thing in the world, so to aid with this, I've added some logging to the underlying packages used when a request passes through the middleware stack. Because some middleware change the request being made, or make new requests altogether, this greatly helps to peel back the curtain, as failures from Nock do not supply much meaningful information on their own. This logging is disabled by default, but can be activated by setting `DEBUG=metamask:*,eth-query DEBUG_COLORS=1` alongside the `jest` command. We use this logging by bumping `eth-block-tracker`, and `eth-json-rpc-middleware`.
2022-09-16 15:18:33 +02:00
);
expect(results).toStrictEqual(mockResults);
});
});
});
}