hspec-wai-json 0.6.1 → 0.7.0
raw patch · 3 files changed
+63/−28 lines, 3 filesdep ~hspec-waiPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hspec-wai
API changes (from Hackage documentation)
- Test.Hspec.Wai.JSON: instance FromValue ByteString
- Test.Hspec.Wai.JSON: instance FromValue ResponseMatcher
+ Test.Hspec.Wai.JSON: instance Test.Hspec.Wai.JSON.FromValue Data.ByteString.Lazy.Internal.ByteString
+ Test.Hspec.Wai.JSON: instance Test.Hspec.Wai.JSON.FromValue Test.Hspec.Wai.Matcher.ResponseMatcher
Files
- hspec-wai-json.cabal +7/−5
- src/Test/Hspec/Wai/JSON.hs +15/−11
- test/Test/Hspec/Wai/JSONSpec.hs +41/−12
hspec-wai-json.cabal view
@@ -1,9 +1,9 @@--- This file has been generated from package.yml by hpack version 0.2.0.+-- This file has been generated from package.yaml by hpack version 0.15.0. -- -- see: https://github.com/sol/hpack name: hspec-wai-json-version: 0.6.1+version: 0.7.0 homepage: https://github.com/hspec/hspec-wai#readme bug-reports: https://github.com/hspec/hspec-wai/issues license: MIT@@ -25,12 +25,13 @@ location: https://github.com/hspec/hspec-wai library- hs-source-dirs: src+ hs-source-dirs:+ src exposed-modules: Test.Hspec.Wai.JSON build-depends: base == 4.*- , hspec-wai == 0.6.*+ , hspec-wai == 0.7.* , bytestring , template-haskell , aeson@@ -41,7 +42,8 @@ test-suite spec type: exitcode-stdio-1.0- hs-source-dirs: test+ hs-source-dirs:+ test main-is: Spec.hs other-modules: Test.Hspec.Wai.JSONSpec
src/Test/Hspec/Wai/JSON.hs view
@@ -9,13 +9,14 @@ import Data.List import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy as BL-import Data.Aeson (Value, encode)+import Data.Aeson (Value, decode, encode) import Data.Aeson.QQ import qualified Data.CaseInsensitive as CI import Language.Haskell.TH.Quote import Test.Hspec.Wai import Test.Hspec.Wai.Internal (formatHeader)+import Test.Hspec.Wai.Matcher -- $setup -- The examples in this module assume that you have the @QuasiQuotes@ language@@ -56,19 +57,22 @@ fromValue :: Value -> a instance FromValue ResponseMatcher where- fromValue v = ResponseMatcher 200 [MatchHeader p] (Just body)+ fromValue = ResponseMatcher 200 [MatchHeader p] . equalsJSON where- body = fromValue v-- permissibleHeaders = addIfASCII ("Content-Type", "application/json") [("Content-Type", "application/json; charset=utf-8")]-- addIfASCII h = if BL.all (< 128) body then (h :) else id-- mkCI = map (second CI.mk)-- p headers = if any (`elem` mkCI permissibleHeaders) (mkCI headers)+ p headers body = if any (`elem` mkCI permissibleHeaders) (mkCI headers) then Nothing else (Just . unlines) ("missing header:" : (intersperse " OR" $ map formatHeader permissibleHeaders))+ where+ mkCI = map (second CI.mk)+ permissibleHeaders = addIfASCII ("Content-Type", "application/json") [("Content-Type", "application/json; charset=utf-8")]+ addIfASCII h = if BL.all (< 128) body then (h :) else id++equalsJSON :: Value -> MatchBody+equalsJSON expected = MatchBody matcher+ where+ matcher headers actualBody = case decode actualBody of+ Just actual | actual == expected -> Nothing+ _ -> let MatchBody m = bodyEquals (encode expected) in m headers actualBody instance FromValue ByteString where fromValue = encode
test/Test/Hspec/Wai/JSONSpec.hs view
@@ -1,9 +1,11 @@-{-# LANGUAGE OverloadedStrings, QuasiQuotes #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE OverloadedStrings #-} module Test.Hspec.Wai.JSONSpec (main, spec) where import Test.Hspec+import Data.String -import Test.Hspec.Wai+import Test.Hspec.Wai hiding (pending) import Test.Hspec.Wai.JSON main :: IO ()@@ -12,33 +14,60 @@ spec :: Spec spec = do describe "json" $ do+ context "when matching body" $ do+ let MatchBody matcher = matchBody [json|{foo: 23}|]++ it "ignores whitespace" $ do+ let+ actual = fromString $ unlines [+ "{"+ , show ("foo" :: String) ++ " : 23"+ , "}"+ ]+ matcher [] actual `shouldBe` Nothing++ it "rejects bodies that are not equal" $ do+ matcher [] [json|{foo: 42}|] `shouldBe` Just (unlines [+ "body mismatch:"+ , " expected: {\"foo\":23}"+ , " but got: {\"foo\":42}"+ ])+ context "when matching Content-Type header" $ do- context "when JSON is ASCII" $ do- let [MatchHeader matcher] = matchHeaders [json|{foo: 23}|]+ let [MatchHeader matcher] = matchHeaders [json|{foo: 23}|]++ context "when body is ASCII" $ do+ let+ body = [json|{foo: 23}|]+ match = (`matcher` body)+ it "accepts 'application/json'" $ do- matcher [("Content-Type", "application/json")] `shouldBe` Nothing+ match [("Content-Type", "application/json")] `shouldBe` Nothing it "accepts 'application/json; charset=utf-8'" $ do- matcher [("Content-Type", "application/json; charset=utf-8")] `shouldBe` Nothing+ match [("Content-Type", "application/json; charset=utf-8")] `shouldBe` Nothing it "ignores case" $ do- matcher [("Content-Type", "application/JSON; charset=UTF-8")] `shouldBe` Nothing+ match [("Content-Type", "application/JSON; charset=UTF-8")] `shouldBe` Nothing it "rejects other headers" $ do- matcher [("Content-Type", "foobar")] `shouldBe` (Just . unlines) [+ match [("Content-Type", "foobar")] `shouldBe` (Just . unlines) [ "missing header:" , " Content-Type: application/json" , " OR" , " Content-Type: application/json; charset=utf-8" ] - context "when JSON contains Unicode" $ do- let [MatchHeader matcher] = matchHeaders [json|{foo: #{"\955" :: String}}|]+ context "when body is UTF-8" $ do+ let+ body = [json|{foo: #{"\955" :: String}}|]+ match = (`matcher` body)+ it "rejects 'application/json'" $ do- matcher [("Content-Type", "application/json")] `shouldBe` (Just . unlines) [+ match [("Content-Type", "application/json")] `shouldBe` (Just . unlines) [ "missing header:" , " Content-Type: application/json; charset=utf-8" ] it "accepts 'application/json; charset=utf-8'" $ do- matcher [("Content-Type", "application/json; charset=utf-8")] `shouldBe` Nothing+ match [("Content-Type", "application/json; charset=utf-8")] `shouldBe` Nothing