api-builder 0.14.0.0 → 0.15.0.0
raw patch · 6 files changed
+307/−75 lines, 6 filesdep ~http-typesPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: http-types
API changes (from Hackage documentation)
Files
- api-builder.cabal +85/−75
- test-io/Network/API/Builder/Examples/StackOverflowSpec.hs +40/−0
- test/Network/API/Builder/ErrorSpec.hs +25/−0
- test/Network/API/Builder/QuerySpec.hs +33/−0
- test/Network/API/Builder/RoutesSpec.hs +24/−0
- test/Network/API/Builder/SendSpec.hs +100/−0
api-builder.cabal view
@@ -1,91 +1,101 @@-name: api-builder-version: 0.14.0.0-synopsis: Library for easily building REST API wrappers in Haskell-license: BSD3-license-file: LICENSE-author: Fraser Murray-maintainer: fraser.m.murray@gmail.com-homepage: https://github.com/intolerable/api-builder-copyright: (c) Fraser Murray 2014-category: Network-build-type: Simple-cabal-version: >= 1.10+-- This file has been generated from package.yaml by hpack version 0.20.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: 7c4b7181e34f5c26900835396c9c93f9249c246a35bacfea6a01f9a84dff464b +name: api-builder+version: 0.15.0.0+synopsis: Library for easily building REST API wrappers in Haskell+category: Network+homepage: https://github.com/intolerable/api-builder+author: Fraser Murray+maintainer: fraser.m.murray@gmail.com+copyright: (c) Fraser Murray 2014+license: BSD3+license-file: LICENSE+build-type: Simple+cabal-version: >= 1.10+ source-repository head type: git location: git://github.com/intolerable/api-builder.git -source-repository this- type: git- location: git://github.com/intolerable/api-builder.git- tag: v0.11.0.0- library- exposed-modules:- Network.API.Builder- Network.API.Builder.API- Network.API.Builder.Builder- Network.API.Builder.Error- Network.API.Builder.Examples.StackOverflow- Network.API.Builder.Query- Network.API.Builder.Receive- Network.API.Builder.Routes- Network.API.Builder.Send- Network.API.Builder.Send.Multipart+ hs-source-dirs:+ src+ default-extensions: OverloadedStrings FlexibleInstances+ ghc-options: -Wall build-depends:- base >= 4.6 && < 4.12,- aeson >= 0.9 && < 1.3,- bifunctors >= 4.0 && < 6.0,- bytestring == 0.10.*,- HTTP == 4000.*,- http-client >= 0.4.30 && < 0.6,- http-client-tls >= 0.2 && < 0.4,- http-types >= 0.8 && < 0.11,- text == 1.*,- tls >= 1.3 && < 1.5,- transformers >= 0.4 && < 0.6- hs-source-dirs: src/+ HTTP ==4000.*+ , aeson >=0.9 && <1.3+ , base >=4.6 && <4.12+ , bifunctors >=4.0 && <6.0+ , bytestring ==0.10.*+ , http-client >=0.4.30 && <0.6+ , http-client-tls >=0.2 && <0.4+ , http-types >=0.8 && <0.13+ , text ==1.*+ , tls >=1.3 && <1.5+ , transformers >=0.4 && <0.6+ exposed-modules:+ Network.API.Builder+ Network.API.Builder.API+ Network.API.Builder.Builder+ Network.API.Builder.Error+ Network.API.Builder.Examples.StackOverflow+ Network.API.Builder.Query+ Network.API.Builder.Receive+ Network.API.Builder.Routes+ Network.API.Builder.Send+ Network.API.Builder.Send.Multipart+ other-modules:+ Paths_api_builder default-language: Haskell2010- default-extensions:- FlexibleInstances- OverloadedStrings- ghc-options: -Wall test-suite test- hs-source-dirs: test- main-is: Spec.hs- default-extensions:- OverloadedStrings- ScopedTypeVariables- default-language: Haskell2010 type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs:+ test+ default-extensions: OverloadedStrings FlexibleInstances ScopedTypeVariables+ ghc-options: -Wall build-depends:- base == 4.*,- Cabal >= 1.16.0,- api-builder,- aeson,- bytestring,- hspec,- http-client,- text,- transformers- GHC-options: -Wall+ Cabal >=1.16.0+ , aeson+ , api-builder+ , base ==4.*+ , bytestring+ , hspec+ , http-client+ , text+ , transformers+ other-modules:+ Network.API.Builder.ErrorSpec+ Network.API.Builder.QuerySpec+ Network.API.Builder.RoutesSpec+ Network.API.Builder.SendSpec+ Paths_api_builder+ default-language: Haskell2010 test-suite test-io- hs-source-dirs: test-io- main-is: Spec.hs- default-extensions:- LambdaCase- default-language: Haskell2010 type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs:+ test-io+ default-extensions: OverloadedStrings FlexibleInstances LambdaCase+ ghc-options: -Wall build-depends:- base == 4.*,- Cabal >= 1.16.0,- api-builder,- aeson,- bytestring,- containers,- hspec,- text,- transformers- GHC-options: -Wall+ Cabal >=1.16.0+ , aeson+ , api-builder+ , base ==4.*+ , bytestring+ , containers+ , hspec+ , text+ , transformers+ other-modules:+ Network.API.Builder.Examples.StackOverflowSpec+ Paths_api_builder+ default-language: Haskell2010
+ test-io/Network/API/Builder/Examples/StackOverflowSpec.hs view
@@ -0,0 +1,40 @@+module Network.API.Builder.Examples.StackOverflowSpec where++import Network.API.Builder.Examples.StackOverflow++import Control.Monad+import Data.List (nub)+import Test.Hspec+import qualified Data.Set as Set+import qualified Data.Text as Text++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "getAnswers" $ do++ it "can get answers" $+ getAnswers >>= \case+ Left _ -> expectationFailure "getAnswers failed"+ Right (Questions qs) -> do+ nub qs `shouldMatchList` qs+ forM_ qs $ \q -> do+ tags q `shouldSatisfy` isNubbed+ title q `shouldSatisfy` (not . Text.null)++ it "can get answers via https" $+ getAnswersSSL >>= \case+ Left _ -> expectationFailure "getAnswers failed"+ Right (Questions qs) -> do+ nub qs `shouldMatchList` qs+ forM_ qs $ \q -> do+ tags q `shouldSatisfy` isNubbed+ title q `shouldSatisfy` (not . Text.null)++isNubbed :: Ord a => [a] -> Bool+isNubbed = f Set.empty+ where+ f _ [] = True+ f s (x:xs) = not (Set.member x s) && f (Set.insert x s) xs
+ test/Network/API/Builder/ErrorSpec.hs view
@@ -0,0 +1,25 @@+module Network.API.Builder.ErrorSpec where++import Network.API.Builder.Error++import Test.Hspec+import Test.Hspec.QuickCheck++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "APIError" $ do+ describe "Eq" $ do+ it "should check for equality properly" $ do+ HTTPError undefined == (HTTPError undefined :: APIError ())+ `shouldBe` False+ APIError () `shouldBe` APIError ()+ InvalidURLError `shouldBe` (InvalidURLError :: APIError ())++ prop "ParseError s == ParseError s" $ \s ->+ ParseError s == (ParseError s :: APIError ())++ prop "APIError x == APIError x" $ \(x :: String) ->+ APIError x == APIError x
+ test/Network/API/Builder/QuerySpec.hs view
@@ -0,0 +1,33 @@+module Network.API.Builder.QuerySpec where++import Network.API.Builder.Query++import Test.Hspec+import Test.Hspec.QuickCheck++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "ToQuery" $ do++ it "can convert an Integer" $ do+ toQuery "integer" (5 :: Integer) `shouldBe`+ [("integer", "5")]++ it "can convert a Boolean" $ do+ toQuery "bool" False `shouldBe` [("bool", "false")]++ it "can convert a list of Ints" $ do+ toQuery "list" ([1,2,3,4,5] :: [Int]) `shouldBe` [("list", "1,2,3,4,5")]++ it "can convert Maybe values" $ do+ toQuery "maybe" (Just False) `shouldBe` [("maybe", "false")]+ toQuery "maybe" (Nothing :: Maybe Bool) `shouldBe` []++ prop "toQuery x y == toQuery x (Just y)" $ \(y :: Int) ->+ toQuery "x" y == toQuery "x" (Just y)++skip :: String -> Expectation -> Expectation+skip _ _ = return ()
+ test/Network/API/Builder/RoutesSpec.hs view
@@ -0,0 +1,24 @@+module Network.API.Builder.RoutesSpec where++import Network.API.Builder.Routes++import Test.Hspec++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+ describe "routeURL" $ do+ it "should be able to create a basic url" $ do+ routeURL "" (Route [ "api", "index" ] [ ] "GET")+ `shouldBe` "/api/index"+ routeURL "" (Route [ "api", "index.json" ] [ ] "GET")+ `shouldBe` "/api/index.json"+ routeURL "" (Route [ ] [ "test" =. False ] "GET")+ `shouldBe` "?test=false"+ routeURL "" (Route [ "about.json" ] [ "test" =. True ] "GET")+ `shouldBe` "/about.json?test=true"+ routeURL "" (Route [ "about.json" ] [ "test" =. True ] "GET")+ `shouldBe` "/about.json?test=true"+
+ test/Network/API/Builder/SendSpec.hs view
@@ -0,0 +1,100 @@+module Network.API.Builder.SendSpec where++import Network.API.Builder.Builder+import Network.API.Builder.Routes+import Network.API.Builder.Send++import Data.Aeson+import Data.ByteString.Lazy (ByteString)+import qualified Network.HTTP.Client as HTTP+import Test.Hspec++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+ describe "Sendable" $ do++ describe "()" $ do+ it "should be able to construct a basic request" $ do+ case send exampleBuilder (Route ["api.json"] [] "GET") () of+ Just req -> do+ HTTP.secure req `shouldBe` True+ HTTP.host req `shouldBe` "example.com"+ HTTP.method req `shouldBe` "GET"+ HTTP.port req `shouldBe` 443+ HTTP.queryString req `shouldBe` ""+ HTTP.path req `shouldBe` "/api.json"+ Nothing -> expectationFailure "req construction failed"+ it "should be able to construct request with query params" $ do+ case send exampleBuilder (Route ["api.json"] ["a_query" =. True] "GET") () of+ Just req -> do+ HTTP.secure req `shouldBe` True+ HTTP.host req `shouldBe` "example.com"+ HTTP.method req `shouldBe` "GET"+ HTTP.port req `shouldBe` 443+ HTTP.queryString req `shouldBe` "?a_query=true"+ HTTP.path req `shouldBe` "/api.json"+ Nothing -> expectationFailure "req construction failed"+ it "should be able to construct a POST request" $ do+ case send exampleBuilder (Route ["api.json"] ["query" =. False] "POST") () of+ Just req -> do+ HTTP.secure req `shouldBe` True+ HTTP.host req `shouldBe` "example.com"+ HTTP.method req `shouldBe` "POST"+ HTTP.port req `shouldBe` 443+ HTTP.queryString req `shouldBe` ""+ HTTP.path req `shouldBe` "/api.json"+ case HTTP.requestBody req of+ HTTP.RequestBodyBS "query=false" -> return ()+ _ -> expectationFailure "incorrect POST body"+ Nothing -> expectationFailure "req construction failed"++ describe "PostQuery" $ do+ it "should be able to construct a POST request with no body" $ do+ case send exampleBuilder (Route ["api.json"] ["query" =. False] "POST") PostQuery of+ Just req -> do+ HTTP.secure req `shouldBe` True+ HTTP.host req `shouldBe` "example.com"+ HTTP.method req `shouldBe` "POST"+ HTTP.port req `shouldBe` 443+ HTTP.queryString req `shouldBe` "?query=false"+ HTTP.path req `shouldBe` "/api.json"+ case HTTP.requestBody req of+ HTTP.RequestBodyLBS "" -> return ()+ _ -> expectationFailure "incorrect POST body"+ Nothing -> expectationFailure "req construction failed"++ describe "Value" $ do+ it "should be able to construct a POST request with the correct JSON body" $ do+ case send exampleBuilder (Route ["api.json"] ["query" =. False] "POST") $ object ["hello" .= Null] of+ Just req -> do+ HTTP.secure req `shouldBe` True+ HTTP.host req `shouldBe` "example.com"+ HTTP.method req `shouldBe` "POST"+ HTTP.port req `shouldBe` 443+ HTTP.queryString req `shouldBe` "?query=false"+ HTTP.path req `shouldBe` "/api.json"+ case HTTP.requestBody req of+ HTTP.RequestBodyLBS "{\"hello\":null}" -> return ()+ _ -> expectationFailure "incorrect POST body"+ Nothing -> expectationFailure "req construction failed"++ describe "ByteString" $ do+ it "should be able to construct a POST request with the correct ByteString body" $ do+ case send exampleBuilder (Route ["api.json"] ["query" =. False] "POST") ("hello world" :: ByteString) of+ Just req -> do+ HTTP.secure req `shouldBe` True+ HTTP.host req `shouldBe` "example.com"+ HTTP.method req `shouldBe` "POST"+ HTTP.port req `shouldBe` 443+ HTTP.queryString req `shouldBe` "?query=false"+ HTTP.path req `shouldBe` "/api.json"+ case HTTP.requestBody req of+ HTTP.RequestBodyLBS "hello world" -> return ()+ _ -> expectationFailure "incorrect POST body"+ Nothing -> expectationFailure "req construction failed"++exampleBuilder :: Builder+exampleBuilder = basicBuilder "example" "https://example.com"