import assert from 'assert' ; import * as fetch from 'node-fetch' ; import * as nodeFetch from 'node-fetch' ; import Server from './Server' ; import { Assertion , StatusAssertion , BodyAssertion , HeaderAssertion , AssertionContext , } from './Assertions' ; export default class Test implements PromiseLike < fetch . Response > { private _pServer : Promise < Server > ; private _description : string ; private _result : Promise < fetch . Response > ; private _assertions : Assertion [ ] = [ ] ; constructor ( pServer , url , init ? ) { this . _pServer = pServer ; if ( typeof url === 'string' ) { const method = ( ( init && init . method ) || 'get' ) . toUpperCase ( ) ; this . _description = `${ method } ${ url }` ; } else { const method = ( url . method || ( init && init . method ) || 'get' ) . toUpperCase ( ) ; this . _description = `${ method } ${ url }` ; } this . _result = this . _fetchPriv ( url , init ) ; } private _fetchPriv ( url , init ? ) { return this . _pServer . then ( ( server ) => { let result ; if ( typeof url === 'string' ) { const requestUrl = server . url + url ; result = nodeFetch . default ( requestUrl , init ) ; } else { const request = new nodeFetch . Request ( server . url + url . url , { method : url . method , headers : url . headers , body : url . body , redirect : url . redirect , timeout : url . timeout , compress : url . compress , size : url . size , follow : url . follow , } ) ; result = nodeFetch . default ( request , init ) ; } return result ; } ) ; } param statusCode param body expect ( statusCode , body ? ) ; param header param value expect ( header , value ) ; param body param value expect ( body ) ; expect ( a , b ? ) { if ( typeof a === 'number' ) { this . expectStatus ( a ) ; if ( arguments . length === 2 ) { this . expectBody ( b ) ; } } else if ( typeof a === 'string' && arguments . length === 2 ) { this . expectHeader ( a , b ) ; } else { this . expectBody ( a ) ; } return this ; } param statusCode param statusText expectStatus ( statusCode , statusText ? ) { this . _assertions . push ( new StatusAssertion ( statusCode , statusText ) ) ; return this ; } param expectedBody expectBody ( expectedBody ) { this . _assertions . push ( new BodyAssertion ( expectedBody ) ) ; return this ; } param name param value expectHeader ( name , value ) { this . _assertions . push ( new HeaderAssertion ( name , value ) ) ; return this ; } end ( ) { const expected = { } ; const actual = { } ; const context = { } ; return this . _result . then ( async ( response ) => { const server = await this . _pServer ; server . close ( ) ; let message ; for ( const assertion of this . _assertions ) { const assertionMessage = await assertion . execute ( actual , expected , response , context ) ; message = message || assertionMessage ; } assert . deepStrictEqual ( actual , expected , message ? this . _should ( message ) : undefined ) ; return response ; } , ( err ) => this . _pServer . then ( ( server ) => { server . close ( ) ; throw err ; } ) ) ; } /**
     * Tests are 'thennable', so you can treat them like a Promise and get back
     * the WHAT-WG fetch response.
     */ then ( onfulfilled ? , onrejected ? ) { return this . end ( ) . then ( onfulfilled , onrejected ) ; } private _should ( message ) { return `Request "${ this . _description }" should ${ message }` ; } /**
     * Returns the JSON contents of the response.
     */ async json ( ) { const response = await this . end ( ) ; return await response . json ( ) ; } }