summoner-2.2.0.0: test/Test/TomlSpec.hs
module Test.TomlSpec
( tomlSpec
) where
import Hedgehog (MonadGen, forAll, tripping)
import Test.Hspec (Spec, describe, it, shouldReturn, shouldSatisfy)
import Test.Hspec.Hedgehog (hedgehog)
import Toml.Codec.Code (decode, encode)
import Validation (isSuccess)
import Summoner.Config (ConfigP (..), PartialConfig, configCodec, defaultConfig, finalise)
import Summoner.CustomPrelude (CustomPrelude (..))
import Summoner.Default (defaultConfigFileContent)
import Summoner.GhcVer (GhcVer)
import Summoner.License (LicenseName)
import Summoner.Source (Source (..))
import Test.DecisionSpec (genDecision)
import qualified Data.Text as T
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
tomlSpec :: Spec
tomlSpec = describe "TOML Testing" $ do
tomlConfigSpec
tomlProp
tomlConfigSpec :: Spec
tomlConfigSpec = describe "TOML configuration spec" $ do
it "finalises default configuration" $
finalise defaultConfig `shouldSatisfy` isSuccess
it "parses default configuration" $
decode configCodec defaultConfigFileContent `shouldSatisfy` isRight
it "default configuration is up-to-date" $
-- Normalize line endings (CRLF -> LF) for cross-platform compatibility
T.filter (/= '\r') . decodeUtf8 <$> readFileBS "examples/summoner-default.toml"
`shouldReturn` defaultConfigFileContent
tomlProp :: Spec
tomlProp = describe "TOML property tests" $
it "decode . encode == id" $ hedgehog $ do
configToml <- forAll genPartialConfig
tripping configToml (encode configCodec) (decode configCodec)
----------------------------------------------------------------------------
-- Generators
----------------------------------------------------------------------------
genTextWithSeparator :: MonadGen m => Char -> m Text
genTextWithSeparator s = do
x <- T.toUpper <$> genText
y <- T.toUpper <$> genText
Gen.element [x, x <> T.cons s y]
genText :: MonadGen m => m Text
genText = Gen.text
(Range.constant 1 11)
Gen.alpha
genString :: MonadGen m => m String
genString = Gen.list (Range.constant 0 100) Gen.alphaNum
genTextArr :: MonadGen m => m [Text]
genTextArr = Gen.list (Range.constant 0 10) genText
genGhcVerArr :: MonadGen m => m [GhcVer]
genGhcVerArr = Gen.list (Range.constant 0 10) Gen.enumBounded
genCustomPrelude :: MonadGen m => m CustomPrelude
genCustomPrelude = do
cpPackage <- genTextWithSeparator '-'
cpModule <- genTextWithSeparator '.'
pure CustomPrelude{..}
genLicense :: MonadGen m => m LicenseName
genLicense = Gen.element universe
genSource :: MonadGen m => m Source
genSource = do
txt <- genText
s <- Gen.element [Local . toString, Url, Raw]
pure $ s txt
genPartialConfig :: MonadGen m => m PartialConfig
genPartialConfig = do
cOwner <- Last <$> Gen.maybe genText
cFullName <- Last <$> Gen.maybe genText
cEmail <- Last <$> Gen.maybe genText
cLicense <- Last <$> Gen.maybe genLicense
cGhcVer <- Last <$> Gen.maybe genGhcVerArr
cCabal <- genDecision
cStack <- genDecision
cGitHub <- genDecision
cGhActions <- genDecision
cTravis <- genDecision
cAppVey <- genDecision
cPrivate <- genDecision
cLib <- genDecision
cExe <- genDecision
cTest <- genDecision
cBench <- genDecision
cPrelude <- Last <$> Gen.maybe genCustomPrelude
cExtensions <- genTextArr
cGhcOptions <- genTextArr
cGitignore <- genTextArr
cNoUpload <- Any <$> Gen.bool
cFiles <- Gen.map (Range.constant 0 10) (liftA2 (,) genString genSource)
cBranchName <- Last <$> Gen.maybe genText
pure ConfigP{..}