checkmate-0.4.0: test/Checkmate/Parser/CheckFileSpec.hs
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
module Checkmate.Parser.CheckFileSpec (spec) where
import Control.Monad
import System.IO (hClose)
import Data.Text
import Data.Text.IO
import Test.Hspec
import Test.Hspec.Megaparsec
import Text.InterpolatedString.Perl6
import Text.Megaparsec hiding (ParseError)
import System.FilePath
import System.IO.Temp
import Checkmate.Check
import Checkmate.Parser.CheckFile
spec :: Spec
spec = do
parserSpec "parser" $ \ text ->
return (".", parse (parser ".") ("." </> "CHECK") text)
parserSpec "parseCheckFileText" $ \ text ->
return (".", parseCheckFileText ("." </> "CHECK") text)
parserSpec "parseCheckFileText" $ \ text ->
withSystemTempFile "checkmate-test" $ \ filePath handle -> do
hPutStr handle text
hClose handle
result <- parseCheckFile filePath
return (takeDirectory filePath, result)
parserSpec :: String
-> ( Text -> IO (FilePath, Either ParseError Checklist)
)
-> Spec
parserSpec specName parseFn =
describe specName $ do
it "returns [] if a given text is empty" $ do
(_, parsed) <- parse' ""
parsed `shouldParse` []
let bulletStyles =
[ ("CHECK", "CHECK", "CHECK", "CHECK")
, ("CHECK:", "CHECK:", "CHECK:", "CHECK:")
, ("bullet \"*\"", "*", "*", "*")
, ("bullet \"-\"", "-", "-", "-")
, ("bullet \"+\"", "+", "+", "+")
, ("digit \"1.\"", "1.", "2.", "3.")
, ("digit \"1)\"", "1)", "2)", "3)")
] :: [(Text, Text, Text, Text)]
forM_ bulletStyles $ \ (styleName, b1, b2, b3) -> do
it [qq|interprets $styleName line as a Check|] $ do
(dir, parsed) <- parse' [qq|$b1 foo|]
parsed `shouldParse` [Check dir 1 "foo"]
let nl = "\n" :: Text
it [qq|interprets multiple $styleName lines as [Check]|] $ do
(ad, a) <- parse' [qq|$b1 foo$nl$b2 bar$nl|]
a `shouldParse` [Check ad 1 "foo", Check ad 2 "bar"]
(bd, b) <- parse' [qq|$b1 foo$nl$b2 bar$nl$b3 baz|]
b `shouldParse` [ Check bd 1 "foo"
, Check bd 2 "bar"
, Check bd 3 "baz"
]
it [qq|interprets multiple lines as a Check until it's followed
by another $styleName|] $ do
(ad, a) <- parse' [qq|$b1 foo{nl}bar{nl}qux$nl|]
a `shouldParse` [Check ad 1 "foo\nbar\nqux"]
(bd, b) <- parse' [qq|$b1 foo{nl}bar$nl$b2 qux$nl|]
b `shouldParse` [Check bd 1 "foo\nbar", Check bd 2 "qux"]
it "ignores the leading spaces/empty lines" $ do
(_, a) <- parse' " "
a `shouldParse` []
(_, b) <- parse' "\t"
b `shouldParse` []
(_, c) <- parse' "\n"
c `shouldParse` []
(_, d) <- parse' "\r\n"
d `shouldParse` []
(_, e) <- parse' "\n\n"
e `shouldParse` []
(_, f) <- parse' " \t \n\n"
f `shouldParse` []
(dir, g) <- parse' (mconcat [" \t \n\n", b1, " foo"])
g `shouldParse` [Check dir 1 "foo"]
it "parses well even if bullet styles are mixed" $ do
(dir, parsed) <- parse'
"CHECK foo\nbar\n- baz\nqux\n* quz\n+ a\n1. b\n2) c\nCHECK: d"
parsed `shouldParse`
[ Check dir 1 "foo\nbar"
, Check dir 2 "baz\nqux"
, Check dir 3 "quz"
, Check dir 4 "a"
, Check dir 5 "b"
, Check dir 6 "c"
, Check dir 7 "d"
]
where
parse' :: Text -> IO (Scope, Either ParseError Checklist)
parse' text = do
(dir, result) <- parseFn text
return (Directory dir, result)