{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
-- Because of webdriver using dangerous constructors
{-# OPTIONS_GHC -fno-warn-incomplete-record-updates #-}
-- For the undefined trick
{-# OPTIONS_GHC -fno-warn-unused-pattern-binds #-}
module Test.Syd.Webdriver.Screenshot where
import Codec.Picture as Picture
import Control.Monad.Reader
import qualified Data.ByteString as SB
import qualified Data.ByteString.Lazy as LB
import Path
import Path.IO
import System.Exit
import Test.Syd
import Test.Syd.Webdriver
import Test.WebDriver as WD
-- | A screenshot with location
data Screenshot = Screenshot
{ -- | File location for comparisons
screenshotFile :: !(Path Abs File),
-- | Decoded image
screenshotImage :: !(Picture.Image PixelRGB8)
}
-- | Take a screenshot and turn it into a golden test.
goldenScreenshotHere :: FilePath -> WebdriverTestM app (GoldenTest Screenshot)
goldenScreenshotHere fp = pureGoldenScreenshot fp <$> WD.screenshot
-- | Make a golden test for a given screenshot in lazy 'LB.ByteString' form.
pureGoldenScreenshot :: FilePath -> LB.ByteString -> GoldenTest Screenshot
pureGoldenScreenshot fp contents =
GoldenTest
{ goldenTestRead = do
relFile <- parseRelFile fp
currentDir <- getCurrentDir
let resolvedFile = currentDir </> relFile
mContents <- forgivingAbsence $ SB.readFile $ fromAbsFile resolvedFile
forM mContents $ \cts -> do
case decodePng cts of
Left err -> die err
Right dynamicImage ->
pure $
Screenshot
{ screenshotFile = resolvedFile,
screenshotImage = convertRGB8 dynamicImage
},
goldenTestProduce = do
let sb = LB.toStrict contents
case decodePng sb of
Left err -> expectationFailure $ "Could not parse screenshot as png: " <> err
Right dynamicImage -> do
let image = convertRGB8 dynamicImage
relFile <- parseRelFile fp
tempDir <- resolveDir' "screenshot-comparison"
let tempFile = tempDir </> relFile
ensureDir $ parent tempFile
-- Write it to a file so we can compare it if it differs.
writePng (fromAbsFile tempFile) image
pure $
Screenshot
{ screenshotFile = tempFile,
screenshotImage = image
},
goldenTestWrite = \(Screenshot _ actual) -> do
relFile <- parseRelFile fp
currentDir <- getCurrentDir
let resolvedFile = currentDir </> relFile
ensureDir $ parent resolvedFile
writePng (fromAbsFile resolvedFile) actual,
goldenTestCompare = \(Screenshot actualPath actual) (Screenshot expectedPath expected) ->
if actual == expected
then Nothing
else
Just $
ExpectationFailed $
unlines
[ "Screenshots differ.",
"expected: " <> fromAbsFile expectedPath,
"actual: " <> fromAbsFile actualPath
]
}