@@ -6,6 +6,12 @@ import {
66 PutPendingApproval ,
77} from '../../../src/typedRoutes/api/v1/pendingApproval' ;
88import { assertDecode } from './common' ;
9+ import 'should' ;
10+ import 'should-http' ;
11+ import 'should-sinon' ;
12+ import * as sinon from 'sinon' ;
13+ import { BitGo } from 'bitgo' ;
14+ import { setupAgent } from '../../lib/testutil' ;
915/**
1016 * Helper function to test io-ts codec decoding
1117 */
@@ -204,4 +210,263 @@ describe('PendingApproval codec tests', function () {
204210 assert . ok ( PutPendingApproval . response [ 400 ] ) ;
205211 } ) ;
206212 } ) ;
213+
214+ describe ( 'Supertest Integration Tests' , function ( ) {
215+ const agent = setupAgent ( ) ;
216+
217+ const mockApprovedResponse = {
218+ id : 'approval123' ,
219+ state : 'approved' ,
220+ wallet : 'wallet123' ,
221+ enterprise : 'enterprise123' ,
222+ } ;
223+
224+ const mockRejectedResponse = {
225+ id : 'approval123' ,
226+ state : 'rejected' ,
227+ wallet : 'wallet123' ,
228+ enterprise : 'enterprise123' ,
229+ } ;
230+
231+ afterEach ( function ( ) {
232+ sinon . restore ( ) ;
233+ } ) ;
234+
235+ it ( 'should successfully approve pending approval' , async function ( ) {
236+ const approvalId = '123456789abcdef' ;
237+ const requestBody = {
238+ state : 'approved' ,
239+ walletPassphrase : 'mySecurePassword' ,
240+ } ;
241+
242+ const mockPendingApprovalObject = {
243+ approve : sinon . stub ( ) . resolves ( mockApprovedResponse ) ,
244+ reject : sinon . stub ( ) . resolves ( mockRejectedResponse ) ,
245+ } ;
246+
247+ sinon . stub ( BitGo . prototype , 'pendingApprovals' ) . returns ( {
248+ get : sinon . stub ( ) . resolves ( mockPendingApprovalObject ) ,
249+ } as any ) ;
250+
251+ const result = await agent
252+ . put ( `/api/v1/pendingapprovals/${ approvalId } /express` )
253+ . set ( 'Authorization' , 'Bearer test_access_token_12345' )
254+ . set ( 'Content-Type' , 'application/json' )
255+ . send ( requestBody ) ;
256+
257+ assert . strictEqual ( result . status , 200 ) ;
258+ result . body . should . have . property ( 'id' ) ;
259+ result . body . should . have . property ( 'state' ) ;
260+ assert . strictEqual ( result . body . id , mockApprovedResponse . id ) ;
261+ assert . strictEqual ( result . body . state , 'approved' ) ;
262+ assert . strictEqual ( result . body . wallet , mockApprovedResponse . wallet ) ;
263+ assert . strictEqual ( result . body . enterprise , mockApprovedResponse . enterprise ) ;
264+ } ) ;
265+
266+ it ( 'should successfully reject pending approval' , async function ( ) {
267+ const approvalId = '123456789abcdef' ;
268+ const requestBody = {
269+ state : 'rejected' ,
270+ walletPassphrase : 'mySecurePassword' ,
271+ } ;
272+
273+ const mockPendingApprovalObject = {
274+ approve : sinon . stub ( ) . resolves ( mockApprovedResponse ) ,
275+ reject : sinon . stub ( ) . resolves ( mockRejectedResponse ) ,
276+ } ;
277+
278+ sinon . stub ( BitGo . prototype , 'pendingApprovals' ) . returns ( {
279+ get : sinon . stub ( ) . resolves ( mockPendingApprovalObject ) ,
280+ } as any ) ;
281+
282+ const result = await agent
283+ . put ( `/api/v1/pendingapprovals/${ approvalId } /express` )
284+ . set ( 'Authorization' , 'Bearer test_access_token_12345' )
285+ . set ( 'Content-Type' , 'application/json' )
286+ . send ( requestBody ) ;
287+
288+ assert . strictEqual ( result . status , 200 ) ;
289+ result . body . should . have . property ( 'id' ) ;
290+ result . body . should . have . property ( 'state' ) ;
291+ assert . strictEqual ( result . body . id , mockRejectedResponse . id ) ;
292+ assert . strictEqual ( result . body . state , 'rejected' ) ;
293+ assert . strictEqual ( result . body . wallet , mockRejectedResponse . wallet ) ;
294+ assert . strictEqual ( result . body . enterprise , mockRejectedResponse . enterprise ) ;
295+ } ) ;
296+
297+ it ( 'should successfully approve with otp' , async function ( ) {
298+ const approvalId = '123456789abcdef' ;
299+ const requestBody = {
300+ state : 'approved' ,
301+ walletPassphrase : 'mySecurePassword' ,
302+ otp : '123456' ,
303+ } ;
304+
305+ const mockPendingApprovalObject = {
306+ approve : sinon . stub ( ) . resolves ( mockApprovedResponse ) ,
307+ reject : sinon . stub ( ) . resolves ( mockRejectedResponse ) ,
308+ } ;
309+
310+ sinon . stub ( BitGo . prototype , 'pendingApprovals' ) . returns ( {
311+ get : sinon . stub ( ) . resolves ( mockPendingApprovalObject ) ,
312+ } as any ) ;
313+
314+ const result = await agent
315+ . put ( `/api/v1/pendingapprovals/${ approvalId } /express` )
316+ . set ( 'Authorization' , 'Bearer test_access_token_12345' )
317+ . set ( 'Content-Type' , 'application/json' )
318+ . send ( requestBody ) ;
319+
320+ assert . strictEqual ( result . status , 200 ) ;
321+ assert . strictEqual ( result . body . id , mockApprovedResponse . id ) ;
322+ assert . strictEqual ( result . body . state , 'approved' ) ;
323+ } ) ;
324+
325+ it ( 'should successfully approve with xprv' , async function ( ) {
326+ const approvalId = '123456789abcdef' ;
327+ const requestBody = {
328+ state : 'approved' ,
329+ xprv : 'xprvString' ,
330+ } ;
331+
332+ const mockPendingApprovalObject = {
333+ approve : sinon . stub ( ) . resolves ( mockApprovedResponse ) ,
334+ reject : sinon . stub ( ) . resolves ( mockRejectedResponse ) ,
335+ } ;
336+
337+ sinon . stub ( BitGo . prototype , 'pendingApprovals' ) . returns ( {
338+ get : sinon . stub ( ) . resolves ( mockPendingApprovalObject ) ,
339+ } as any ) ;
340+
341+ const result = await agent
342+ . put ( `/api/v1/pendingapprovals/${ approvalId } /express` )
343+ . set ( 'Authorization' , 'Bearer test_access_token_12345' )
344+ . set ( 'Content-Type' , 'application/json' )
345+ . send ( requestBody ) ;
346+
347+ assert . strictEqual ( result . status , 200 ) ;
348+ assert . strictEqual ( result . body . id , mockApprovedResponse . id ) ;
349+ assert . strictEqual ( result . body . state , 'approved' ) ;
350+ } ) ;
351+
352+ it ( 'should successfully preview pending transactions' , async function ( ) {
353+ const approvalId = '123456789abcdef' ;
354+ const requestBody = {
355+ previewPendingTxs : true ,
356+ } ;
357+
358+ const mockPreviewResponse = {
359+ id : 'approval123' ,
360+ txHex : '0x123456789' ,
361+ pendingTransactions : [ ] ,
362+ } ;
363+
364+ const mockPendingApprovalObject = {
365+ approve : sinon . stub ( ) . resolves ( mockPreviewResponse ) ,
366+ reject : sinon . stub ( ) . resolves ( mockPreviewResponse ) ,
367+ } ;
368+
369+ sinon . stub ( BitGo . prototype , 'pendingApprovals' ) . returns ( {
370+ get : sinon . stub ( ) . resolves ( mockPendingApprovalObject ) ,
371+ } as any ) ;
372+
373+ const result = await agent
374+ . put ( `/api/v1/pendingapprovals/${ approvalId } /express` )
375+ . set ( 'Authorization' , 'Bearer test_access_token_12345' )
376+ . set ( 'Content-Type' , 'application/json' )
377+ . send ( requestBody ) ;
378+
379+ assert . strictEqual ( result . status , 200 ) ;
380+ assert . strictEqual ( result . body . id , mockPreviewResponse . id ) ;
381+ assert . strictEqual ( result . body . txHex , mockPreviewResponse . txHex ) ;
382+ result . body . should . have . property ( 'pendingTransactions' ) ;
383+ } ) ;
384+
385+ it ( 'should successfully reject with empty body (defaults to reject)' , async function ( ) {
386+ const approvalId = '123456789abcdef' ;
387+ const requestBody = { } ;
388+
389+ const mockPendingApprovalObject = {
390+ approve : sinon . stub ( ) . resolves ( mockApprovedResponse ) ,
391+ reject : sinon . stub ( ) . resolves ( mockRejectedResponse ) ,
392+ } ;
393+
394+ sinon . stub ( BitGo . prototype , 'pendingApprovals' ) . returns ( {
395+ get : sinon . stub ( ) . resolves ( mockPendingApprovalObject ) ,
396+ } as any ) ;
397+
398+ const result = await agent
399+ . put ( `/api/v1/pendingapprovals/${ approvalId } /express` )
400+ . set ( 'Authorization' , 'Bearer test_access_token_12345' )
401+ . set ( 'Content-Type' , 'application/json' )
402+ . send ( requestBody ) ;
403+
404+ assert . strictEqual ( result . status , 200 ) ;
405+ assert . strictEqual ( result . body . id , mockRejectedResponse . id ) ;
406+ assert . strictEqual ( result . body . state , 'rejected' ) ;
407+ } ) ;
408+ } ) ;
409+
410+ describe ( 'Error Handling Tests' , function ( ) {
411+ const agent = setupAgent ( ) ;
412+
413+ afterEach ( function ( ) {
414+ sinon . restore ( ) ;
415+ } ) ;
416+
417+ it ( 'should handle SDK method failure' , async function ( ) {
418+ const approvalId = '123456789abcdef' ;
419+ const requestBody = {
420+ walletPassphrase : 'mySecurePassword' ,
421+ } ;
422+
423+ const mockPendingApprovalObject = {
424+ approve : sinon . stub ( ) . rejects ( new Error ( 'Failed to update pending approval' ) ) ,
425+ reject : sinon . stub ( ) . rejects ( new Error ( 'Failed to update pending approval' ) ) ,
426+ } ;
427+
428+ sinon . stub ( BitGo . prototype , 'pendingApprovals' ) . returns ( {
429+ get : sinon . stub ( ) . resolves ( mockPendingApprovalObject ) ,
430+ } as any ) ;
431+
432+ const result = await agent
433+ . put ( `/api/v1/pendingapprovals/${ approvalId } /express` )
434+ . set ( 'Authorization' , 'Bearer test_access_token_12345' )
435+ . set ( 'Content-Type' , 'application/json' )
436+ . send ( requestBody ) ;
437+
438+ assert . strictEqual ( result . status , 500 ) ;
439+ result . body . should . have . property ( 'error' ) ;
440+ } ) ;
441+
442+ it ( 'should handle invalid type in request field' , async function ( ) {
443+ const approvalId = '123456789abcdef' ;
444+ const requestBody = {
445+ walletPassphrase : 12345 , // number instead of string
446+ } ;
447+
448+ const result = await agent
449+ . put ( `/api/v1/pendingapprovals/${ approvalId } /express` )
450+ . set ( 'Authorization' , 'Bearer test_access_token_12345' )
451+ . set ( 'Content-Type' , 'application/json' )
452+ . send ( requestBody ) ;
453+
454+ assert . ok ( result . status >= 400 ) ;
455+ } ) ;
456+
457+ it ( 'should handle invalid previewPendingTxs type' , async function ( ) {
458+ const approvalId = '123456789abcdef' ;
459+ const requestBody = {
460+ previewPendingTxs : 'true' , // string instead of boolean
461+ } ;
462+
463+ const result = await agent
464+ . put ( `/api/v1/pendingapprovals/${ approvalId } /express` )
465+ . set ( 'Authorization' , 'Bearer test_access_token_12345' )
466+ . set ( 'Content-Type' , 'application/json' )
467+ . send ( requestBody ) ;
468+
469+ assert . ok ( result . status >= 400 ) ;
470+ } ) ;
471+ } ) ;
207472} ) ;
0 commit comments