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

-- | Tests for Arbitrary instances involving Validity
--
-- You will need @TypeApplications@ to use these.
module Test.Validity.Arbitrary
    ( arbitrarySpec
    , arbitraryGeneratesOnlyValid
    ) where

import Data.Data

import Data.GenValidity

import Test.Hspec
import Test.QuickCheck

import Test.Validity.GenValidity
import Test.Validity.Utils

-- | A @Spec@ that specifies that @arbitrary@ only generates data that
-- satisfy @isValid@
--
-- Example usage:
--
-- > arbitrarySpec @Int
arbitrarySpec ::
       forall a. (Typeable a, Show a, Validity a, Arbitrary a)
    => Spec
arbitrarySpec = do
    let name = nameOf @a
    describe ("Arbitrary " ++ name) $
        describe ("arbitrary :: Gen " ++ name) $
        it "only generates valid values" $ arbitraryGeneratesOnlyValid @a

-- | @arbitrary@ only generates valid data
--
-- prop> arbitraryGeneratesOnlyValid @Int
arbitraryGeneratesOnlyValid ::
       forall a. (Show a, Validity a, Arbitrary a)
    => Property
arbitraryGeneratesOnlyValid = genGeneratesValid @a arbitrary shrink