module Main where
import Control.Monad (unless)
import Data.List (isInfixOf)
import Test.Tasty
import Test.Tasty.HUnit
import qualified Text.Pandoc.Filter.Pyplot as Filter
import qualified Text.Pandoc.Filter.Scripting as Filter
import Text.Pandoc.JSON
import System.Directory (doesFileExist)
import System.FilePath ((</>))
import System.IO.Temp (getCanonicalTemporaryDirectory)
main :: IO ()
main = defaultMain $
testGroup "Text.Pandoc.Filter.Pyplot"
[ testFileCreation
, testFileInclusion
, testBlockingCallError
]
-- | Create a code block with the right attributes to trigger pandoc-pyplot
mkPlotCodeBlock :: FilePath -- ^ Plot target
-> String -- ^ Plot alt description
-> String -- ^ Plot caption
-> Maybe FilePath -- ^ Possible inclusion
-> Filter.PythonScript -- ^ Script
-> Block
mkPlotCodeBlock target alt caption include script = CodeBlock attrs script
where
attrs = case include of
Nothing -> ( mempty , mempty
, [ ("plot_target", target)
, ("plot_alt", alt)
, ("plot_caption", caption)
]
)
Just includePath -> ( mempty , mempty
, [ ("plot_target", target)
, ("plot_alt", alt)
, ("plot_caption", caption)
, ("plot_include", includePath)
]
)
-- | Assert that a file exists
assertFileExists :: HasCallStack
=> FilePath
-> Assertion
assertFileExists filepath = do
fileExists <- doesFileExist filepath
unless fileExists (assertFailure msg)
where
msg = mconcat ["File ", filepath, " does not exist."]
-- | Assert that a list first list is contained,
-- wholly and intact, anywhere within the second.
assertIsInfix :: (Eq a, Show a, HasCallStack)
=> [a]
-> [a]
-> Assertion
assertIsInfix xs ys =
unless (xs `isInfixOf` ys) (assertFailure msg)
where
msg = mconcat ["Expected ", show xs, " to be an infix of ", show ys]
-------------------------------------------------------------------------------
-- Test that plot files and source files are created when the filter is run
testFileCreation :: TestTree
testFileCreation = testCase "writes output and source files" $ do
tempDir <- getCanonicalTemporaryDirectory
let codeBlock = mkPlotCodeBlock
(tempDir </> "test.png")
mempty
mempty
Nothing
"import matplotlib.pyplot as plt\n"
_ <- Filter.makePlot' codeBlock
assertFileExists (tempDir </> "test.png")
assertFileExists (tempDir </> "test.txt")
-------------------------------------------------------------------------------
-- Test that included files are found within the source
testFileInclusion :: TestTree
testFileInclusion = testCase "includes plot inclusions" $ do
tempDir <- getCanonicalTemporaryDirectory
let codeBlock = mkPlotCodeBlock
(tempDir </> "test.png")
mempty
mempty
(Just "test/fixtures/include.py")
"import matplotlib.pyplot as plt\n"
_ <- Filter.makePlot' codeBlock
inclusion <- readFile "test/fixtures/include.py"
src <- readFile (tempDir </> "test.txt")
assertIsInfix inclusion src
-------------------------------------------------------------------------------
-- Test that a script containing a blockign call to matplotlib.pyplot.show
-- returns the appropriate error
testBlockingCallError :: TestTree
testBlockingCallError = testCase "raises an exception for blocking calls" $ do
tempDir <- getCanonicalTemporaryDirectory
let codeBlock = mkPlotCodeBlock
(tempDir </> "test.png")
mempty
mempty
Nothing
"import matplotlib.pyplot as plt\nplt.show()"
result <- Filter.makePlot' codeBlock
case result of
Right block -> assertFailure "did not catch the expected blocking call"
Left error ->
if error == Filter.BlockingCallError
then pure ()
else assertFailure "did not catch the expected blocking call"
-------------------------------------------------------------------------------