on master help sign in
first shot at Servant.Mock
commit87c3bd590eafe504f169a2f95aea194927656a4d authorAlp Mestanogullari <alpmestan@gmail.com> dateWed 22 Jul 2015, 21:22 (11 years ago) parentf7d25c5
6 files changed+212
servant-mock/LICENSE+30 servant-mock/Setup.hs+2 servant-mock/example/main.hs+23 servant-mock/servant-mock.cabal+47 servant-mock/src/Servant/Mock.hs+109 sources.txt+1
servant-mock/LICENSEnew file+30
@@ -0,0 +1,30 @@
1+Copyright (c) 2015, Alp Mestanogullari
2+
3+All rights reserved.
4+
5+Redistribution and use in source and binary forms, with or without
6+modification, are permitted provided that the following conditions are met:
7+
8+ * Redistributions of source code must retain the above copyright
9+ notice, this list of conditions and the following disclaimer.
10+
11+ * Redistributions in binary form must reproduce the above
12+ copyright notice, this list of conditions and the following
13+ disclaimer in the documentation and/or other materials provided
14+ with the distribution.
15+
16+ * Neither the name of Alp Mestanogullari nor the names of other
17+ contributors may be used to endorse or promote products derived
18+ from this software without specific prior written permission.
19+
20+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
servant-mock/Setup.hsnew file+2
@@ -0,0 +1,2 @@
1+import Distribution.Simple
2+main = defaultMain
servant-mock/example/main.hsnew file+23
@@ -0,0 +1,23 @@
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE TypeOperators #-}
3+{-# LANGUAGE DeriveGeneric #-}
4+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5+import Data.Aeson
6+import GHC.Generics
7+import Network.Wai.Handler.Warp
8+import Servant
9+import Servant.Mock
10+import Test.QuickCheck.Arbitrary
11+
12+newtype User = User { username :: String }
13+ deriving (Eq, Show, Arbitrary, Generic)
14+
15+instance ToJSON User
16+
17+type API = "user" :> Get '[JSON] User
18+
19+api :: Proxy API
20+api = Proxy
21+
22+main :: IO ()
23+main = run 8080 (serve api $ mock api)
servant-mock/servant-mock.cabalnew file+47
@@ -0,0 +1,47 @@
1+-- Initial servant-mock.cabal generated by cabal init. For further
2+-- documentation, see http://haskell.org/cabal/users-guide/
3+
4+name: servant-mock
5+version: 0.4
6+synopsis: Derive a mock server for free from your servant API types
7+description: Derive a mock server for free from your servant API types
8+homepage: http://github.com/haskell-servant/servant
9+license: BSD3
10+license-file: LICENSE
11+author: Alp Mestanogullari
12+maintainer: alpmestan@gmail.com
13+copyright: 2015 Alp Mestanogullari
14+category: Web
15+build-type: Simple
16+-- extra-source-files:
17+cabal-version: >=1.10
18+
19+flag example
20+ description: Build the example too
21+ manual: True
22+ default: False
23+
24+library
25+ exposed-modules:
26+ Servant.Mock
27+ build-depends:
28+ base >=4.7 && <5,
29+ bytestring >= 0.10 && <0.11,
30+ http-types >= 0.8 && <0.9,
31+ servant >= 0.4,
32+ servant-server >= 0.4,
33+ transformers >= 0.4 && <0.5,
34+ QuickCheck >= 2.8 && <2.9,
35+ wai >= 3.0 && <3.1
36+ hs-source-dirs: src
37+ default-language: Haskell2010
38+
39+executable mock-app
40+ main-is: main.hs
41+ hs-source-dirs: example
42+ default-language: Haskell2010
43+ build-depends: aeson, base, servant-mock, servant-server, QuickCheck, warp
44+ if flag(example)
45+ buildable: True
46+ else
47+ buildable: False
servant-mock/src/Servant/Mock.hsnew file+109
@@ -0,0 +1,109 @@
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE TypeFamilies #-}
3+{-# LANGUAGE TypeOperators #-}
4+{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE FlexibleInstances #-}
6+{-# LANGUAGE ScopedTypeVariables #-}
7+module Servant.Mock ( HasMock(..) ) where
8+
9+import Control.Monad.IO.Class
10+import Data.ByteString.Lazy.Char8 (pack)
11+import Data.Proxy
12+import GHC.TypeLits
13+import Network.HTTP.Types.Status
14+import Network.Wai
15+import Servant
16+import Servant.API.ContentTypes
17+import Test.QuickCheck.Arbitrary (Arbitrary(..), vector)
18+import Test.QuickCheck.Gen (Gen, generate)
19+
20+class HasServer api => HasMock api where
21+ mock :: Proxy api -> Server api
22+
23+instance (HasMock a, HasMock b) => HasMock (a :<|> b) where
24+ mock _ = mock (Proxy :: Proxy a) :<|> mock (Proxy :: Proxy b)
25+
26+instance (KnownSymbol path, HasMock rest) => HasMock (path :> rest) where
27+ mock _ = mock (Proxy :: Proxy rest)
28+
29+instance (KnownSymbol s, FromText a, HasMock rest) => HasMock (Capture s a :> rest) where
30+ mock _ = \_ -> mock (Proxy :: Proxy rest)
31+
32+instance (AllCTUnrender ctypes a, HasMock rest) => HasMock (ReqBody ctypes a :> rest) where
33+ mock _ = \_ -> mock (Proxy :: Proxy rest)
34+
35+instance HasMock rest => HasMock (RemoteHost :> rest) where
36+ mock _ = \_ -> mock (Proxy :: Proxy rest)
37+
38+instance HasMock rest => HasMock (IsSecure :> rest) where
39+ mock _ = \_ -> mock (Proxy :: Proxy rest)
40+
41+instance HasMock rest => HasMock (Vault :> rest) where
42+ mock _ = \_ -> mock (Proxy :: Proxy rest)
43+
44+instance HasMock rest => HasMock (HttpVersion :> rest) where
45+ mock _ = \_ -> mock (Proxy :: Proxy rest)
46+
47+instance (KnownSymbol s, FromText a, HasMock rest)
48+ => HasMock (QueryParam s a :> rest) where
49+ mock _ = \_ -> mock (Proxy :: Proxy rest)
50+
51+instance (KnownSymbol s, FromText a, HasMock rest)
52+ => HasMock (QueryParams s a :> rest) where
53+ mock _ = \_ -> mock (Proxy :: Proxy rest)
54+
55+instance (KnownSymbol s, HasMock rest) => HasMock (QueryFlag s :> rest) where
56+ mock _ = \_ -> mock (Proxy :: Proxy rest)
57+
58+instance (KnownSymbol s, FromText a, HasMock rest)
59+ => HasMock (MatrixParam s a :> rest) where
60+ mock _ = \_ -> mock (Proxy :: Proxy rest)
61+
62+instance (KnownSymbol s, FromText a, HasMock rest)
63+ => HasMock (MatrixParams s a :> rest) where
64+ mock _ = \_ -> mock (Proxy :: Proxy rest)
65+
66+instance (KnownSymbol s, HasMock rest) => HasMock (MatrixFlag s :> rest) where
67+ mock _ = \_ -> mock (Proxy :: Proxy rest)
68+
69+instance (KnownSymbol h, FromText a, HasMock rest) => HasMock (Header h a :> rest) where
70+ mock _ = \_ -> mock (Proxy :: Proxy rest)
71+
72+instance (Arbitrary a, AllCTRender ctypes a) => HasMock (Delete ctypes a) where
73+ mock _ = mockArbitrary
74+
75+instance (Arbitrary a, AllCTRender ctypes a) => HasMock (Get ctypes a) where
76+ mock _ = mockArbitrary
77+
78+instance (Arbitrary a, AllCTRender ctypes a) => HasMock (Patch ctypes a) where
79+ mock _ = mockArbitrary
80+
81+instance (Arbitrary a, AllCTRender ctypes a) => HasMock (Post ctypes a) where
82+ mock _ = mockArbitrary
83+
84+instance (Arbitrary a, AllCTRender ctypes a) => HasMock (Put ctypes a) where
85+ mock _ = mockArbitrary
86+
87+instance HasMock Raw where
88+ mock _ = \req respond -> do
89+ bdy <- genBody
90+ respond $ responseLBS status200 [] bdy
91+
92+ where genBody = fmap pack $ generate (vector 100 :: Gen [Char])
93+
94+mockArbitrary :: (MonadIO m, Arbitrary a) => m a
95+mockArbitrary = liftIO (generate arbitrary)
96+
97+-- utility instance
98+instance (Arbitrary (HList ls), Arbitrary a)
99+ => Arbitrary (Headers ls a) where
100+ arbitrary = Headers <$> arbitrary <*> arbitrary
101+
102+instance Arbitrary (HList '[]) where
103+ arbitrary = pure HNil
104+
105+instance (Arbitrary a, Arbitrary (HList hs))
106+ => Arbitrary (HList (Header h a ': hs)) where
107+ arbitrary = HCons <$> fmap Header arbitrary <*> arbitrary
108+
109+
sources.txt+1
@@ -6,3 +6,4 @@ servant-server
66servant-examples
77servant-blaze
88servant-lucid
9+servant-mock