11{-# LANGUAGE CPP #-}
22{-# LANGUAGE DeriveGeneric #-}
33{-# LANGUAGE PackageImports #-}
4+ {-# LANGUAGE QuasiQuotes #-}
45{-# LANGUAGE RecordWildCards #-}
56{-# LANGUAGE ScopedTypeVariables #-}
67{-# OPTIONS_GHC -fno-warn-orphans #-}
78module Data.OpenApi.Schema.ValidationSpec where
89
910import Control.Applicative
1011import Control.Lens ((&) , (.~) , (?~) )
12+ import Control.Monad
1113import Data.Aeson
1214#if MIN_VERSION_aeson(2,0,0)
1315import qualified Data.Aeson.Key as Key
1416import qualified Data.Aeson.KeyMap as KeyMap
1517#endif
18+ import Data.Aeson.QQ.Simple
1619import Data.Aeson.Types
1720import Data.Hashable (Hashable )
1821import Data.HashMap.Strict (HashMap )
@@ -45,6 +48,13 @@ import Test.QuickCheck.Instances ()
4548shouldValidate :: (ToJSON a , ToSchema a ) => Proxy a -> a -> Bool
4649shouldValidate _ x = validateToJSON x == []
4750
51+ shouldValidateValue :: (ToSchema a ) => Proxy a -> Value -> Expectation
52+ shouldValidateValue px val = do
53+ let (defs, sch) = runDeclare (declareSchema px) mempty
54+ case validateJSON defs sch val of
55+ [] -> pure ()
56+ errors -> expectationFailure $ unlines errors
57+
4858shouldNotValidate :: forall a . ToSchema a => (a -> Value ) -> a -> Bool
4959shouldNotValidate f = not . null . validateJSON defs sch . f
5060 where
@@ -75,7 +85,7 @@ spec = do
7585 prop " T.Text" $ shouldValidate (Proxy :: Proxy T. Text )
7686 prop " TL.Text" $ shouldValidate (Proxy :: Proxy TL. Text )
7787 prop " [String]" $ shouldValidate (Proxy :: Proxy [String ])
78- -- prop "(Maybe [Int])" $ shouldValidate (Proxy :: Proxy (Maybe [Int]))
88+ prop " (Maybe [Int])" $ shouldValidate (Proxy :: Proxy (Maybe [Int ]))
7989 prop " (IntMap String)" $ shouldValidate (Proxy :: Proxy (IntMap String ))
8090 prop " (Set Bool)" $ shouldValidate (Proxy :: Proxy (Set Bool ))
8191 prop " (NonEmpty Bool)" $ shouldValidate (Proxy :: Proxy (NonEmpty Bool ))
@@ -92,7 +102,11 @@ spec = do
92102 prop " (Int, String, Double)" $ shouldValidate (Proxy :: Proxy (Int , String , Double ))
93103 prop " (Int, String, Double, [Int])" $ shouldValidate (Proxy :: Proxy (Int , String , Double , [Int ]))
94104 prop " (Int, String, Double, [Int], Int)" $ shouldValidate (Proxy :: Proxy (Int , String , Double , [Int ], Int ))
95- prop " Person" $ shouldValidate (Proxy :: Proxy Person )
105+ describe " Person: record with optional field" $ do
106+ let px = Proxy :: Proxy Person
107+ it " optional field is Just" $ shouldValidateValue px personJustEmailField
108+ it " optional field is Null" $ shouldValidateValue px personNullEmailField
109+ it " optional field is omitted" $ shouldValidateValue px personOmittedEmailField
96110 prop " Color" $ shouldValidate (Proxy :: Proxy Color )
97111 prop " Paint" $ shouldValidate (Proxy :: Proxy Paint )
98112 prop " MyRoseTree" $ shouldValidate (Proxy :: Proxy MyRoseTree )
@@ -128,6 +142,32 @@ instance ToSchema Person
128142instance Arbitrary Person where
129143 arbitrary = Person <$> arbitrary <*> arbitrary <*> arbitrary
130144
145+ personJustEmailField :: Value
146+ personJustEmailField = [aesonQQ |
147+ {
148+ "name" : "foo",
149+ "phone" : 1,
150+ "email" : "foo@email.com"
151+ }
152+ |]
153+
154+ personNullEmailField :: Value
155+ personNullEmailField = [aesonQQ |
156+ {
157+ "name" : "foo",
158+ "phone" : 1,
159+ "email" : null
160+ }
161+ |]
162+
163+ personOmittedEmailField :: Value
164+ personOmittedEmailField = [aesonQQ |
165+ {
166+ "name" : "foo",
167+ "phone" : 1
168+ }
169+ |]
170+
131171invalidPersonToJSON :: Person -> Value
132172invalidPersonToJSON Person {.. } = object
133173 [ stringToKey " personName" .= toJSON name
0 commit comments