import { Url } from 'url' ; import { afterAll , afterEach , beforeAll } from '@jest/globals' ; import nock from 'nock' ; import { makeGraphqlSnapshot } from './graphql-snapshot' ; export type { Scope , ReplyHeaders } from 'nock' ; interface RequestLogItem { headers : Record < string , string > ; method : string ; url : string ; body ? : any ; graphql ? : any ; } type BasePath = string | RegExp | Url ; let requestLog = [ ] ; let missingLog = [ ] ; type TestRequest = { method : string ; href : string ; } ; function onMissing ( req , opts ? ) { if ( opts ) { missingLog . push ( `  ${ opts . method } ${ opts . href }` ) ; } else { missingLog . push ( `  ${ req . method } ${ req . href }` ) ; } } export function allUsed ( ) { return nock . isDone ( ) ; } argument throwOnPending export function clear ( throwOnPending = true ) { const isDone = nock . isDone ( ) ; const pending = nock . pendingMocks ( ) ; nock . abortPendingRequests ( ) ; nock . cleanAll ( ) ; const missing = missingLog ; requestLog = [ ] ; missingLog = [ ] ; if ( ! isDone && throwOnPending ) { throw new Error ( `Pending mocks!\n * ${ pending . join ( '\n * ' ) }` ) ; } if ( missing . length && throwOnPending ) { throw new Error ( `Missing mocks!\n * ${ missing . join ( '\n * ' ) }` ) ; } } export function scope ( basePath , options ? ) { return nock ( basePath , options ) . on ( 'request' , ( req ) => { const { headers , method } = req ; const url = req . options ?. href ; const result = { headers , method , url } ; const requestBody = req . requestBodyBuffers ?. [ 0 ] ?. toString ( ) ; if ( requestBody && headers [ 'content-type' ] === 'application/json' ) { try { const body = JSON . parse ( requestBody ) ; const graphql = makeGraphqlSnapshot ( body ) ; if ( graphql ) { result . graphql = graphql ; } else { result . body = body ; } } catch ( e ) { result . body = requestBody ; } } requestLog . push ( result ) ; } ) ; } export function getTrace ( ) { const errorLines = [ ] ; if ( missingLog . length ) { errorLines . push ( 'Missing mocks:' ) ; errorLines . push ( ... missingLog ) ; } if ( ! nock . isDone ( ) ) { errorLines . push ( 'Unused mocks:' ) ; errorLines . push ( ... nock . pendingMocks ( ) . map ( ( x ) => `  ${ x }` ) ) ; } if ( errorLines . length ) { throw new Error ( [ 'Completed requests:' , ... requestLog . map ( ( { method , url } ) => `  ${ method } ${ url }` ) , ... errorLines , ] . join ( '\n' ) ) ; } return requestLog ; } beforeAll ( ( ) => { nock . emitter . on ( 'no match' , onMissing ) ; nock . disableNetConnect ( ) ; } ) ; afterAll ( ( ) => { nock . emitter . removeListener ( 'no match' , onMissing ) ; nock . restore ( ) ; } ) ; afterEach ( ( ) => { clear ( ) ; } ) ;