/
Spec.hs
88 lines (77 loc) · 2.89 KB
/
Spec.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
module Main (main) where
import Control.Monad
import Data.Aeson
import Data.ByteString (ByteString)
import Data.FileEmbed (embedFile)
import Data.Map (Map, (!))
import Data.Text (Text)
import Data.Yaml
import Test.Hspec
import Text.Megaparsec
import Text.Mustache
import Text.Mustache.Parser
import qualified Data.Map as M
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
-- | Representation of information contained in a Mustache spec file.
data SpecFile = SpecFile
{ specOverview :: Text -- ^ Textual overview of this spec file
, specTests :: [Test] -- ^ The actual collection of tests
}
instance FromJSON SpecFile where
parseJSON = withObject "Mustache spec file" $ \o -> do
specOverview <- o .: "overview"
specTests <- o .: "tests"
return SpecFile {..}
-- | Representation of a single test.
data Test = Test
{ testName :: String
, testDesc :: String
, testData :: Value
, testTemplate :: Text
, testExpected :: Text
, testPartials :: Map Text Text
}
instance FromJSON Test where
parseJSON = withObject "Test" $ \o -> do
testName <- o .: "name"
testDesc <- o .: "desc"
testData <- o .: "data"
testTemplate <- o .: "template"
testExpected <- o .: "expected"
testPartials <- o .:? "partials" .!= M.empty
return Test {..}
main :: IO ()
main = hspec spec
spec :: Spec
spec = do
specData "Comments" $(embedFile "specification/comments.yml")
specData "Delimiters" $(embedFile "specification/delimiters.yml")
specData "Interpolation" $(embedFile "specification/interpolation.yml")
specData "Inverted" $(embedFile "specification/inverted.yml")
specData "Partials" $(embedFile "specification/partials.yml")
specData "Sections" $(embedFile "specification/sections.yml")
specData :: String -> ByteString -> Spec
specData aspect bytes = describe aspect $ do
let handleError = expectationFailure . parseErrorPretty
case decodeEither' bytes of
Left err ->
it "should load YAML specs first" $
expectationFailure (prettyPrintParseException err)
Right SpecFile {..} ->
forM_ specTests $ \Test {..} ->
it (testName ++ ": " ++ testDesc) $
case compileMustacheText (PName $ T.pack testName) testTemplate of
Left perr -> handleError perr
Right Template {..} -> do
ps1 <- forM (M.keys testPartials) $ \k -> do
let pname = PName k
case parseMustache (T.unpack k) (testPartials ! k) of
Left perr -> handleError perr >> undefined
Right ns -> return (pname, ns)
let ps2 = M.fromList ps1 `M.union` templateCache
TL.toStrict (renderMustache (Template templateActual ps2) testData)
`shouldBe` testExpected