{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Test.Text.Roundtrip
    ( textRoundtrip
    ) where

import Prelude

import Data.Proxy
    ( Proxy )
import Data.Text.Class
    ( FromText (..), ToText (..) )
import Data.Typeable
    ( Typeable, typeRep )
import Test.Hspec
    ( Spec, it )
import Test.QuickCheck
    ( Arbitrary (..), property, (===) )

-- | Constructs a test to check that roundtrip textual encoding and decoding
-- is possible for values of the given type.
textRoundtrip
    :: forall a. (Arbitrary a, Eq a, Show a, ToText a, FromText a, Typeable a)
    => Proxy a
    -> Spec
textRoundtrip :: Proxy a -> Spec
textRoundtrip Proxy a
proxy = String -> Property -> SpecWith (Arg Property)
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it (TypeRep -> String
forall a. Show a => a -> String
show (Proxy a -> TypeRep
forall k (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep Proxy a
proxy)) (Property -> SpecWith (Arg Property))
-> Property -> SpecWith (Arg Property)
forall a b. (a -> b) -> a -> b
$
    (a -> Property) -> Property
forall prop. Testable prop => prop -> Property
property ((a -> Property) -> Property) -> (a -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \a
a -> Text -> Either TextDecodingError a
forall a. FromText a => Text -> Either TextDecodingError a
fromText (a -> Text
forall a. ToText a => a -> Text
toText @a a
a) Either TextDecodingError a
-> Either TextDecodingError a -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== a -> Either TextDecodingError a
forall a b. b -> Either a b
Right a
a