content: {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE QuasiQuotes #-}
  
  module URI.ByteString.ExtensionSpec
    ( spec
    ) where
  
  import Test.Hspec
  
  import Control.Exception (ErrorCall, evaluate)
  import Data.List (isInfixOf)
  import URI.ByteString
  import URI.ByteString.Extension
  import URI.ByteString.QQ
  
  spec :: Spec
  spec = do
    describe "IsString Scheme" $ it "works" $ do
      "https" `shouldBe` Scheme "https"
  
    describe "IsString Host" $ it "works" $ do
      "example.com" `shouldBe` Host "example.com"
  
    describe "IsString URIRef Relative" $ it "works" $ do
      "example.com/foo?bar=baz" `shouldBe` [relativeRef|example.com/foo?bar=baz|]
  
    describe "IsString URIRef Absolute" $ it "works" $ do
      "https://example.com/foo?bar=baz"
        `shouldBe` [uri|https://example.com/foo?bar=baz|]
  
    describe "fromText" $ do
      it "returns Just a URI for valid values, as the quasi-quoter would" $ do
        fromText "http://example.com/foo?bar=baz"
          `shouldBe` Just [uri|http://example.com/foo?bar=baz|]
  
      it "returns Nothing for invalid values" $ do
        fromText "Oh my, what did I do?" `shouldBe` Nothing
  
    describe "unsafeFromText" $ do
      it "returns a URI for valid values, as the quasi-quoter would" $ do
        unsafeFromText "http://example.com/foo?bar=baz"
          `shouldBe` [uri|http://example.com/foo?bar=baz|]
  
      it "raises for invalid values" $ do
        evaluate (unsafeFromText "Oh my, what did I do?")
          `shouldThrow` errorContaining "MissingColon"
  
    describe "toText" $ do
      it "serializes the URI to text" $ do
        toText [uri|https://example.com/foo?bar=baz|]
          `shouldBe` "https://example.com/foo?bar=baz"
  
    describe "fromRelative" $ do
      it "makes a URI absolute with a given host" $ do
        fromRelative "ftp" "foo.com" [relativeRef|/bar?baz=bat|]
          `shouldBe` [uri|ftp://foo.com/bar?baz=bat|]
  
    describe "withQuery" $ do
      it "appends a query to a URI" $ do
        let uriWithQuery = [uri|http://example.com|] `withQuery` [("foo", "bar")]
  
        uriWithQuery `shouldBe` [uri|http://example.com?foo=bar|]
  
      it "handles a URI with an existing query" $ do
        let uriWithQuery =
              [uri|http://example.com?foo=bar|] `withQuery` [("baz", "bat")]
  
        uriWithQuery `shouldBe` [uri|http://example.com?foo=bar&baz=bat|]
  
      -- This is arguably testing the internals of another package, but IMO
      -- it's worthwhile to show that you don't (and can't) pre-sanitize when
      -- using this function.
      it "handles santization of the query" $ do
        let uriWithQuery =
              [uri|http://example.com|] `withQuery` [("foo", "bar baz")]
  
        toText uriWithQuery `shouldBe` "http://example.com?foo=bar%20baz"
  
  errorContaining :: String -> Selector ErrorCall
  errorContaining msg = (msg `isInfixOf`) . show
  