{-# LANGUAGE DeriveGeneric #-} module Main (main) where import Data.Proxy (Proxy (..)) import Data.TreeDiff import Data.TreeDiff.Golden import Data.TreeDiff.QuickCheck import GHC.Generics (Generic) import Prelude () import Prelude.Compat import Test.QuickCheck (Property, counterexample) import Test.Tasty (TestTree, defaultMain, testGroup) import Test.Tasty.Golden.Advanced (goldenTest) import Test.Tasty.QuickCheck (testProperty) import qualified Text.Parsec as P import qualified Text.PrettyPrint.ANSI.Leijen as WL import qualified Text.Trifecta as T (eof, parseString) import qualified Text.Trifecta.Result as T (ErrInfo (..), Result (..)) main :: IO () main = defaultMain $ testGroup "tests" [ testProperty "trifecta-pretty roundtrip" roundtripTrifectaPretty , testProperty "parsec-ansi-wl-pprint roundtrip" roundtripParsecAnsiWl , exFooTests ] ------------------------------------------------------------------------------- -- QuickCheck: ediffEq ------------------------------------------------------------------------------- -- | This property tests that we can parse pretty printed 'Expr'. -- -- We demonstrate the use of 'ediffEq'. We could used '===' there, -- but now the nice diff will be printed as well -- (as there is 'ToExpr Expr' instance). roundtripTrifectaPretty :: Expr -> Property roundtripTrifectaPretty e = counterexample info $ ediffEq (Just e) res' where doc = show (prettyExpr e) res = T.parseString (exprParser <* T.eof) mempty doc info = case res of T.Success e' -> doc ++ "\n" ++ show e' T.Failure err -> doc ++ "\n" ++ show (T._errDoc err) res' = case res of T.Success e' -> Just e' T.Failure _ -> Nothing roundtripParsecAnsiWl :: Expr -> Property roundtripParsecAnsiWl e = counterexample info $ ediffEq (Just e) res' where doc = show (WL.plain (ansiWlExpr e)) res = P.parse (exprParser <* P.eof) "" doc info = case res of Right e' -> doc ++ "\n" ++ show e' Left err -> doc ++ "\n" ++ show err res' = either (const Nothing) Just res ------------------------------------------------------------------------------- -- Golden ------------------------------------------------------------------------------- -- | This test case verifies that we don't change 'Foo' or 'exFoo'. -- -- We demonstrate the use of 'ediffGolden'. -- -- First we declare a type, make it instance of 'ToExpr' and define -- an example value 'exFoo'. In real-world you might e.g. read the source -- file and parse it into the AST type. -- -- Then we create a golden test that verifies that version we got now, -- is the same we had previously. @tree-diff@ seralises the 'Expr', -- not the original value. This is a design trade-off: -- as we can always deserialise we can better diff the values even the -- type is changed, e.g. the fields is added. data Foo = Foo { fooInt :: Int , fooBar :: [Maybe String] , fooQuu :: (Double, Proxy ()) , fooNew :: Bool , fooStr :: String } deriving (Eq, Show, Generic) instance ToExpr Foo exFoo :: Foo exFoo = Foo { fooInt = 42 , fooBar = [Just "pub", Just "night\nclub"] , fooQuu = (125.375, Proxy) , fooNew = True , fooStr = "Some Name" } exFooTests :: TestTree exFooTests = ediffGolden goldenTest "golden exFoo" "fixtures/exfoo.expr" $ return exFoo