{-# OPTIONS_GHC -fno-warn-unused-top-binds #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeInType #-} {-# LANGUAGE TypeOperators #-} module Servant.Zeppelin.SwaggerSpec (spec) where import Control.Lens (at, mapped, (&), (?~), (^?), _Just) import Data.Aeson import qualified Data.HashMap.Strict.InsOrd as O import Data.Proxy import qualified Data.Set as S import Data.Swagger import GHC.Generics (Generic) import Servant.API import Servant.Swagger import Servant.Zeppelin import Servant.Zeppelin.Swagger () import Servant.Zeppelin.Internal.Types import Test.Hspec hiding (example) spec :: Spec spec = do swaggerSpec return () swaggerSpec :: Spec swaggerSpec = describe "Has Swagger instance" $ do let swag = toSwagger $ Proxy @API it "has properties of the main type" $ do let Just (Inline depSchema) = swag ^? definitions . at "side-loaded JSON: Album" . _Just . properties . at "dependencies" . _Just Just props = depSchema ^? properties (S.fromList . O.keys $ props) `shouldBe` S.fromList ["photos", "person"] -------------------------------------------------------------------------------- -- | api -------------------------------------------------------------------------------- type API = "album" :> Get '[JSON] Album :> SideLoad [Person, [Photo]] -------------------------------------------------------------------------------- -- | Data -------------------------------------------------------------------------------- -- | Photo newtype PhotoId = PhotoId Int deriving (Eq, Show, Num, Generic, ToJSON, FromJSON) instance ToSchema PhotoId type instance NamedDependency [Photo] = "photos" type instance NamedDependency [PhotoId] = "photoIds" data Photo = Photo { photoId :: PhotoId , photoCaption :: String , artistId :: PersonId } deriving (Eq, Show, Generic) instance ToJSON Photo instance FromJSON Photo type instance NamedDependency [Photo] = "photos" examplePhotos :: Photo examplePhotos = Photo 1 "At the Beach." 1 instance ToSchema Photo where declareNamedSchema p = genericDeclareNamedSchema defaultSchemaOptions p & mapped.schema.example ?~ toJSON examplePhotos -- | Person newtype PersonId = PersonId Int deriving (Eq, Show, Num, Generic, ToJSON, FromJSON) instance ToSchema PersonId type instance NamedDependency Person = "person" data Person = Person { personId :: PersonId , personName :: String } deriving (Eq, Show, Generic) instance ToJSON Person instance FromJSON Person examplePerson :: Person examplePerson = Person 1 "Alice" type instance NamedDependency Person = "person" instance ToSchema Person where declareNamedSchema p = genericDeclareNamedSchema defaultSchemaOptions p & mapped.schema.example ?~ toJSON examplePerson -- | Albums newtype AlbumId = AlbumId Int deriving (Eq, Show, Generic, Num, ToJSON, FromJSON) instance ToSchema AlbumId data Album = Album { albumId :: AlbumId , albumName :: String , albumOwner :: PersonId , albumPhotos :: [PhotoId] } deriving (Eq, Show, Generic) instance ToJSON Album instance FromJSON Album exampleAlbum :: Album exampleAlbum = Album 1 "Vacations" 1 [1] instance ToSchema Album where declareNamedSchema p = genericDeclareNamedSchema defaultSchemaOptions p & mapped.schema.example ?~ toJSON exampleAlbum