{-# LANGUAGE OverloadedStrings #-} module Main where import Data.Either import Data.Monoid (mempty) import qualified Data.Text as T import Test.Hspec import Text.Mustache import Text.Mustache.Types import Text.Mustache.Parser parserSpec :: Spec parserSpec = describe "mustacheParser" $ do let lparse = parse "testsuite" let returnedOne = return . return let text = "test12356p0--=-34{}jnv,\n" it "parses text" $ lparse text `shouldBe` returnedOne (MustacheText text) it "parses a variable" $ lparse "{{name}}" `shouldBe` returnedOne (MustacheVariable True ["name"]) it "parses a variable with whitespace" $ lparse "{{ name }}" `shouldBe` returnedOne (MustacheVariable True ["name"]) it "allows '-' in variable names" $ lparse "{{ name-name }}" `shouldBe` returnedOne (MustacheVariable True ["name-name"]) it "allows '_' in variable names" $ lparse "{{ name_name }}" `shouldBe` returnedOne (MustacheVariable True ["name_name"]) it "parses a variable unescaped with {{{}}}" $ lparse "{{{name}}}" `shouldBe` returnedOne (MustacheVariable False ["name"]) it "parses a variable unescaped with {{{}}} with whitespace" $ lparse "{{{ name }}}" `shouldBe` returnedOne (MustacheVariable False ["name"]) it "parses a variable unescaped with &" $ lparse "{{&name}}" `shouldBe` returnedOne (MustacheVariable False ["name"]) it "parses a variable unescaped with & with whitespace" $ lparse "{{& name }}" `shouldBe` returnedOne (MustacheVariable False ["name"]) it "parses a partial" $ lparse "{{>myPartial}}" `shouldBe` returnedOne (MustachePartial "myPartial") it "parses a partial with whitespace" $ lparse "{{> myPartial }}" `shouldBe` returnedOne (MustachePartial "myPartial") it "parses the an empty section" $ lparse "{{#section}}{{/section}}" `shouldBe` returnedOne (MustacheSection ["section"] mempty) it "parses the an empty section with whitespace" $ lparse "{{# section }}{{/ section }}" `shouldBe` returnedOne (MustacheSection ["section"] mempty) it "parses a delimiter change" $ lparse "{{=<< >>=}}<>{{var}}" `shouldBe` return [MustacheVariable True ["var"], MustacheText "{{var}}"] it "parses a delimiter change with whitespace" $ lparse "{{=<< >>=}}<< var >>{{var}}" `shouldBe` return [MustacheVariable True ["var"], MustacheText "{{var}}"] it "parses two subsequent delimiter changes" $ lparse "{{=(( ))=}}(( var ))((=-- $-=))--#section$---/section$-" `shouldBe` return [MustacheVariable True ["var"], MustacheSection ["section"] []] it "propagates a delimiter change from a nested scope" $ lparse "{{#section}}{{=<< >>=}}<><>" `shouldBe` return [MustacheSection ["section"] [], MustacheVariable True ["var"]] it "fails if the tag contains illegal characters" $ lparse "{{#&}}" `shouldSatisfy` isLeft it "parses a nested variable" $ lparse "{{ name.val }}" `shouldBe` returnedOne (MustacheVariable True ["name", "val"]) it "parses a variable containing whitespace" $ lparse "{{ val space }}" `shouldBe` returnedOne (MustacheVariable True ["val space"]) substituteSpec :: Spec substituteSpec = describe "substitute" $ do let toTemplate ast' = MustacheTemplate "testsuite" ast' [] it "substitutes a html escaped value for a variable" $ substitute (toTemplate [MustacheVariable True ["name"]]) (object ["name" ~> ("" :: T.Text)]) `shouldBe` return "<tag>" it "substitutes raw value for an unescaped variable" $ substitute (toTemplate [MustacheVariable False ["name"]]) (object ["name" ~> ("" :: T.Text)]) `shouldBe` return "" it "substitutes a section when the key is present (and an empty object)" $ substitute (toTemplate [MustacheSection ["section"] [MustacheText "t"]]) (object ["section" ~> object []]) `shouldBe` return "t" it "substitutes a section when the key is present (and 'true')" $ substitute (toTemplate [MustacheSection ["section"] [MustacheText "t"]]) (object ["section" ~> True]) `shouldBe` return "t" it "substitutes a section once when the key is present and a singleton list" $ substitute (toTemplate [MustacheSection ["section"] [MustacheText "t"]]) (object ["section" ~> ["True" :: T.Text]]) `shouldBe` return "t" it "substitutes a section twice when the key is present and a list with two items" $ substitute (toTemplate [MustacheSection ["section"] [MustacheText "t"]]) (object ["section" ~> (["True", "False"] :: [T.Text])]) `shouldBe` return "tt" it "substitutes a section twice when the key is present and a list with two\ \ objects, changing the scope to each object" $ substitute (toTemplate [MustacheSection ["section"] [MustacheVariable True ["t"]]]) (object [ "section" ~> [ object ["t" ~> ("var1" :: T.Text)] , object ["t" ~> ("var2" :: T.Text)] ] ]) `shouldBe` return "var1var2" it "does not substitute a section when the key is not present" $ substitute (toTemplate [MustacheSection ["section"] [MustacheText "t"]]) (object []) `shouldBe` return "" it "does not substitute a section when the key is present (and 'false')" $ substitute (toTemplate [MustacheSection ["section"] [MustacheText "t"]]) (object ["section" ~> False]) `shouldBe` return "" it "does not substitute a section when the key is present (and empty list)" $ substitute (toTemplate [MustacheSection ["section"] [MustacheText "t"]]) (object ["section" ~> ([] :: [T.Text])]) `shouldBe` return "" it "substitutes a nested section" $ substitute (toTemplate [MustacheVariable True ["outer", "inner"]]) (object [ "outer" ~> object ["inner" ~> ("success" :: T.Text)] , "inner" ~> ("error" :: T.Text) ] ) `shouldBe` return "success" main :: IO () main = hspec $ do parserSpec substituteSpec