From d6cf809bccfa38241fac6e27043186c6efb234d8 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 23 Jan 2023 10:52:42 -0330 Subject: [PATCH] Setup network controller mocks per-test (#17250) The network controller unit test network mocks are now setup for each test. This makes modifying network behavior on a per-test basis easier, and makes it more clear which test relies upon which mocks. --- .../controllers/network/network-controller.js | 2 + .../network/network-controller.test.js | 82 ++++++++++++++----- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/app/scripts/controllers/network/network-controller.js b/app/scripts/controllers/network/network-controller.js index b525d3c3d..20be4b8b3 100644 --- a/app/scripts/controllers/network/network-controller.js +++ b/app/scripts/controllers/network/network-controller.js @@ -75,6 +75,8 @@ export const NETWORK_EVENTS = { }; export default class NetworkController extends EventEmitter { + static defaultProviderConfig = defaultProviderConfig; + /** * Construct a NetworkController. * diff --git a/app/scripts/controllers/network/network-controller.test.js b/app/scripts/controllers/network/network-controller.test.js index 6fc0968ef..214bbfd80 100644 --- a/app/scripts/controllers/network/network-controller.test.js +++ b/app/scripts/controllers/network/network-controller.test.js @@ -1,5 +1,6 @@ import nock from 'nock'; import { deferredPromise } from '../../lib/util'; +import { NETWORK_TYPES } from '../../../../shared/constants/network'; import NetworkController, { NETWORK_EVENTS } from './network-controller'; /** @@ -80,26 +81,51 @@ async function withController(...args) { } } +/** + * Setup Nock mocks for the block tracker. + * + * @param {object} options - Options. + * @param {NETWORK_TYPES} options.networkType - The network type to mock. + * @param {object} options.block - The mock block to return. + * @param {Record} options.requests - A set of methods to setup + * mocks for, mapped to the number of times to expect each request. + */ +function setupMockRpcBlockResponses({ + networkType = NetworkController.defaultProviderConfig.type, + block = BLOCK, + requests = { eth_getBlockByNumber: 1, eth_blockNumber: 1 }, +} = {}) { + const rpcUrl = + networkType === NETWORK_TYPES.RPC + ? 'http://localhost:8545/' + : `https://${networkType}.infura.io/v3/${defaultControllerOptions.infuraProjectId}`; + const { origin, pathname } = new URL(rpcUrl); + + const scope = nock(origin); + + if (requests.eth_getBlockByNumber) { + scope + .post( + pathname, + (body) => + body.method === 'eth_getBlockByNumber' && + body.params[0] === block.number, + ) + .times(requests.eth_getBlockByNumber) + .reply(200, () => JSON.stringify(constructSuccessfulRpcResponse(block))); + } + if (requests.eth_blockNumber) { + scope + .post(pathname, (body) => body.method === 'eth_blockNumber') + .times(requests.eth_blockNumber) + .reply(200, () => + JSON.stringify(constructSuccessfulRpcResponse(block.number)), + ); + } +} + describe('NetworkController', () => { describe('controller', () => { - let latestBlock; - - beforeEach(() => { - latestBlock = BLOCK; - nock('http://localhost:8545') - .persist() - .post(/.*/u) - .reply(200, () => - JSON.stringify(constructSuccessfulRpcResponse(latestBlock)), - ); - nock('https://mainnet.infura.io') - .persist() - .post('/v3/foo') - .reply(200, () => - JSON.stringify(constructSuccessfulRpcResponse(latestBlock)), - ); - }); - afterEach(() => { nock.cleanAll(); }); @@ -107,6 +133,7 @@ describe('NetworkController', () => { describe('#provider', () => { it('provider should be updatable without reassignment', async () => { await withController(async ({ controller }) => { + setupMockRpcBlockResponses(); await controller.initializeProvider(); const providerProxy = controller.getProviderAndBlockTracker().provider; @@ -127,6 +154,7 @@ describe('NetworkController', () => { it('should stop the block tracker for the current selected network', async () => { await withController(async ({ controller }) => { + setupMockRpcBlockResponses(); await controller.initializeProvider(); const { blockTracker } = controller.getProviderAndBlockTracker(); // The block tracker starts running after a listener is attached @@ -154,6 +182,8 @@ describe('NetworkController', () => { describe('#setProviderType', () => { it('should update provider.type', async () => { await withController(async ({ controller }) => { + setupMockRpcBlockResponses({ networkType: NETWORK_TYPES.RPC }); + setupMockRpcBlockResponses({ networkType: NETWORK_TYPES.MAINNET }); await controller.initializeProvider(); controller.setProviderType('mainnet'); const { type } = controller.getProviderConfig(); @@ -163,6 +193,8 @@ describe('NetworkController', () => { it('should set the network to loading', async () => { await withController(async ({ controller }) => { + setupMockRpcBlockResponses({ networkType: NETWORK_TYPES.RPC }); + setupMockRpcBlockResponses({ networkType: NETWORK_TYPES.MAINNET }); await controller.initializeProvider(); controller.setProviderType('mainnet'); @@ -179,7 +211,7 @@ describe('NetworkController', () => { describe('#getEIP1559Compatibility', () => { it('should return false when baseFeePerGas is not in the block header', async () => { await withController(async ({ controller }) => { - latestBlock = PRE_1559_BLOCK; + setupMockRpcBlockResponses({ block: PRE_1559_BLOCK }); await controller.initializeProvider(); const supportsEIP1559 = await controller.getEIP1559Compatibility(); expect(supportsEIP1559).toStrictEqual(false); @@ -188,6 +220,7 @@ describe('NetworkController', () => { it('should return true when baseFeePerGas is in block header', async () => { await withController(async ({ controller }) => { + setupMockRpcBlockResponses(); await controller.initializeProvider(); const supportsEIP1559 = await controller.getEIP1559Compatibility(); expect(supportsEIP1559).toStrictEqual(true); @@ -196,6 +229,7 @@ describe('NetworkController', () => { it('should store EIP1559 support in state to reduce calls to _getLatestBlock', async () => { await withController(async ({ controller }) => { + setupMockRpcBlockResponses(); await controller.initializeProvider(); await controller.getEIP1559Compatibility(); const supportsEIP1559 = await controller.getEIP1559Compatibility(); @@ -205,12 +239,20 @@ describe('NetworkController', () => { it('should clear stored EIP1559 support when changing networks', async () => { await withController(async ({ controller }) => { + setupMockRpcBlockResponses({ networkType: NETWORK_TYPES.RPC }); + setupMockRpcBlockResponses({ + networkType: NETWORK_TYPES.MAINNET, + block: PRE_1559_BLOCK, + requests: { + eth_blockNumber: 2, + eth_getBlockByNumber: 1, + }, + }); await controller.initializeProvider(); await controller.getEIP1559Compatibility(); expect(controller.networkDetails.getState().EIPS[1559]).toStrictEqual( true, ); - latestBlock = PRE_1559_BLOCK; await new Promise((resolve) => { controller.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, () => { resolve();