diff --git a/spec/sagas/__snapshots__/config.spec.ts.snap b/spec/reducers/config/__snapshots__/config.spec.ts.snap similarity index 79% rename from spec/sagas/__snapshots__/config.spec.ts.snap rename to spec/reducers/config/__snapshots__/config.spec.ts.snap index c0e9a2f6..fb70e64f 100644 --- a/spec/sagas/__snapshots__/config.spec.ts.snap +++ b/spec/reducers/config/__snapshots__/config.spec.ts.snap @@ -8,7 +8,17 @@ Object { "@@redux-saga/IO": true, "CALL": Object { "args": Array [], - "context": null, + "context": RpcNode { + "client": RPCClient { + "batch": [Function], + "call": [Function], + "createHeaders": [Function], + "decorateRequest": [Function], + "endpoint": "https://node.expanse.tech/", + "headers": Object {}, + }, + "requests": RPCRequests {}, + }, "fn": [Function], }, }, @@ -29,25 +39,9 @@ Object { exports[`handleNodeChangeIntent* should select getCustomNodeConfig and match race snapshot 1`] = ` Object { "@@redux-saga/IO": true, - "RACE": Object { - "lb": Object { - "@@redux-saga/IO": true, - "CALL": Object { - "args": Array [], - "context": null, - "fn": [Function], - }, - }, - "to": Object { - "@@redux-saga/IO": true, - "CALL": Object { - "args": Array [ - 5000, - ], - "context": null, - "fn": [Function], - }, - }, + "SELECT": Object { + "args": Array [], + "selector": [Function], }, } `; diff --git a/spec/sagas/config.spec.ts b/spec/reducers/config/config.spec.ts similarity index 75% rename from spec/sagas/config.spec.ts rename to spec/reducers/config/config.spec.ts index 0f6da828..76f15fc5 100644 --- a/spec/sagas/config.spec.ts +++ b/spec/reducers/config/config.spec.ts @@ -4,31 +4,40 @@ import { call, cancel, fork, put, take, select } from 'redux-saga/effects'; import { cloneableGenerator, createMockTask } from 'redux-saga/utils'; import { toggleOffline, changeNode, changeNodeIntent, setLatestBlock } from 'actions/config'; import { - pollOfflineStatus, - handlePollOfflineStatus, handleNodeChangeIntent, - unsetWeb3Node, - unsetWeb3NodeOnWalletEvent, - equivalentNodeOrDefault, - reload -} from 'sagas/config'; + handlePollOfflineStatus, + pollOfflineStatus, + reload, + switchToNewNode +} from 'sagas/config/node'; import { getNodeId, getNodeConfig, getOffline, getCustomNodeConfigs, - getCustomNetworkConfigs + getCustomNetworkConfigs, + isStaticNodeId, + getStaticNodeFromId, + getNetworkConfigById, + getCustomNodeFromId } from 'selectors/config'; import { Web3Wallet } from 'libs/wallet'; import { RPCNode } from 'libs/nodes'; import { showNotification } from 'actions/notifications'; import { translateRaw } from 'translations'; import { StaticNodeConfig } from 'types/node'; - +import { staticNodesExpectedState } from './nodes/staticNodes.spec'; +import { metaExpectedState } from './meta/meta.spec'; +import { selectedNodeExpectedState } from './nodes/selectedNode.spec'; +import { staticNetworksExpectedState } from './networks/staticNetworks.spec'; +import { customNetworksExpectedState } from './networks/customNetworks.spec'; +import { StaticNetworkConfig } from '../../../shared/types/network'; +import { customNodesExpectedState, firstCustomNodeId } from './nodes/customNodes.spec'; // init module configuredStore.getState(); describe('pollOfflineStatus*', () => { + const { togglingToOffline, togglingToOnline } = metaExpectedState; const nav = navigator as any; const doc = document as any; const data = {} as any; @@ -38,7 +47,6 @@ describe('pollOfflineStatus*', () => { ping: jest.fn() } }; - const isOffline = true; const raceSuccess = { pingSucceeded: true, timeout: false @@ -88,14 +96,14 @@ describe('pollOfflineStatus*', () => { it('should call delay if document is hidden', () => { data.hiddenDoc = data.gen.clone(); doc.hidden = true; - expect(data.hiddenDoc.next(!isOffline).value).toEqual(call(delay, 1000)); + expect(data.hiddenDoc.next(togglingToOnline.offline).value).toEqual(call(delay, 1000)); doc.hidden = false; }); it('should race pingSucceeded and timeout', () => { data.isOfflineClone = data.gen.clone(); data.shouldDelayClone = data.gen.clone(); - expect(data.gen.next(isOffline).value).toMatchSnapshot(); + expect(data.gen.next(togglingToOffline.offline).value).toMatchSnapshot(); }); it('should toggle offline and show notification if navigator disagrees with isOffline and ping succeeds', () => { @@ -106,11 +114,11 @@ describe('pollOfflineStatus*', () => { }); it('should toggle offline and show notification if navigator agrees with isOffline and ping fails', () => { - nav.onLine = isOffline; - expect(data.isOfflineClone.next(!isOffline)); + nav.onLine = togglingToOffline.offline; + expect(data.isOfflineClone.next(togglingToOnline.offline)); expect(data.isOfflineClone.next(raceFailure).value).toMatchSnapshot(); expect(data.isOfflineClone.next().value).toEqual(put(toggleOffline())); - nav.onLine = !isOffline; + nav.onLine = togglingToOnline.offline; }); }); @@ -136,17 +144,15 @@ describe('handleNodeChangeIntent*', () => { let originalRandom; // normal operation variables - const defaultNode = configInitialState.nodeSelection; - const defaultNodeConfig = NODES[defaultNode]; - const customNetworkConfigs = []; - const defaultNodeNetwork = NETWORKS[defaultNodeConfig.network]; - const newNode = Object.keys(NODES).reduce( - (acc, cur) => (NODES[cur].network !== defaultNodeConfig.network ? cur : acc) + const defaultNodeId = selectedNodeExpectedState.initialState.nodeId; + const defaultNodeConfig: StaticNodeConfig = staticNodesExpectedState.initialState[defaultNodeId]; + const newNodeId = Object.keys(staticNodesExpectedState.initialState).reduce( + (acc, cur) => + staticNodesExpectedState.initialState[cur].network !== defaultNodeConfig.network ? cur : acc ); - const newNodeConfig = NODES[newNode]; - const newNodeNetwork = NETWORKS[newNodeConfig.network]; + const newNodeConfig: StaticNodeConfig = staticNodesExpectedState.initialState[newNodeId]; - const changeNodeIntentAction = changeNodeIntent(newNode); + const changeNodeIntentAction = changeNodeIntent(newNodeId); const latestBlock = '0xa'; const raceSuccess = { lb: latestBlock @@ -159,9 +165,10 @@ describe('handleNodeChangeIntent*', () => { data.gen = cloneableGenerator(handleNodeChangeIntent)(changeNodeIntentAction); function shouldBailOut(gen, nextVal, errMsg) { - expect(gen.next(nextVal).value).toEqual(put(showNotification('danger', errMsg, 5000))); + expect(gen.next(nextVal).value).toEqual(select(getNodeId)); + expect(gen.next(defaultNodeId).value).toEqual(put(showNotification('danger', errMsg, 5000))); expect(gen.next().value).toEqual( - put(changeNode(defaultNode, defaultNodeConfig, defaultNodeNetwork)) + put(changeNode({ networkId: defaultNodeConfig.network, nodeId: defaultNodeId })) ); expect(gen.next().done).toEqual(true); } @@ -175,34 +182,38 @@ describe('handleNodeChangeIntent*', () => { Math.random = originalRandom; }); - it('should select getNode', () => { - expect(data.gen.next().value).toEqual(select(getNodeId)); + it('should select is static node', () => { + expect(data.gen.next().value).toEqual(select(isStaticNodeId, newNodeId)); }); it('should select nodeConfig', () => { - expect(data.gen.next(defaultNode).value).toEqual(select(getNodeConfig)); + expect(data.gen.next(defaultNodeId).value).toEqual(select(getNodeConfig)); }); - it('should select getCustomNetworkConfigs', () => { - expect(data.gen.next(defaultNodeConfig).value).toEqual(select(getCustomNetworkConfigs)); + it('should select getStaticNodeFromId', () => { + expect(data.gen.next(defaultNodeConfig).value).toEqual(select(getStaticNodeFromId, newNodeId)); }); it('should race getCurrentBlock and delay', () => { - expect(data.gen.next(customNetworkConfigs).value).toMatchSnapshot(); + expect(data.gen.next(newNodeConfig).value).toMatchSnapshot(); }); it('should show error and revert to previous node if check times out', () => { data.clone1 = data.gen.clone(); shouldBailOut(data.clone1, raceFailure, translateRaw('ERROR_32')); }); - + it('should getNetworkConfigById', () => { + expect(data.gen.next(raceSuccess).value).toEqual( + select(getNetworkConfigById, newNodeConfig.network) + ); + }); it('should put setLatestBlock', () => { expect(data.gen.next(raceSuccess).value).toEqual(put(setLatestBlock(latestBlock))); }); it('should put changeNode', () => { expect(data.gen.next().value).toEqual( - put(changeNode(changeNodeIntentAction.payload, newNodeConfig, newNodeNetwork)) + put(changeNode({ networkId: newNodeConfig.network, nodeId: newNodeId })) ); }); @@ -216,41 +227,40 @@ describe('handleNodeChangeIntent*', () => { }); // custom node variables - const customNodeConfigs = [ - { - name: 'name', - url: 'url', - port: 443, - network: 'network' - } - ]; - const customNodeIdFound = 'url:443'; - const customNodeIdNotFound = 'notFound'; - const customNodeAction = changeNodeIntent(customNodeIdFound); - const customNodeNotFoundAction = changeNodeIntent(customNodeIdNotFound); + const customNodeConfigs = customNodesExpectedState.addFirstCustomNode; + const customNodeAction = changeNodeIntent(firstCustomNodeId); data.customNode = handleNodeChangeIntent(customNodeAction); - data.customNodeNotFound = handleNodeChangeIntent(customNodeNotFoundAction); // test custom node it('should select getCustomNodeConfig and match race snapshot', () => { data.customNode.next(); - data.customNode.next(defaultNode); - data.customNode.next(defaultNodeConfig); - expect(data.customNode.next(customNetworkConfigs).value).toEqual(select(getCustomNodeConfigs)); + data.customNode.next(false); + expect(data.customNode.next(defaultNodeConfig).value).toEqual( + select(getCustomNodeFromId, firstCustomNodeId) + ); expect(data.customNode.next(customNodeConfigs).value).toMatchSnapshot(); }); + const customNodeIdNotFound = firstCustomNodeId + 'notFound'; + const customNodeNotFoundAction = changeNodeIntent(customNodeIdNotFound); + data.customNodeNotFound = handleNodeChangeIntent(customNodeNotFoundAction); + // test custom node not found it('should handle unknown / missing custom node', () => { data.customNodeNotFound.next(); - data.customNodeNotFound.next(defaultNode); - data.customNodeNotFound.next(defaultNodeConfig); - expect(data.customNodeNotFound.next(customNetworkConfigs).value).toEqual( - select(getCustomNodeConfigs) + data.customNodeNotFound.next(false); + }); + + it('should blah', () => { + expect(data.customNodeNotFound.next(defaultNodeConfig).value).toEqual( + select(getCustomNodeFromId, customNodeIdNotFound) ); + }); + + it('should blahah', () => { shouldBailOut( data.customNodeNotFound, - customNodeConfigs, + null, `Attempted to switch to unknown node '${customNodeNotFoundAction.payload}'` ); });