    {-# LANGUAGE AllowAmbiguousTypes #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE TypeApplications #-}

    -- | Tests for GenValidity instances
    --
    -- You will need @TypeApplications@ to use these.
    module Test.Validity.GenValidity
      ( genValidSpec,
        genValidGeneratesValid,
        genGeneratesValid,
        genGeneratesInvalid,
      )
    where

    import Data.Data
    import Data.GenValidity
    import Test.Hspec
    import Test.QuickCheck
    import Test.Validity.GenValidity.Property
    import Test.Validity.Utils

    -- | A @Spec@ that specifies that @genValid@ only generates valid data.
    --
    -- In general it is a good idea to add this spec to your test suite if you
    -- write a custom implementation of @genValid@.
    --
    -- Example usage:
    --
    -- > genValidSpec @Int
    genValidSpec ::
      forall a.
      (Typeable a, Show a, GenValid a) =>
      Spec
    genValidSpec :: forall a. (Typeable a, Show a, GenValid a) => Spec
    genValidSpec =
      Spec -> Spec
    forall a. SpecWith a -> SpecWith a
    parallel (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $ do
        let name :: String
    name = forall a. Typeable a => String
    forall {k} (a :: k). Typeable a => String
    nameOf @a
        String -> Spec -> Spec
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
    describe (String
    "GenValid " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    name) (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $
          String -> Spec -> Spec
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
    describe (String
    "genValid   :: Gen " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    name) (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $
            String -> Property -> SpecM (Arg Property) ()
    forall a.
    (HasCallStack, Example a) =>
    String -> a -> SpecWith (Arg a)
    it (String
    "only generates valid \'" String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    name String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    "\'s") (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              forall a. (Show a, GenValid a) => Property
    genValidGeneratesValid @a

    -- | @genValid@ only generates valid data
    --
    -- prop> genValidGeneratesValid @()
    -- prop> genValidGeneratesValid @Bool
    -- prop> genValidGeneratesValid @Ordering
    -- prop> genValidGeneratesValid @Char
    -- prop> genValidGeneratesValid @Int
    -- prop> genValidGeneratesValid @Float
    -- prop> genValidGeneratesValid @Double
    -- prop> genValidGeneratesValid @Integer
    -- prop> genValidGeneratesValid @(Maybe Int)
    -- prop> genValidGeneratesValid @[Int]
    genValidGeneratesValid ::
      forall a.
      (Show a, GenValid a) =>
      Property
    genValidGeneratesValid :: forall a. (Show a, GenValid a) => Property
    genValidGeneratesValid = forall a. (Show a, Validity a) => Gen a -> Property
    genGeneratesValid @a Gen a
    forall a. GenValid a => Gen a
    genValid