packages feed

sydtest-0.18.0.0: src/Test/Syd/Def/Golden.hs

module Test.Syd.Def.Golden
  ( module Test.Syd.Def.Golden,
    GoldenTest (..),
  )
where

import Data.ByteString (ByteString)
import qualified Data.ByteString as SB
import qualified Data.ByteString.Builder as SBB
import qualified Data.ByteString.Lazy as LB
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import Path
import Path.IO
import Test.Syd.Expectation
import Test.Syd.Run
import Text.Show.Pretty

-- | Test that the given bytestring is the same as what we find in the given golden file.
pureGoldenByteStringFile :: FilePath -> ByteString -> GoldenTest ByteString
pureGoldenByteStringFile fp bs = goldenByteStringFile fp (pure bs)

-- | Test that the produced bytestring is the same as what we find in the given golden file.
goldenByteStringFile :: FilePath -> IO ByteString -> GoldenTest ByteString
goldenByteStringFile fp produceBS =
  GoldenTest
    { goldenTestRead = do
        resolvedFile <- resolveFile' fp
        forgivingAbsence $ SB.readFile $ fromAbsFile resolvedFile,
      goldenTestProduce = produceBS,
      goldenTestWrite = \actual -> do
        resolvedFile <- resolveFile' fp
        ensureDir $ parent resolvedFile
        SB.writeFile (fromAbsFile resolvedFile) actual,
      goldenTestCompare = \actual expected ->
        if actual == expected
          then pure Nothing
          else do
            assertion <- bytestringsNotEqualButShouldHaveBeenEqual actual expected
            pure $ Just $ Context assertion (goldenContext fp)
    }

-- | Test that the given lazy bytestring is the same as what we find in the given golden file.
--
-- Note: This converts the lazy bytestring to a strict bytestring first.
pureGoldenLazyByteStringFile :: FilePath -> LB.ByteString -> GoldenTest LB.ByteString
pureGoldenLazyByteStringFile fp bs = goldenLazyByteStringFile fp (pure bs)

-- | Test that the produced bytestring is the same as what we find in the given golden file.
--
-- Note: This converts the lazy bytestring to a strict bytestring first.
goldenLazyByteStringFile :: FilePath -> IO LB.ByteString -> GoldenTest LB.ByteString
goldenLazyByteStringFile fp produceBS =
  GoldenTest
    { goldenTestRead = do
        resolvedFile <- resolveFile' fp
        forgivingAbsence $ fmap LB.fromStrict $ SB.readFile $ fromAbsFile resolvedFile,
      goldenTestProduce = produceBS,
      goldenTestWrite = \actual -> do
        resolvedFile <- resolveFile' fp
        ensureDir $ parent resolvedFile
        SB.writeFile (fromAbsFile resolvedFile) (LB.toStrict actual),
      goldenTestCompare = \actual expected ->
        let actualBS = LB.toStrict actual
            expectedBS = LB.toStrict expected
         in if actualBS == expectedBS
              then pure Nothing
              else do
                assertion <- bytestringsNotEqualButShouldHaveBeenEqual actualBS expectedBS
                pure $ Just $ Context assertion (goldenContext fp)
    }

-- | Test that the given lazy bytestring is the same as what we find in the given golden file.
--
-- Note: This converts the builder to a strict bytestring first.
pureGoldenByteStringBuilderFile :: FilePath -> SBB.Builder -> GoldenTest SBB.Builder
pureGoldenByteStringBuilderFile fp bs = goldenByteStringBuilderFile fp (pure bs)

-- | Test that the produced bytestring is the same as what we find in the given golden file.
--
-- Note: This converts the builder to a strict bytestring first.
goldenByteStringBuilderFile :: FilePath -> IO SBB.Builder -> GoldenTest SBB.Builder
goldenByteStringBuilderFile fp produceBS =
  GoldenTest
    { goldenTestRead = do
        resolvedFile <- resolveFile' fp
        forgivingAbsence $ fmap SBB.byteString $ SB.readFile $ fromAbsFile resolvedFile,
      goldenTestProduce = produceBS,
      goldenTestWrite = \actual -> do
        resolvedFile <- resolveFile' fp
        ensureDir $ parent resolvedFile
        SB.writeFile (fromAbsFile resolvedFile) (LB.toStrict (SBB.toLazyByteString actual)),
      goldenTestCompare = \actual expected ->
        let actualBS = LB.toStrict (SBB.toLazyByteString actual)
            expectedBS = LB.toStrict (SBB.toLazyByteString expected)
         in if actualBS == expectedBS
              then pure Nothing
              else do
                assertion <- bytestringsNotEqualButShouldHaveBeenEqual actualBS expectedBS
                pure $ Just $ Context assertion (goldenContext fp)
    }

-- | Test that the given text is the same as what we find in the given golden file.
pureGoldenTextFile :: FilePath -> Text -> GoldenTest Text
pureGoldenTextFile fp bs = goldenTextFile fp (pure bs)

-- | Test that the produced text is the same as what we find in the given golden file.
goldenTextFile :: FilePath -> IO Text -> GoldenTest Text
goldenTextFile fp produceBS =
  GoldenTest
    { goldenTestRead = do
        resolvedFile <- resolveFile' fp
        forgivingAbsence $ TE.decodeUtf8 <$> SB.readFile (fromAbsFile resolvedFile),
      goldenTestProduce = produceBS,
      goldenTestWrite = \actual -> do
        resolvedFile <- resolveFile' fp
        ensureDir $ parent resolvedFile
        SB.writeFile (fromAbsFile resolvedFile) (TE.encodeUtf8 actual),
      goldenTestCompare = \actual expected ->
        if actual == expected
          then pure Nothing
          else do
            assertion <- textsNotEqualButShouldHaveBeenEqual actual expected
            pure $ Just $ Context assertion (goldenContext fp)
    }

-- | Test that the given string is the same as what we find in the given golden file.
pureGoldenStringFile :: FilePath -> String -> GoldenTest String
pureGoldenStringFile fp bs = goldenStringFile fp (pure bs)

-- | Test that the produced string is the same as what we find in the given golden file.
goldenStringFile :: FilePath -> IO String -> GoldenTest String
goldenStringFile fp produceBS =
  GoldenTest
    { goldenTestRead = do
        resolvedFile <- resolveFile' fp
        forgivingAbsence $ fmap T.unpack $ TE.decodeUtf8 <$> SB.readFile (fromAbsFile resolvedFile),
      goldenTestProduce = produceBS,
      goldenTestWrite = \actual -> do
        resolvedFile <- resolveFile' fp
        ensureDir $ parent resolvedFile
        SB.writeFile (fromAbsFile resolvedFile) (TE.encodeUtf8 (T.pack actual)),
      goldenTestCompare = \actual expected ->
        if actual == expected
          then pure Nothing
          else do
            assertion <- stringsNotEqualButShouldHaveBeenEqual actual expected
            pure $ Just $ Context assertion (goldenContext fp)
    }

-- | Test that the show instance has not changed for the given value.
goldenShowInstance :: (Show a) => FilePath -> a -> GoldenTest String
goldenShowInstance fp a = pureGoldenStringFile fp (show a)

-- | Test that the show instance has not changed for the given value, via `ppShow`.
goldenPrettyShowInstance :: (Show a) => FilePath -> a -> GoldenTest String
goldenPrettyShowInstance fp a = pureGoldenStringFile fp (ppShow a)

-- | The golden test context for adding context to a golden test assertion:
--
-- > goldenTestCompare = \actual expected ->
-- >   if actual == expected
-- >     then Nothing
-- >     else Just $ Context (stringsNotEqualButShouldHaveBeenEqual actual expected) (goldenContext fp)
goldenContext :: FilePath -> String
goldenContext fp = "The golden results are in: " <> fp