swagger2-2.3.1: test/Data/Swagger/Schema/GeneratorSpec.hs
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PackageImports #-}
module Data.Swagger.Schema.GeneratorSpec where
import Prelude ()
import Prelude.Compat
import Data.Swagger
import Data.Swagger.Schema.Generator
import Control.Lens.Operators
import Data.Aeson
import Data.Hashable (Hashable)
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
import "unordered-containers" Data.HashSet (HashSet)
import qualified "unordered-containers" Data.HashSet as HashSet
import Data.Int
import Data.IntMap (IntMap)
import Data.List.NonEmpty.Compat (NonEmpty (..), nonEmpty)
import Data.Map (Map, fromList)
import Data.Monoid (mempty)
import Data.Proxy
import Data.Proxy
import Data.Set (Set)
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Data.Time
import Data.Version (Version)
import Data.Word
import GHC.Generics
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck
shouldValidate :: (FromJSON a, ToSchema a) => Proxy a -> Property
shouldValidate = validateFromJSON
shouldNotValidate :: (FromJSON a, ToSchema a) => Proxy a -> Property
shouldNotValidate = expectFailure . shouldValidate
spec :: Spec
spec = do
describe "FromJSON validation" $ do
prop "Bool" $ shouldValidate (Proxy :: Proxy Bool)
prop "Char" $ shouldValidate (Proxy :: Proxy Char)
prop "Double" $ shouldValidate (Proxy :: Proxy Double)
prop "Float" $ shouldValidate (Proxy :: Proxy Float)
prop "Int" $ shouldValidate (Proxy :: Proxy Int)
prop "Int8" $ shouldValidate (Proxy :: Proxy Int8)
prop "Int16" $ shouldValidate (Proxy :: Proxy Int16)
prop "Int32" $ shouldValidate (Proxy :: Proxy Int32)
prop "Int64" $ shouldValidate (Proxy :: Proxy Int64)
prop "Integer" $ shouldValidate (Proxy :: Proxy Integer)
prop "Word" $ shouldValidate (Proxy :: Proxy Word)
prop "Word8" $ shouldValidate (Proxy :: Proxy Word8)
prop "Word16" $ shouldValidate (Proxy :: Proxy Word16)
prop "Word32" $ shouldValidate (Proxy :: Proxy Word32)
prop "Word64" $ shouldValidate (Proxy :: Proxy Word64)
prop "String" $ shouldValidate (Proxy :: Proxy String)
prop "()" $ shouldValidate (Proxy :: Proxy ())
-- prop "ZonedTime" $ shouldValidate (Proxy :: Proxy ZonedTime)
-- prop "UTCTime" $ shouldValidate (Proxy :: Proxy UTCTime)
prop "T.Text" $ shouldValidate (Proxy :: Proxy T.Text)
prop "TL.Text" $ shouldValidate (Proxy :: Proxy TL.Text)
prop "[String]" $ shouldValidate (Proxy :: Proxy [String])
-- prop "(Maybe [Int])" $ shouldValidate (Proxy :: Proxy (Maybe [Int]))
prop "(IntMap String)" $ shouldValidate (Proxy :: Proxy (IntMap String))
prop "(Set Bool)" $ shouldValidate (Proxy :: Proxy (Set Bool))
prop "(NonEmpty Bool)" $ shouldValidate (Proxy :: Proxy (NonEmpty Bool))
prop "(HashSet Bool)" $ shouldValidate (Proxy :: Proxy (HashSet Bool))
prop "(Either Int String)" $ shouldValidate (Proxy :: Proxy (Either Int String))
prop "(Int, String)" $ shouldValidate (Proxy :: Proxy (Int, String))
prop "(Map String Int)" $ shouldValidate (Proxy :: Proxy (Map String Int))
prop "(Map T.Text Int)" $ shouldValidate (Proxy :: Proxy (Map T.Text Int))
prop "(Map TL.Text Bool)" $ shouldValidate (Proxy :: Proxy (Map TL.Text Bool))
prop "(HashMap String Int)" $ shouldValidate (Proxy :: Proxy (HashMap String Int))
prop "(HashMap T.Text Int)" $ shouldValidate (Proxy :: Proxy (HashMap T.Text Int))
prop "(HashMap TL.Text Bool)" $ shouldValidate (Proxy :: Proxy (HashMap TL.Text Bool))
prop "Object" $ shouldValidate (Proxy :: Proxy Object)
prop "(Int, String, Double)" $ shouldValidate (Proxy :: Proxy (Int, String, Double))
prop "(Int, String, Double, [Int])" $ shouldValidate (Proxy :: Proxy (Int, String, Double, [Int]))
prop "(Int, String, Double, [Int], Int)" $ shouldValidate (Proxy :: Proxy (Int, String, Double, [Int], Int))
describe "Invalid FromJSON validation" $ do
prop "WrongType" $ shouldNotValidate (Proxy :: Proxy WrongType)
prop "MissingRequired" $ shouldNotValidate (Proxy :: Proxy MissingRequired)
prop "MissingProperty" $ shouldNotValidate (Proxy :: Proxy MissingProperty)
prop "WrongPropType" $ shouldNotValidate (Proxy :: Proxy WrongPropType)
-- =============================
-- Data types and bunk instances
-- =============================
data WrongType = WrongType Bool
instance FromJSON WrongType where
parseJSON = withBool "WrongType" $ return . WrongType
instance ToSchema WrongType where
declareNamedSchema _ = return . NamedSchema (Just "WrongType") $
mempty
& type_ .~ SwaggerObject
data MissingRequired = MissingRequired
{ propA :: String
, propB :: Bool
}
instance FromJSON MissingRequired where
parseJSON = withObject "MissingRequired" $ \o ->
MissingRequired
<$> o .: "propA"
<*> o .: "propB"
instance ToSchema MissingRequired where
declareNamedSchema _ = do
stringSchema <- declareSchemaRef (Proxy :: Proxy String)
boolSchema <- declareSchemaRef (Proxy :: Proxy Bool)
return . NamedSchema (Just "MissingRequired") $
mempty
& type_ .~ SwaggerObject
& properties .~ [("propA", stringSchema)
,("propB", boolSchema)
]
& required .~ ["propA"]
data MissingProperty = MissingProperty
{ propC :: String
, propD :: Bool
}
instance FromJSON MissingProperty where
parseJSON = withObject "MissingProperty" $ \o ->
MissingProperty
<$> o .: "propC"
<*> o .: "propD"
instance ToSchema MissingProperty where
declareNamedSchema _ = do
stringSchema <- declareSchemaRef (Proxy :: Proxy String)
return . NamedSchema (Just "MissingProperty") $
mempty
& type_ .~ SwaggerObject
& properties .~ [("propC", stringSchema)]
& required .~ ["propC"]
data WrongPropType = WrongPropType
{ propE :: String
}
instance FromJSON WrongPropType where
parseJSON = withObject "WrongPropType" $ \o ->
WrongPropType
<$> o .: "propE"
instance ToSchema WrongPropType where
declareNamedSchema _ = do
boolSchema <- declareSchemaRef (Proxy :: Proxy Bool)
return . NamedSchema (Just "WrongPropType") $
mempty
& type_ .~ SwaggerObject
& properties .~ [("propE", boolSchema)]
& required .~ ["propE"]