Skip to content

Commit 64a241c

Browse files
authored
Merge pull request #221 from BitGo/WAL-1489/recovery-tests-refactoring
refactor: enhance recovery-related tests with API mocks
2 parents 0c4bb0d + bc02141 commit 64a241c

5 files changed

Lines changed: 494 additions & 401 deletions

File tree

src/__tests__/api/master/musigRecovery.test.ts

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import 'should';
22
import sinon from 'sinon';
33

4-
import { AbstractEthLikeNewCoins } from '@bitgo-beta/abstract-eth';
54
import nock from 'nock';
65
import * as request from 'supertest';
76
import { app as expressApp } from '../../../masterBitGoExpressApp';
87
import { AppMode, MasterExpressConfig, TlsMode } from '../../../shared/types';
98
import { data as ethRecoveryData } from '../../mocks/ethRecoveryMusigMockData';
9+
import { BitGoAPITestHarness } from './testUtils';
1010

1111
describe('POST /api/v1/:coin/advancedwallet/recovery', () => {
1212
let agent: request.SuperAgentTest;
@@ -41,23 +41,51 @@ describe('POST /api/v1/:coin/advancedwallet/recovery', () => {
4141
afterEach(() => {
4242
nock.cleanAll();
4343
sinon.restore();
44+
BitGoAPITestHarness.clearConstantsCache();
4445
});
4546

4647
it('should get the tx hex for broadcasting from eve on musig recovery ', async () => {
47-
// sdk call mock on mbe
48-
const recoverStub = sinon
49-
.stub(AbstractEthLikeNewCoins.prototype, 'recover')
50-
.resolves(ethRecoveryData.unsignedSweepPrebuildTx);
48+
const backupKeyAddress = '0x30edc88a77598833f58947638b2ac3d5713d9845';
49+
const apiKey = 'etherscan-api-token';
50+
const etherscanBase = 'https://api.etherscan.io';
51+
const chainid = '560048';
52+
53+
// Etherscan calls to get the nonce, balance, and sequence ID for the backup key and wallet contract
54+
const txlistNock = nock(etherscanBase)
55+
.get(
56+
`/v2/api?chainid=${chainid}&module=account&action=txlist&address=${backupKeyAddress}&apikey=${apiKey}`,
57+
)
58+
.twice()
59+
.reply(200, { result: [] });
60+
61+
const backupBalanceNock = nock(etherscanBase)
62+
.get(
63+
`/v2/api?chainid=${chainid}&module=account&action=balance&address=${backupKeyAddress}&apikey=${apiKey}`,
64+
)
65+
.reply(200, { result: '10000000000000000' });
66+
67+
const walletBalanceNock = nock(etherscanBase)
68+
.get(
69+
`/v2/api?chainid=${chainid}&module=account&action=balance&address=${ethRecoveryData.walletContractAddress}&apikey=${apiKey}`,
70+
)
71+
.reply(200, { result: '1000000000000000000' });
72+
73+
const sequenceIdNock = nock(etherscanBase)
74+
.get(
75+
`/v2/api?chainid=${chainid}&module=proxy&action=eth_call&to=${ethRecoveryData.walletContractAddress}&data=a0b7967b&tag=latest&apikey=${apiKey}`,
76+
)
77+
.reply(200, {
78+
result: '0x0000000000000000000000000000000000000000000000000000000000000001',
79+
});
5180

52-
// the call to eve.recoverWallet(...)
53-
// that contains the calls to sdk.signTransaction
5481
const eveRecoverWalletNock = nock(advancedWalletManagerUrl)
55-
.post(`/api/${coin}/multisig/recovery`, {
56-
userPub: ethRecoveryData.userKey,
57-
backupPub: ethRecoveryData.backupKey,
58-
unsignedSweepPrebuildTx: ethRecoveryData.unsignedSweepPrebuildTx,
59-
coinSpecificParams: undefined,
60-
walletContractAddress: ethRecoveryData.walletContractAddress,
82+
.post(`/api/${coin}/multisig/recovery`, (body) => {
83+
return (
84+
body.userPub === ethRecoveryData.userKey &&
85+
body.backupPub === ethRecoveryData.backupKey &&
86+
body.walletContractAddress === ethRecoveryData.walletContractAddress &&
87+
body.unsignedSweepPrebuildTx !== undefined
88+
);
6189
})
6290
.reply(200, {
6391
txHex: ethRecoveryData.txHexFullSigned,
@@ -74,13 +102,16 @@ describe('POST /api/v1/:coin/advancedwallet/recovery', () => {
74102
walletContractAddress: ethRecoveryData.walletContractAddress,
75103
bitgoPub: '',
76104
},
77-
apiKey: 'etherscan-api-token',
105+
apiKey,
78106
recoveryDestinationAddress: ethRecoveryData.recoveryDestinationAddress,
79107
});
80108

81109
response.status.should.equal(200);
82110
response.body.should.have.property('txHex', ethRecoveryData.txHexFullSigned);
83-
sinon.assert.calledOnce(recoverStub);
111+
txlistNock.isDone().should.be.true();
112+
backupBalanceNock.isDone().should.be.true();
113+
walletBalanceNock.isDone().should.be.true();
114+
sequenceIdNock.isDone().should.be.true();
84115
eveRecoverWalletNock.done();
85116
});
86117

src/__tests__/api/master/nonRecovery.test.ts

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
import 'should';
22
import * as request from 'supertest';
33
import nock from 'nock';
4+
import sinon from 'sinon';
45
import { app as expressApp } from '../../../masterBitGoExpressApp';
56
import { AppMode, MasterExpressConfig, TlsMode } from '../../../shared/types';
6-
import sinon from 'sinon';
7-
import * as middleware from '../../../shared/middleware';
8-
import * as masterMiddleware from '../../../masterBitgoExpress/middleware/middleware';
9-
import { BitGoRequest } from '../../../types/request';
10-
import { BitGoAPI } from '@bitgo-beta/sdk-api';
11-
import { AdvancedWalletManagerClient } from '../../../masterBitgoExpress/clients/advancedWalletManagerClient';
7+
import { BitGoAPITestHarness } from './testUtils';
128

139
describe('Non Recovery Tests', () => {
1410
let agent: request.SuperAgentTest;
15-
let mockBitgo: BitGoAPI;
1611
const advancedWalletManagerUrl = 'http://advancedwalletmanager.invalid';
1712
const accessToken = 'test-token';
1813
const config: MasterExpressConfig = {
@@ -31,45 +26,21 @@ describe('Non Recovery Tests', () => {
3126
recoveryMode: false,
3227
};
3328

34-
beforeEach(() => {
29+
before(() => {
3530
nock.disableNetConnect();
3631
nock.enableNetConnect('127.0.0.1');
3732

38-
// Create mock BitGo instance with base functionality
39-
mockBitgo = new BitGoAPI({ env: 'test' });
40-
41-
// Setup middleware stubs before creating app
42-
sinon.stub(middleware, 'prepareBitGo').callsFake(() => (req, res, next) => {
43-
(req as BitGoRequest<MasterExpressConfig>).bitgo = mockBitgo;
44-
(req as BitGoRequest<MasterExpressConfig>).config = config;
45-
next();
46-
});
47-
48-
// Create app after middleware is stubbed
4933
const app = expressApp(config);
5034
agent = request.agent(app);
5135
});
5236

5337
afterEach(() => {
5438
nock.cleanAll();
5539
sinon.restore();
40+
BitGoAPITestHarness.clearConstantsCache();
5641
});
5742

5843
describe('Recovery', () => {
59-
const coin = 'tbtc';
60-
61-
beforeEach(() => {
62-
sinon.stub(masterMiddleware, 'validateMasterExpressConfig').callsFake((req, res, next) => {
63-
(req as BitGoRequest<MasterExpressConfig>).params = { coin };
64-
(req as BitGoRequest<MasterExpressConfig>).awmUserClient = new AdvancedWalletManagerClient(
65-
config,
66-
coin,
67-
);
68-
next();
69-
return undefined;
70-
});
71-
});
72-
7344
it('should fail to run mbe recovery if not in recovery mode', async () => {
7445
const coin = 'tbtc';
7546
const userPub = 'xpub_user';

0 commit comments

Comments
 (0)