content: module Hreq.Pure.SuccessSpec (spec) where
  
  import Data.Foldable
  import Data.Proxy
  import Test.Hspec
  
  import Hreq.Client
  import Hreq.Core.Client (RequestBody (..))
  import Hreq.Pure.Util (TestState (..), TestUser (..), defaultResponse, runClientPure)
  
  spec :: Spec
  spec = describe "Hreq.SuccessSpec" successSpec
  
  testUser :: TestUser
  testUser = TestUser "Allan" 29
  
  successSpec :: Spec
  successSpec = do
    let baseUrl = HttpDomain "example.com"
        runClientPure' = runClientPure @'Default
  
    describe "Works with request components" $ do
      it "works with paths" $ do
         let x = hreq @("hello" :> RawResponse GET) Empty
             expected = RunClient (appendToPath "hello" defaultRequest) defaultResponse
         runClientPure' baseUrl x `shouldBe` expected
  
      it "works with request body" $ do
        let x = hreq @(JsonBody TestUser :> RawResponse GET) (testUser :. Empty)
            RunClient req _ = runClientPure' baseUrl x
            Just (RequestBodyLBS body, _ )  = reqBody req
        body `shouldBe` mediaEncode (Proxy @JSON) testUser
  
      it "works with query flags" $ do
        let x = hreq @("users" :> QueryFlag "male" :> QueryFlag "old" :> RawResponse GET) Empty
            RunClient req _ = runClientPure @'Default baseUrl x
        reqPath req `shouldBe` "/users"
        toList (reqQueryString req) `shouldBe` [("male", Nothing), ("old", Nothing)]
  
      it "works with capture" $ do
        let x = hreq @(Capture String :> RawResponse GET) ("allan" :. Empty)
            RunClient req _ = runClientPure @'Default baseUrl x
        reqPath req `shouldBe` "/allan"
  
      it "works with captureAll" $ do
        let x = hreq @(CaptureAll String :> RawResponse GET) (["allan", "lukwago"] :. Empty)
            RunClient req _ = runClientPure @'Default baseUrl x
        reqPath req `shouldBe` "/allan/lukwago"
  
      it "works with single query params" $ do
        let x = hreq @(Param "name" String :> RawResponse GET) ("allan" :. Empty)
            RunClient req _ = runClientPure @'Default baseUrl x
        toList (reqQueryString req) `shouldBe` [("name", Just "allan")]
  
      it "works with multi query params" $ do
        let x = hreq @(Param "name" String :> Param "age" Int :> RawResponse GET) ("allan" :. 29 :. Empty)
            RunClient req _ = runClientPure @'Default baseUrl x
        toList (reqQueryString req) `shouldBe`  [("name", Just "allan"), ("age", Just "29")]
  
      it "works with multi query params as a list" $ do
        let x = hreq @(Params '["name" := String, "age" := Int] :> RawResponse GET) ("allan" :. 29 :. Empty)
            RunClient req _ = runClientPure @'Default baseUrl x
        toList (reqQueryString req) `shouldBe`  [("name", Just "allan"), ("age", Just "29")]
  
    describe "Works with response components" $ do
      it "works with single verb requests" $ do
        let x = hreq @(RawResponse GET) Empty
            expected = RunClient defaultRequest defaultResponse
        runClientPure' baseUrl x `shouldBe` expected
  
      it "works with JSON responses" $ do
         let x = hreq @(GetJson TestUser) Empty
             RunClient _ res = runClientPure @'Default baseUrl x
         res `shouldBe` testUser
  