packages feed

aeson-schemas-1.3.4: test/Tests/EnumTH.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}

module Tests.EnumTH where

import Data.Aeson (decode, encode)
import Data.Char (toLower, toUpper)
import Test.Tasty
import Test.Tasty.HUnit
import Test.Tasty.QuickCheck

import Data.Aeson.Schema.TH (genFromJSONEnum, genToJSONEnum, mkEnum)

mkEnum "State" ["OPEN", "CLOSED"]

data Color = Red | LightBlue | Yellow | DarkGreen | Black | JustABitOffWhite
  deriving (Show, Eq, Enum)

genFromJSONEnum ''Color
genToJSONEnum ''Color

{- Tests -}

test :: TestTree
test =
  testGroup
    "Enum TH helpers"
    [ testMkEnum
    , testGenJSONEnum
    ]

testMkEnum :: TestTree
testMkEnum =
  testGroup
    "mkEnum"
    [ testProperty "mkEnum decode is case insensitive" $ do
        (val, enumVal) <-
          elements
            [ ("OPEN", OPEN)
            , ("CLOSED", CLOSED)
            ]
        casedVal <- randomlyCased val
        return $ decode (encode casedVal) === Just enumVal
    , testCase "mkEnum encode keeps case of constructor" $ do
        encode OPEN @?= "\"OPEN\""
        encode CLOSED @?= "\"CLOSED\""
    , testProperty "mkEnum: (fromJust . decode . encode) === id" $ do
        enumVal <- elements [OPEN, CLOSED]
        return $ (decode . encode) enumVal === Just enumVal
    ]

testGenJSONEnum :: TestTree
testGenJSONEnum =
  testGroup
    "gen{To,From}JSONEnum"
    [ testProperty "genFromJSONEnum decode is case insensitive" $ do
        (val, enumVal) <-
          elements
            [ ("Red", Red)
            , ("LightBlue", LightBlue)
            , ("Yellow", Yellow)
            , ("DarkGreen", DarkGreen)
            , ("Black", Black)
            , ("JustABitOffWhite", JustABitOffWhite)
            ]
        casedVal <- randomlyCased val
        return $ decode (encode casedVal) === Just enumVal
    , testCase "genToJSONEnum encode keeps case of constructor" $ do
        encode Red @?= "\"Red\""
        encode LightBlue @?= "\"LightBlue\""
        encode Yellow @?= "\"Yellow\""
        encode DarkGreen @?= "\"DarkGreen\""
        encode Black @?= "\"Black\""
        encode JustABitOffWhite @?= "\"JustABitOffWhite\""
    , testProperty "genFromJSONEnum + genToJSONEnum: (fromJust . decode . encode) === id" $ do
        enumVal <-
          elements
            [ Red
            , LightBlue
            , Yellow
            , DarkGreen
            , Black
            , JustABitOffWhite
            ]
        return $ (decode . encode) enumVal === Just enumVal
    ]

randomlyCased :: String -> Gen String
randomlyCased s = do
  caseFuncs <- infiniteListOf $ elements [toLower, toUpper]
  return $ zipWith ($) caseFuncs s