on 28b2628 help sign in
23 files changed+96−141
since splitsnapshots
unifiedsplit
package.yaml+1−1 roboservant.cabal+4−6 src/Roboservant/Client.hs+2−2 src/Roboservant/Direct.hs+12−11 src/Roboservant/Server.hs+2−2 src/Roboservant/Types.hs−1 src/Roboservant/Types/Breakdown.hs+1−6 src/Roboservant/Types/BuildFrom.hs+1−5 src/Roboservant/Types/Internal.hs+2−2 src/Roboservant/Types/Orphans.hs−7 src/Roboservant/Types/ReifiedApi.hs+1−7 src/Roboservant/Types/ReifiedApi/Server.hs+1−1 stack.yaml+5−5 stack.yaml.lock+30−9 test/Breakdown.hs+1−1 test/Nested.hs+2−2 test/Post.hs+2−2 test/Product.hs+1−1 test/Put.hs−33 test/QueryParams.hs+3−3 test/Spec.hs+20−30 test/UnsafeIO.hs+3−3 test/Valid.hs+2−1
package.yaml+1−1
@@ -1,6 +1,6 @@
11
22name: roboservant
3−version: 0.1.0.3
3+version: 0.1.0.2
44github: "mwotton/roboservant"
55license: BSD3
66copyright: "2020 Mark Wotton, Samuel Schlesinger"
roboservant.cabal+4−6
@@ -1,13 +1,13 @@
11cabal-version: 1.12
22
3−-- This file has been generated from package.yaml by hpack version 0.35.0.
3+-- This file has been generated from package.yaml by hpack version 0.33.0.
44--
55-- see: https://github.com/sol/hpack
66--
7−-- hash: 0c0c35e1dca1d6c52e5bc61591cbd8c0da9d811b83341bbc676c5f8b93b0b20d
7+-- hash: 596d33d4f2e29f15b48525514def52b101c9e89b6193275bd5c0a4c253de8d5c
88
99name: roboservant
10−version: 0.1.0.3
10+version: 0.1.0.2
1111synopsis: Automatic session-aware servant testing
1212description: Please see the README on GitHub at <https://github.com/mwotton/roboservant#readme>
1313category: Web
@@ -36,7 +36,6 @@ library
3636 Roboservant.Types.BuildFrom
3737 Roboservant.Types.Config
3838 Roboservant.Types.Internal
39− Roboservant.Types.Orphans
4039 Roboservant.Types.ReifiedApi
4140 Roboservant.Types.ReifiedApi.Server
4241 other-modules:
@@ -73,7 +72,7 @@ test-suite example
7372 other-modules:
7473 Paths_roboservant
7574 hs-source-dirs:
76− ./
75+ ./.
7776 ghc-options: -Wall -fwrite-ide-info -hiedir=.hie -pgmL markdown-unlit
7877 build-tool-depends:
7978 markdown-unlit:markdown-unlit
@@ -116,7 +115,6 @@ test-suite roboservant-test
116115 Nested
117116 Post
118117 Product
119− Put
120118 QueryParams
121119 Seeded
122120 UnsafeIO
src/Roboservant/Client.hs+2−2
@@ -8,7 +8,7 @@
88{-# LANGUAGE PolyKinds #-}
99{-# LANGUAGE ScopedTypeVariables #-}
1010{-# LANGUAGE TypeApplications #-}
11−
11+{-# LANGUAGE TypeOperators #-}
1212{-# LANGUAGE UndecidableInstances #-}
1313{-# LANGUAGE TypeFamilies #-}
1414{-# LANGUAGE FlexibleContexts #-}
@@ -97,7 +97,7 @@ instance (Typeable x, Hashable x, Breakdown x) => NormalizeFunction (ClientM x)
9797 where
9898 renderClientError :: ClientError -> InteractionError
9999 renderClientError err = case err of
100− FailureResponse _ Response{responseStatusCode} -> InteractionError textual (responseStatusCode == status500)
100+ FailureResponse _ (Response{responseStatusCode}) -> InteractionError textual (responseStatusCode == status500)
101101 _ -> InteractionError textual True
102102
103103 where textual = T.pack $ show err
src/Roboservant/Direct.hs+12−11
@@ -7,7 +7,7 @@
77{-# LANGUAGE RecordWildCards #-}
88{-# LANGUAGE ScopedTypeVariables #-}
99{-# LANGUAGE TupleSections #-}
10−
10+{-# LANGUAGE TypeApplications #-}
1111{-# LANGUAGE TypeFamilies #-}
1212{-# LANGUAGE UndecidableInstances #-}
1313
@@ -150,12 +150,12 @@ fuzz' reifiedApi Config {..} = handle (pure . Just . formatException) $ do
150150 Report
151151 (unlines [show failureType, show exception])
152152 r
153− displayDiagnostics FuzzState {..} = liftIO $
153+ displayDiagnostics FuzzState {..} = liftIO $ do
154154 logInfo $ unlines $
155− ["api endpoints covered"]
156− <> (map show . Set.toList . Set.fromList $ map apiOffset path)
157− <> ["", "types in stash"]
158− <> DM.foldrWithKey (\_ v r -> (show . NEL.length . getStashValue $ v) : r) [] (getStash stash)
155+ ["api endpoints covered"]
156+ <> (map show . Set.toList . Set.fromList $ map apiOffset path)
157+ <> ["", "types in stash"]
158+ <> DM.foldrWithKey (\_ v r -> (show . NEL.length . getStashValue $ v) : r) [] (getStash stash)
159159 -- <> (map (show . NEL.length . getStashValue ) $ DM.assocs (getStash stash))
160160 -- $ \_k v ->
161161 -- (show . NEL.length $ getStashValue v))
@@ -246,11 +246,11 @@ fuzz' reifiedApi Config {..} = handle (pure . Just . formatException) $ do
246246 if fatalError e
247247 then throw e
248248 else pure ()
249− Right (dyn :: NEL.NonEmpty (Dynamic, Int)) ->
249+ Right (dyn :: NEL.NonEmpty (Dynamic, Int)) -> do
250250 modify'
251− ( \fs@FuzzState {..} ->
252− fs {stash = addToStash (NEL.toList dyn) stash}
253− )
251+ ( \fs@FuzzState {..} ->
252+ fs {stash = addToStash (NEL.toList dyn) stash}
253+ )
254254 where
255255 argVals = V.rmap (\(_ :*: V.Identity x) -> V.Identity x) args
256256 -- argTypes = recordToList' (\(tr :*: _) -> R.SomeTypeRep tr) args
@@ -262,7 +262,8 @@ fuzz' reifiedApi Config {..} = handle (pure . Just . formatException) $ do
262262 (execute op func args)
263263 [ Handler (\(e :: SomeAsyncException) -> throw e),
264264 Handler
265− ( \(e :: SomeException) ->
265+ ( \(e :: SomeException) -> do
266+ -- displayDiagnostics =<< get
266267 throw . RoboservantException ServerCrashed (Just e) =<< get
267268 )
268269 ]
src/Roboservant/Server.hs+2−2
@@ -5,7 +5,7 @@
55{-# LANGUAGE FlexibleContexts #-}
66{-# LANGUAGE GADTs #-}
77{-# LANGUAGE PolyKinds #-}
8−
8+{-# LANGUAGE RankNTypes #-}
99{-# LANGUAGE ScopedTypeVariables #-}
1010{-# LANGUAGE TypeApplications #-}
1111{-# LANGUAGE TypeFamilies #-}
@@ -27,7 +27,7 @@ fuzz :: forall api.
2727 Server api ->
2828 Config ->
2929 IO (Maybe Report)
30−fuzz s = fuzz' (reifyServer s)
30+fuzz s = fuzz' (reifyServer s)
3131 -- todo: how do we pull reifyServer out?
3232 where reifyServer :: (FlattenServer api, ToReifiedApi (Endpoints api))
3333 => Server api -> ReifiedApi
src/Roboservant/Types.hs−1
@@ -23,4 +23,3 @@ import Roboservant.Types.Config
2323import Roboservant.Types.Internal
2424import Roboservant.Types.ReifiedApi
2525import Roboservant.Types.ReifiedApi.Server
26−import Roboservant.Types.Orphans()
src/Roboservant/Types/Breakdown.hs+1−6
@@ -1,6 +1,5 @@
11{-# LANGUAGE AllowAmbiguousTypes #-}
22{-# LANGUAGE DataKinds #-}
3−{-# LANGUAGE FlexibleContexts #-}
43{-# LANGUAGE DerivingVia #-}
54{-# LANGUAGE FlexibleInstances #-}
65{-# LANGUAGE GADTs #-}
@@ -23,8 +22,6 @@ import qualified Data.List.NonEmpty as NEL
2322import Data.Typeable (Typeable)
2423import GHC.Generics
2524import Roboservant.Types.Internal
26−import Servant
27−import Roboservant.Types.Orphans()
2825
2926breakdown ::
3027 (Hashable x, Typeable x, Breakdown x) =>
@@ -49,7 +46,7 @@ instance (Hashable x, Typeable x, Breakdown x) => Breakdown [x] where
4946 breakdownExtras stash = concatMap (NEL.toList . breakdown) stash
5047
5148
52−class GBreakdown (f :: k -> Type) where
49+class GBreakdown (f :: k -> *) where
5350 gBreakdownExtras :: f a -> [(Dynamic, Int)]
5451
5552instance (Hashable x, Typeable x, Generic x, GBreakdown (Rep x)) => Breakdown (Compound (x :: Type)) where
@@ -77,5 +74,3 @@ instance (Hashable a, Typeable a, Breakdown a) => GBreakdown (K1 R a) where
7774
7875instance GBreakdown U1 where
7976 gBreakdownExtras U1 = []
80−
81−deriving via (Atom NoContent) instance Breakdown NoContent
src/Roboservant/Types/BuildFrom.hs+1−5
@@ -23,8 +23,6 @@ import Data.Typeable (Typeable)
2323import GHC.Generics
2424import Roboservant.Types.Internal
2525import qualified Type.Reflection as R
26−import Servant(NoContent)
27−import Roboservant.Types.Orphans()
2826
2927buildFrom :: forall x. (Hashable x, BuildFrom x, Typeable x) => Stash -> Maybe (StashValue x)
3028buildFrom = buildStash . buildFrom'
@@ -77,7 +75,7 @@ deriving via (Atom Int) instance BuildFrom Int
7775
7876deriving via (Atom Char) instance BuildFrom Char
7977
80−class GBuildFrom (f :: k -> Type) where
78+class GBuildFrom (f :: k -> *) where
8179 gExtras :: Stash -> [([Provenance], f a)]
8280
8381instance GBuildFrom b => GBuildFrom (M1 D a b) where
@@ -103,5 +101,3 @@ instance BuildFrom a => GBuildFrom (K1 i a) where
103101
104102instance GBuildFrom U1 where
105103 gExtras _ = [([], U1)]
106−
107−deriving via (Atom NoContent) instance BuildFrom NoContent
src/Roboservant/Types/Internal.hs+2−2
@@ -43,11 +43,11 @@ instance Show Stash where
4343
4444-- | Can't be built up from parts, can't be broken down further.
4545newtype Atom x = Atom {unAtom :: x}
46− deriving newtype (Hashable, Typeable,Eq)
46+ deriving newtype (Hashable, Typeable)
4747
4848-- | can be broken down and built up from generic pieces
4949newtype Compound x = Compound {unCompound :: x}
50− deriving newtype (Hashable, Typeable, Eq)
50+ deriving newtype (Hashable, Typeable)
5151
5252hashedDyn :: (Hashable a, Typeable a) => a -> (Dynamic, Int)
5353hashedDyn a = (toDyn a, hash a)
src/Roboservant/Types/Orphans.hsdeleted−7
@@ -1,7 +0,0 @@
1−{-# OPTIONS_GHC -fno-warn-orphans #-}
2−module Roboservant.Types.Orphans where
3−
4−import Servant
5−import Data.Hashable
6−
7−instance Hashable NoContent
src/Roboservant/Types/ReifiedApi.hs+1−7
@@ -57,7 +57,7 @@ instance Show ReifiedEndpoint where
5757
5858class ( V.RecordToList (EndpointArgs endpoint)
5959 , V.RMap (EndpointArgs endpoint)
60− ) => ToReifiedEndpoint (endpoint :: Type) where
60+ ) => ToReifiedEndpoint (endpoint :: *) where
6161 type EndpointArgs endpoint :: [Type]
6262 type EndpointRes endpoint :: Type
6363
@@ -84,12 +84,6 @@ instance
8484 type EndpointRes (Verb method statusCode contentTypes responseType) = responseType
8585 reifiedEndpointArguments = V.RNil
8686
87−instance ToReifiedEndpoint (NoContentVerb method)
88− where
89− type EndpointArgs (NoContentVerb method) = '[]
90− type EndpointRes (NoContentVerb method) = NoContent
91− reifiedEndpointArguments = V.RNil
92−
9387instance
9488 (ToReifiedEndpoint endpoint) =>
9589 ToReifiedEndpoint ((x :: Symbol) :> endpoint)
src/Roboservant/Types/ReifiedApi/Server.hs+1−1
@@ -6,7 +6,7 @@
66{-# LANGUAGE GADTs #-}
77{-# LANGUAGE LambdaCase #-}
88{-# LANGUAGE PolyKinds #-}
9−
9+{-# LANGUAGE RankNTypes #-}
1010{-# LANGUAGE ScopedTypeVariables #-}
1111{-# LANGUAGE TypeApplications #-}
1212{-# LANGUAGE TypeFamilies #-}
stack.yaml+5−5
@@ -1,10 +1,10 @@
1−resolver: lts-20.4
1+resolver: lts-17.6
22packages:
33- .
44
55extra-deps:
6−# - dependent-map-0.4.0.0@sha256:ca2b131046f4340a1c35d138c5a003fe4a5be96b14efc26291ed35fd08c62221,1657
7−# - dependent-sum-0.7.1.0@sha256:5599aa89637db434431b1dd3fa7c34bc3d565ee44f0519bfbc877be1927c2531,2068
6+- dependent-map-0.4.0.0@sha256:ca2b131046f4340a1c35d138c5a003fe4a5be96b14efc26291ed35fd08c62221,1657
7+- dependent-sum-0.7.1.0@sha256:5599aa89637db434431b1dd3fa7c34bc3d565ee44f0519bfbc877be1927c2531,2068
88- servant-flatten-0.2@sha256:276896f7c5cdec5b8f8493f6205fded0cc602d050b58fdb09a6d7c85c3bb0837,1234
9−# - constraints-extras-0.3.0.2@sha256:013b8d0392582c6ca068e226718a4fe8be8e22321cc0634f6115505bf377ad26,1853
10−- some-1.0.3
9+- constraints-extras-0.3.0.2@sha256:013b8d0392582c6ca068e226718a4fe8be8e22321cc0634f6115505bf377ad26,1853
10+- some-1.0.1@sha256:26e5bab7276f48b25ea8660d3fd1166c0f20fd497dac879a40f408e23211f93e,2055
stack.yaml.lock+30−9
@@ -4,23 +4,44 @@
44# https://docs.haskellstack.org/en/stable/lock_files
55
66packages:
7+- completed:
8+ hackage: dependent-map-0.4.0.0@sha256:ca2b131046f4340a1c35d138c5a003fe4a5be96b14efc26291ed35fd08c62221,1657
9+ pantry-tree:
10+ size: 551
11+ sha256: 5defa30010904d2ad05a036f3eaf83793506717c93cbeb599f40db1a3632cfc5
12+ original:
13+ hackage: dependent-map-0.4.0.0@sha256:ca2b131046f4340a1c35d138c5a003fe4a5be96b14efc26291ed35fd08c62221,1657
14+- completed:
15+ hackage: dependent-sum-0.7.1.0@sha256:5599aa89637db434431b1dd3fa7c34bc3d565ee44f0519bfbc877be1927c2531,2068
16+ pantry-tree:
17+ size: 290
18+ sha256: 9cbfb32b5a8a782b7a1c941803fd517633cb699159b851c1d82267a9e9391b50
19+ original:
20+ hackage: dependent-sum-0.7.1.0@sha256:5599aa89637db434431b1dd3fa7c34bc3d565ee44f0519bfbc877be1927c2531,2068
721- completed:
822 hackage: servant-flatten-0.2@sha256:276896f7c5cdec5b8f8493f6205fded0cc602d050b58fdb09a6d7c85c3bb0837,1234
923 pantry-tree:
10− sha256: 04f12c7bef2c3f9a25d94eb9489752ed498db8e243069fe95838dbb51df1dcb3
1124 size: 325
25+ sha256: 04f12c7bef2c3f9a25d94eb9489752ed498db8e243069fe95838dbb51df1dcb3
1226 original:
1327 hackage: servant-flatten-0.2@sha256:276896f7c5cdec5b8f8493f6205fded0cc602d050b58fdb09a6d7c85c3bb0837,1234
1428- completed:
15− hackage: some-1.0.3@sha256:938cec5fc0d3a08dde34cfc0acd5a0aa2e9fd489c9dbb64417f16588dfb47af0,2399
29+ hackage: constraints-extras-0.3.0.2@sha256:013b8d0392582c6ca068e226718a4fe8be8e22321cc0634f6115505bf377ad26,1853
30+ pantry-tree:
31+ size: 594
32+ sha256: 3ce1012bfb02e4d7def9df19ce80b8cd2b472c691b25b181d9960638673fecd1
33+ original:
34+ hackage: constraints-extras-0.3.0.2@sha256:013b8d0392582c6ca068e226718a4fe8be8e22321cc0634f6115505bf377ad26,1853
35+- completed:
36+ hackage: some-1.0.1@sha256:26e5bab7276f48b25ea8660d3fd1166c0f20fd497dac879a40f408e23211f93e,2055
1637 pantry-tree:
17− sha256: b88dddc6b991cd570c6750f8d309a9feb76938b29a690abdabc4ababb8c7b2f8
18− size: 709
38+ size: 708
39+ sha256: c882b6ebe8a0616f1ab3908f1620087ad5c6d8d82d1a72b99226f6487419bfe6
1940 original:
20− hackage: some-1.0.3
41+ hackage: some-1.0.1@sha256:26e5bab7276f48b25ea8660d3fd1166c0f20fd497dac879a40f408e23211f93e,2055
2142snapshots:
2243- completed:
23− sha256: 3770dfd79f5aed67acdcc65c4e7730adddffe6dba79ea723cfb0918356fc0f94
24− size: 648660
25− url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/20/4.yaml
26− original: lts-20.4
44+ size: 565712
45+ url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/17/6.yaml
46+ sha256: 4e5e581a709c88e3fe26a9ce8bf331435729bead762fb5c190064c6c5bb1b835
47+ original: lts-17.6
test/Breakdown.hs+1−1
@@ -1,7 +1,7 @@
11{-# LANGUAGE DataKinds #-}
22{-# LANGUAGE DeriveGeneric #-}
33{-# LANGUAGE DerivingStrategies #-}
4−
4+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
55{-# LANGUAGE OverloadedStrings #-}
66{-# LANGUAGE TypeOperators #-}
77
test/Nested.hs+2−2
@@ -1,7 +1,7 @@
11{-# LANGUAGE DataKinds #-}
2−
2+{-# LANGUAGE DeriveGeneric #-}
33{-# LANGUAGE DerivingStrategies #-}
4−
4+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
55{-# LANGUAGE OverloadedStrings #-}
66{-# LANGUAGE TypeOperators #-}
77
test/Post.hs+2−2
@@ -1,8 +1,8 @@
11{-# LANGUAGE DataKinds #-}
22{-# LANGUAGE DeriveGeneric #-}
33{-# LANGUAGE DerivingStrategies #-}
4−
5−
4+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5+{-# LANGUAGE OverloadedStrings #-}
66{-# LANGUAGE TypeOperators #-}
77
88module Post where
test/Product.hs+1−1
@@ -1,7 +1,7 @@
11{-# LANGUAGE DataKinds #-}
22{-# LANGUAGE DeriveGeneric #-}
33{-# LANGUAGE DerivingStrategies #-}
4−
4+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
55{-# LANGUAGE OverloadedStrings #-}
66{-# LANGUAGE TypeOperators #-}
77
test/Put.hsdeleted−33
@@ -1,33 +0,0 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE DeriveGeneric #-}
3−{-# LANGUAGE DerivingStrategies #-}
4−
5−
6−{-# LANGUAGE TypeOperators #-}
7−
8−module Put where
9−
10−import Data.Aeson
11−import Data.Hashable
12−import GHC.Generics (Generic)
13−import Servant
14−
15−type Api =
16− Get '[JSON] Foo
17− :<|> ReqBody '[JSON] Foo :> Put '[JSON] ()
18− :<|> ReqBody '[JSON] Foo :> Put '[JSON] NoContent
19−
20−data Foo = Foo
21− deriving (Eq, Show, Generic)
22−
23−instance Hashable Foo
24−
25−instance ToJSON Foo
26−
27−instance FromJSON Foo
28−
29−server :: Server Api
30−server =
31− pure Foo
32− :<|> const (pure ())
33− :<|> const (pure NoContent)
test/QueryParams.hs+3−3
@@ -1,8 +1,8 @@
11{-# LANGUAGE DataKinds #-}
2−
2+{-# LANGUAGE DeriveGeneric #-}
33{-# LANGUAGE DerivingStrategies #-}
4−
5−
4+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5+{-# LANGUAGE OverloadedStrings #-}
66{-# LANGUAGE TypeOperators #-}
77
88module QueryParams where
test/Spec.hs+20−30
@@ -21,7 +21,6 @@ import qualified Foo
2121import qualified Headers
2222import qualified Nested
2323import qualified Post
24−import qualified Put
2524import qualified Product
2625import qualified QueryParams
2726import qualified Roboservant as R
@@ -37,7 +36,6 @@ import Servant.Client(ClientEnv, mkClientEnv, baseUrlPort, parseBaseUrl,HasClien
3736import Network.Wai(Application)
3837import qualified Network.Wai.Handler.Warp as Warp
3938import Network.HTTP.Client (newManager, defaultManagerSettings)
40−import Control.Monad((>=>))
4139
4240main :: IO ()
4341main = hspec spec
@@ -48,15 +46,15 @@ fuzzBoth
4846 HasClient ClientM a)
4947 => String -> Server a -> R.Config -> (Maybe R.Report -> IO ()) -> Spec
5048fuzzBoth name server config condition = do
51− it (name <> " via server") $
49+ it (name <> " via server") $ do
5250 RS.fuzz @a server config >>= condition
5351
54− around (withServer (serve (Proxy :: Proxy a) server)) $
52+ around (withServer (serve (Proxy :: Proxy a) server)) $ do
5553 it (name <> " via client") $ \(clientEnv::ClientEnv) -> do
56− RC.fuzz @a clientEnv config >>= condition
54+ RC.fuzz @a clientEnv config >>= condition
5755
5856withServer :: Application -> ActionWith ClientEnv -> IO ()
59−withServer app action = Warp.testWithApplication (pure app) (genClientEnv >=> action)
57+withServer app action = Warp.testWithApplication (pure app) (\p -> genClientEnv p >>= action)
6058 where genClientEnv port = do
6159 baseUrl <- parseBaseUrl "http://localhost"
6260 manager <- newManager defaultManagerSettings
@@ -75,15 +73,9 @@ spec = do
7573 Just (R.InsufficientCoverage _) -> True
7674 _ -> False
7775 ))
78− describe "posted body" $
76+ describe "posted body" $ do
7977 fuzzBoth @Post.Api "passes a coverage check using a posted body" Post.server R.defaultConfig {R.coverageThreshold = 0.99}
80− (`shouldSatisfy` isNothing)
81−
82−
83− describe "PUTted body" $
84− fuzzBoth @Put.Api "passes a coverage check using a posted body" Put.server R.defaultConfig {R.coverageThreshold = 0.99}
85− (`shouldSatisfy` isNothing)
86−
78+ (`shouldSatisfy` isNothing)
8779
8880 describe "seeded" $ do
8981 let res = Seeded.Seed 1
@@ -91,29 +83,31 @@ spec = do
9183 (R.defaultConfig {R.seed = [(toDyn res, hash res)]})
9284 (`shouldSatisfy` isNothing)
9385
94− describe "Foo" $
86+ describe "Foo" $ do
9587 fuzzBoth @Foo.Api "finds an error in a basic app" Foo.server R.defaultConfig (`shouldSatisfy` serverFailure)
9688
97− describe "QueryParams" $
89+ describe "QueryParams" $ do
9890 fuzzBoth @QueryParams.Api "can handle query params" QueryParams.server R.defaultConfig { R.seed = [R.hashedDyn (12::Int)] }
99− (`shouldSatisfy` isNothing)
91+ (`shouldSatisfy` isNothing)
10092
10193 describe "BuildFrom" $ do
102− describe "headers (and sum types)" $
94+ describe "headers (and sum types)" $ do
10395 fuzzBoth @Headers.Api "should find a failure that's dependent on using header info" Headers.server R.defaultConfig
104− (`shouldSatisfy` serverFailure)
105− describe "product types" $
96+ (`shouldSatisfy` serverFailure)
97+ describe "product types" $ do
10698 fuzzBoth @Product.Api "should find a failure that's dependent on creating a product" Product.server
107− R.defaultConfig {R.seed = [R.hashedDyn 'a', R.hashedDyn (1 :: Int)]}
108− (`shouldSatisfy` serverFailure)
99+ R.defaultConfig {R.seed = [R.hashedDyn 'a', R.hashedDyn (1 :: Int)]}
100+ (`shouldSatisfy` serverFailure)
109101 describe "Breakdown" $ do
110102 fuzzBoth @Breakdown.ProductApi "handles products" Breakdown.productServer R.defaultConfig
111103 (`shouldSatisfy` serverFailure)
112104 fuzzBoth @Breakdown.SumApi "handles sums" Breakdown.sumServer R.defaultConfig
113105 (`shouldSatisfy` serverFailure)
114− describe "flattening" $
106+ describe "flattening" $ do
107+ -- we don't actually do much here, this is just here to document the appropriate response
108+ -- if you get a type error with a nested api.
115109 fuzzBoth @Nested.FlatApi "can handle nested apis" Nested.server R.defaultConfig {R.coverageThreshold = 0.99}
116− (`shouldSatisfy` isNothing)
110+ (`shouldSatisfy` isNothing)
117111
118112serverFailure :: Maybe R.Report -> Bool
119113serverFailure = \case
@@ -137,12 +131,8 @@ deriving via (R.Atom Seeded.Seed) instance R.BuildFrom Seeded.Seed
137131deriving via (R.Atom Void) instance R.BuildFrom Void
138132
139133deriving via (R.Atom Post.FooPost) instance R.Breakdown Post.FooPost
140−deriving via (R.Atom Post.FooPost) instance R.BuildFrom Post.FooPost
141−
142−deriving via (R.Atom Put.Foo) instance R.Breakdown Put.Foo
143−deriving via (R.Atom Put.Foo) instance R.BuildFrom Put.Foo
144−
145134
135+deriving via (R.Atom Post.FooPost) instance R.BuildFrom Post.FooPost
146136
147137deriving via (R.Compound Breakdown.Foo) instance R.Breakdown Breakdown.Foo
148138
@@ -158,7 +148,7 @@ shouldFail =
158148 ( \i ->
159149 i
160150 { itemExample = \p a cb -> do
161− r <- itemExample i p a cb
151+ r <- (itemExample i) p a cb
162152 pure
163153 r
164154 { resultStatus = case resultStatus r of
test/UnsafeIO.hs+3−3
@@ -1,7 +1,7 @@
11{-# LANGUAGE DataKinds #-}
2−
2+{-# LANGUAGE DeriveGeneric #-}
33{-# LANGUAGE DerivingStrategies #-}
4−
4+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
55{-# LANGUAGE OverloadedStrings #-}
66{-# LANGUAGE TypeOperators #-}
77
@@ -22,7 +22,7 @@ healthcheck ref = do
2222 t <- liftIO $ readIORef ref
2323 case t of
2424 0 -> pure ()
25− n -> throwError $ err500 {errBody = "observed inconsistency: " <> BL8.pack (show n)}
25+ n -> throwError $ err500 {errBody = "observed inconsistency: " <> (BL8.pack $ show n)}
2626
2727makeServer :: IO (Server UnsafeApi)
2828makeServer = do
test/Valid.hs+2−1
@@ -1,7 +1,7 @@
11{-# LANGUAGE DataKinds #-}
22{-# LANGUAGE DeriveGeneric #-}
33{-# LANGUAGE DerivingStrategies #-}
4−
4+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
55{-# LANGUAGE OverloadedStrings #-}
66{-# LANGUAGE TypeOperators #-}
77
@@ -10,6 +10,7 @@ module Valid where
1010import Data.Void
1111import GHC.Generics
1212import Servant
13+import Servant.API.Generic
1314import Servant.Server.Generic
1415
1516type Api =