freckle-app-1.20.3.0: tests/Freckle/App/TextualEnumSpec.hs
module Freckle.App.TextualEnumSpec
( spec
) where
import Freckle.App.Prelude
import Data.Aeson qualified as JSON
import Data.Csv qualified as CSV
import Data.List.NonEmpty (NonEmpty ((:|)))
import Database.Persist.Sql qualified as Sql
import Freckle.App.Test.Properties.JSON
import Freckle.App.Test.Properties.PathPiece
import Freckle.App.Test.Properties.PersistValue
import Freckle.App.TextualEnum
import Servant qualified
import Test.Hspec
import Test.QuickCheck
import Web.PathPieces qualified as Path
data PrimaryColor
= Red
| Blue
| Yellow
deriving stock (Bounded, Enum, Eq, Show)
deriving
( CSV.ToField
, CSV.FromField
, JSON.ToJSON
, JSON.FromJSON
, Servant.FromHttpApiData
, Servant.ToHttpApiData
, Path.PathPiece
, Sql.PersistField
, Arbitrary
)
via TextualEnum PrimaryColor
instance EnumValue PrimaryColor where
toText = \case
Red -> "red"
Blue -> "blue"
Yellow -> "yellow"
data BadExample
= Okay
| Conflict1
| Conflict2
deriving stock (Bounded, Enum, Eq, Show)
instance EnumValue BadExample where
toText = \case
Okay -> "ok"
Conflict1 -> "conflict"
Conflict2 -> "conflict"
spec :: Spec
spec = do
describe "TextualEnum" $ do
describe "JSON" $
it "round trips" $
property $
prop_roundTripJSON @PrimaryColor
describe "PathPiece" $
it "round trips" $
property $
prop_roundTripPathPiece @PrimaryColor
describe "HttpApiData" $
it "round trips" $
property $
\(e :: PrimaryColor) -> Servant.parseUrlPiece (Servant.toUrlPiece e) == Right e
describe "PersistValue" $
it "round trips" $
property $
prop_roundTripPersistValue @PrimaryColor
describe "CSV" $
it "round trips" $
property $ \(e :: PrimaryColor) ->
CSV.runParser (CSV.parseField $ CSV.toField e) == Right e
describe "prop_roundTripEnumText" $ do
it "holds for a well defined toText" $
property $
prop_roundTripEnumText @PrimaryColor
it "does not hold when toText doesn't map to distinct values" $
any (not . prop_roundTripEnumText @BadExample) enums
describe "enums" $ do
it "returns all values" $
enums @PrimaryColor
`shouldBe` fmap TextualEnum (Red :| [Blue, Yellow])