purescript-httpurple/Test/HTTPure/SpecHelpers.purs
2017-07-10 12:06:14 -07:00

100 lines
3.5 KiB
Haskell

module HTTPure.SpecHelpers where
import Prelude (Unit, bind, discard, pure, unit, ($), (<>), (>>=), (<<<))
import Control.Monad.Aff as Aff
import Control.Monad.Eff as Eff
import Control.Monad.Eff.Exception as Exception
import Control.Monad.ST as ST
import Node.Encoding as Encoding
import Node.HTTP as HTTP
import Node.HTTP.Client as HTTPClient
import Node.Stream as Stream
import Node.StreamBuffer as StreamBuffer
import Test.Spec as Spec
import Test.Spec.Runner as Runner
import Unsafe.Coerce as Coerce
import HTTPure.HTTPureM as HTTPureM
import HTTPure.Request as Request
import HTTPure.Response as Response
-- | A type alias encapsulating all effect types used in making a mock request.
type MockRequestEffects e s =
( st :: ST.ST s
, exception :: Exception.EXCEPTION
, http :: HTTP.HTTP | e
)
-- | A type alias encapsulating all effect types used in tests.
type TestEffects s =
Runner.RunnerEffects (
HTTPureM.HTTPureEffects (
MockRequestEffects
( sb :: StreamBuffer.STREAM_BUFFER
) s
)
)
-- | The type for integration tests.
type Test = forall s. Spec.Spec (TestEffects s) Unit
-- | The type for the entire test suite.
type TestSuite = forall s. Eff.Eff (TestEffects s) Unit
-- | Given an HTTPClient.Request, close the request stream so the request can be
-- | fired.
endRequest :: forall e.
HTTPClient.Request -> Eff.Eff (http :: HTTP.HTTP | e) Unit
endRequest request = Stream.end (HTTPClient.requestAsStream request) $ pure unit
-- | Given a URL, a failure handler, and a success handler, create an HTTP
-- | client request.
getResponse :: forall e.
String ->
(Exception.Error -> Eff.Eff (http :: HTTP.HTTP | e) Unit) ->
(HTTPClient.Response -> Eff.Eff (http :: HTTP.HTTP | e) Unit) ->
Eff.Eff (http :: HTTP.HTTP | e) Unit
getResponse url _ success = HTTPClient.requestFromURI url success >>= endRequest
-- | Given an ST String buffer and a new string, concatenate that new string
-- | onto the ST buffer.
concat :: forall e s.
ST.STRef s String -> String -> Eff.Eff (st :: ST.ST s | e) Unit
concat buf new = ST.modifySTRef buf (\old -> old <> new) >>= (\_ -> pure unit)
-- | Convert a request to an Aff containing the string with the response body.
toString :: forall e s.
HTTPClient.Response -> Aff.Aff (MockRequestEffects e s) String
toString response = Aff.makeAff \_ success -> do
let stream = HTTPClient.responseAsStream response
buf <- ST.newSTRef ""
Stream.onDataString stream Encoding.UTF8 $ concat buf
Stream.onEnd stream $ ST.readSTRef buf >>= success
-- | Run an HTTP GET with the given url and return an Aff that contains the
-- | string with the response body.
get :: forall e s. String -> Aff.Aff (MockRequestEffects e s) String
get url = Aff.makeAff (getResponse url) >>= toString
-- | Mock a Request object
mockRequest :: forall e. String -> Request.Request e
mockRequest = Request.fromHTTPRequest <<< mockHTTPRequest
-- | Mock a Request object
mockResponse :: forall e1 e2.
Stream.Writable () (sb :: StreamBuffer.STREAM_BUFFER | e1) ->
Response.Response e2
mockResponse = Response.fromHTTPResponse <<< mockHTTPResponse
-- | Mock an HTTP Request object
mockHTTPRequest :: String -> HTTP.Request
mockHTTPRequest url = Coerce.unsafeCoerce { url: url }
-- | Mock an HTTP Request object
mockHTTPResponse :: forall e1.
Stream.Writable () (sb :: StreamBuffer.STREAM_BUFFER | e1) ->
HTTP.Response
mockHTTPResponse = Coerce.unsafeCoerce