{-# LANGUAGE CPP #-}

module Test.Syd.Validity.Property.Utils
  ( forAllUnchecked,
    forAllValid,
    forAllInvalid,
    shouldBeValid,
    shouldBeInvalid,
    (<==>),
    (===>),
  )
where

import Data.GenValidity
import Test.QuickCheck
import Test.Syd

#if !MIN_VERSION_base(4,8,0)
import Control.Applicative (pure)
#endif

forAllUnchecked ::
  (Show a, GenUnchecked a, Testable prop) => (a -> prop) -> Property
forAllUnchecked :: (a -> prop) -> Property
forAllUnchecked = Gen a -> (a -> [a]) -> (a -> prop) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> [a]) -> (a -> prop) -> Property
forAllShrink Gen a
forall a. GenUnchecked a => Gen a
genUnchecked a -> [a]
forall a. GenUnchecked a => a -> [a]
shrinkUnchecked

forAllValid :: (Show a, GenValid a, Testable prop) => (a -> prop) -> Property
forAllValid :: (a -> prop) -> Property
forAllValid = Gen a -> (a -> [a]) -> (a -> prop) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> [a]) -> (a -> prop) -> Property
forAllShrink Gen a
forall a. GenValid a => Gen a
genValid a -> [a]
forall a. GenValid a => a -> [a]
shrinkValid

forAllInvalid ::
  (Show a, GenInvalid a, Testable prop) => (a -> prop) -> Property
forAllInvalid :: (a -> prop) -> Property
forAllInvalid = Gen a -> (a -> [a]) -> (a -> prop) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> [a]) -> (a -> prop) -> Property
forAllShrink Gen a
forall a. GenInvalid a => Gen a
genInvalid a -> [a]
forall a. GenInvalid a => a -> [a]
shrinkInvalid

(===>) :: Bool -> Bool -> Bool
===> :: Bool -> Bool -> Bool
(===>) Bool
a Bool
b = Bool -> Bool
not Bool
a Bool -> Bool -> Bool
|| Bool
b

(<==>) :: Bool -> Bool -> Bool
<==> :: Bool -> Bool -> Bool
(<==>) Bool
a Bool
b = Bool
a Bool -> Bool -> Bool
===> Bool
b Bool -> Bool -> Bool
&& Bool
b Bool -> Bool -> Bool
===> Bool
a

shouldBeValid :: (Show a, Validity a) => a -> Expectation
shouldBeValid :: a -> Expectation
shouldBeValid a
a =
  case a -> Either String a
forall a. Validity a => a -> Either String a
prettyValidate a
a of
    Right a
_ -> () -> Expectation
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    Left String
err ->
      String -> Expectation
forall a. HasCallStack => String -> IO a
expectationFailure (String -> Expectation) -> String -> Expectation
forall a b. (a -> b) -> a -> b
$
        [String] -> String
unlines
          [ String
"'validate' reported this value to be invalid: ",
            a -> String
forall a. Show a => a -> String
show a
a,
            String
"pretty version:",
            a -> String
forall a. Show a => a -> String
ppShow a
a,
            String
"with explanation:",
            String
err,
            String
""
          ]

shouldBeInvalid :: (Show a, Validity a) => a -> Expectation
shouldBeInvalid :: a -> Expectation
shouldBeInvalid a
a =
  case a -> Either String a
forall a. Validity a => a -> Either String a
prettyValidate a
a of
    Right a
_ ->
      String -> Expectation
forall a. HasCallStack => String -> IO a
expectationFailure (String -> Expectation) -> String -> Expectation
forall a b. (a -> b) -> a -> b
$
        [String] -> String
unlines
          [ String
"'validate' reported this value to be valid: ",
            a -> String
forall a. Show a => a -> String
show a
a,
            String
"pretty version:",
            a -> String
forall a. Show a => a -> String
ppShow a
a,
            String
"where we expected it to be invalid"
          ]
    Left String
_ -> () -> Expectation
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()