content: {-# LANGUAGE OverloadedStrings #-}
  module Test.Hspec.Wai.MatcherSpec (main, spec) where
  
  import           Test.Hspec
  
  import           Network.HTTP.Types
  import           Network.Wai.Test
  
  import           Test.Hspec.Wai.Matcher
  
  main :: IO ()
  main = hspec spec
  
  spec :: Spec
  spec = do
    describe "match" $ do
      context "when both status and body do match" $ do
        it "returns Nothing" $ do
          SResponse status200 [] "" `match` 200
            `shouldBe` Nothing
  
      context "when status does not match" $ do
        it "returns an error message" $ do
          SResponse status404 [] "" `match` 200
            `shouldBe` (Just . unlines) [
              "status mismatch:"
            , "  expected: 200"
            , "  but got:  404"
            ]
  
      context "when body does not match" $ do
        it "returns an error message" $ do
          SResponse status200 [] "foo" `match` "bar"
            `shouldBe` (Just . unlines) [
              "body mismatch:"
            , "  expected: bar"
            , "  but got:  foo"
            ]
  
        context "when one body contains unsafe characters" $ do
          it "uses show for both bodies in the error message" $ do
            SResponse status200 [] "foo\nbar" `match` "bar"
              `shouldBe` (Just . unlines) [
                "body mismatch:"
              , "  expected: \"bar\""
              , "  but got:  \"foo\\nbar\""
              ]
  
      context "when both status and body do not match" $ do
        it "combines error messages" $ do
          SResponse status404 [] "foo" `match` "bar"
            `shouldBe` (Just . unlines) [
              "status mismatch:"
            , "  expected: 200"
            , "  but got:  404"
            , "body mismatch:"
            , "  expected: bar"
            , "  but got:  foo"
            ]
  
      context "when matching headers" $ do
        context "when header is missing" $ do
          it "returns an error message" $ do
            SResponse status200 [] "" `match` 200 {matchHeaders = ["Content-Type" <:> "application/json"]}
              `shouldBe` (Just . unlines) [
                "missing header:"
              , "  Content-Type: application/json"
              , "the actual headers were:"
              ]
  
        context "when multiple headers are missing" $ do
          it  "combines error messages" $ do
            let expectedHeaders = ["Content-Type" <:> "application/json", "Content-Encoding" <:> "chunked"]
            SResponse status200 [(hContentLength, "23")] "" `match` 200 {matchHeaders = expectedHeaders}
              `shouldBe` (Just . unlines) [
                "missing header:"
              , "  Content-Type: application/json"
              , "missing header:"
              , "  Content-Encoding: chunked"
              , "the actual headers were:"
              , "  Content-Length: 23"
              ]
  