import { Disposable } from '@typed/disposable' import { Either, fromLeft, fromRight, isLeft, Left, Right } from '@typed/either' import { isPromiseLike } from '@typed/logic' import { Json } from './Json' import { HttpCallbacks, HttpOptions, HttpResponse, TestHttpEnv } from './types' /** * Create a test-friendly http environment * @param testHttp :: (url -> HttpOptions -> Either Error HttpResponse) * @param timer :: Timer */ export function createTestHttpEnv( testHttp: ( url: string, options: HttpOptions, ) => Either | PromiseLike>, ): TestHttpEnv { const responses: Either[] = [] function http(url: string, options: HttpOptions, callbacks: HttpCallbacks): Disposable { const { success, failure } = callbacks function getResponse() { const disposable = Disposable.lazy() function onResponse(response: Either) { responses.push(response) if (isLeft(response)) { return disposable.addDisposable(failure(fromLeft(response))) } disposable.addDisposable(success(fromRight(response))) } const response = testHttp(url, options) if (isPromiseLike(response)) { response.then(onResponse) } else { onResponse(response) } return disposable } return getResponse() } return { http, getResponses: () => responses.slice(), } } export function createSuccessfulResponse(options: Partial> = {}) { return Right.of(createHttpResponse(options)) } export function createFailedResponse(error: Error) { return Left.of(error) } export function createHttpResponse(options: Partial> = {}): HttpResponse { const response: HttpResponse = { status: 200, statusText: 'OK', responseText: '', headers: {}, ...options, } return response } export function createJsonResponse( jsonReadyValue: A, options: Partial> = {}, ): HttpResponse { const responseText = JSON.stringify(jsonReadyValue) return createHttpResponse({ ...options, headers: { 'Content-Type': 'application/json', ...options.headers }, responseText, }) }