{-# LANGUAGE OverloadedStrings #-} module Snap.Snaplet.Heist.Tests where ------------------------------------------------------------------------------ import Control.Applicative import Control.Monad (join) import Control.Monad.IO.Class (liftIO) import qualified Data.ByteString.Char8 as BSC import Data.List (isInfixOf) import qualified Data.Set as Set import qualified Data.Map as Map import qualified Data.Text as T import Test.HUnit (Assertion, assertBool, assertFailure) import qualified Test.Framework as F import Test.Framework.Providers.HUnit (testCase) ------------------------------------------------------------------------------ import Data.Map.Syntax ((##)) import qualified Heist as H import qualified Heist.Interpreted as I import Snap.Snaplet (with) import qualified Snap.Test as ST import Snap.TestCommon (expectException) import Snap.Snaplet.Test (evalHandler, runHandler) import qualified Snap.Snaplet.Heist as HS import qualified Snap.Snaplet.Heist.Compiled as C import qualified Snap.Snaplet.Heist.Interpreted as I import Snap.Snaplet.Test.Common.App (appInit, appInit', heist) import qualified Text.XmlHtml as XML heistTests :: F.Test heistTests = F.testGroup "Snap.Snaplet.Heist" [testCase "Load templates" addTemplatesOK ,testCase "Get Heist state" assertHasTemplates ,testCase "Handler with heist state" accessibleHeistState ,testCase "gRender a template" gSimpleRender -- ,testCase "gRender another template" gSimpleRenderAnother -- TODO investigate ,testCase "cRender a template" (simpleRender False) ,testCase "Render a template" (simpleRender True) ,testCase "gRenderAs a small template" gSimpleRenderAs ,testCase "cRenderAs a template" (simpleRenderAs False) ,testCase "renderAs a template" (simpleRenderAs True) ,testCase "gServe existing template" gSimpleHeistServeOK ,testCase "cServe templates" (simpleHeistServeOK False) ,testCase "serve templates" (simpleHeistServeOK True) ,testCase "gHeistServe underscore template" gSimpleHeistServeUnd ,testCase "gHeistServe missing template" gSimpleHeistServeMissing ,testCase "gHeistServeSingle template" gSimpleHeistServeSingle ,testCase "cHeistServeSingle template" (simpleHeistServeSingle False) ,testCase "heistServeSingle template" (simpleHeistServeSingle True) ,testCase "gHeistServeSingle underscored template" gSimpleHeistServeSingleUnd ,testCase "gHeistServeSingle missing template" gSimpleHeistServeSingleMissing ,testCase "Choose compiled mode" chooseCompiled ,testCase "Choose interpreted mode" chooseInterpreted ,testCase "Render with splices" fooRenderWith ,testCase "Recognize withSplices" seeLocalSplices ,testCase "Recognize heistLocal" seeLocalState ,testCase "cRender with compiled module" compiledModuleRender ,testCase "cRenderAs compiled module" compiledModuleRenderAs ,testCase "cHeistServe a template" compiledModuleServe ,testCase "cHeistServeSingle a template" compiledModuleServeOne ] ------------------------------------------------------------------------------ addTemplatesOK :: Assertion addTemplatesOK = do let hdl = with heist $ I.render "foopage" res <- runHandler Nothing (ST.get "" Map.empty) hdl appInit either (assertFailure . show) (ST.assertSuccess) res ------------------------------------------------------------------------------ assertHasTemplates :: Assertion assertHasTemplates = do let hdl = with heist $ do s <- HS.getHeistState t <- return $ H.templateNames s sp <- return $ H.spliceNames s sc <- return $ H.compiledSpliceNames s liftIO $ putStrLn $ "Templates " ++ unwords (map show t) liftIO $ putStrLn $ "Splices: " ++ unwords (map show sp) liftIO $ putStrLn $ "Compiled splices: " ++ unwords (map show sc) return $ Set.fromList (map head t) res <- evalHandler Nothing (ST.get "" Map.empty) hdl appInit assertBool "templateNames include foopage, barpage, bazpage" $ (Right (Set.fromList [])) == (Set.difference (Set.fromList ["foopage","barpage","bazpage"]) <$> res) ------------------------------------------------------------------------------ accessibleHeistState :: Assertion accessibleHeistState = do let hdl = with heist . HS.withHeistState $ I.lookupSplice "thisSpliceDoesntExist" res <- runHandler Nothing (ST.get "" Map.empty) hdl appInit either (assertFailure . show) (ST.assertSuccess) res ------------------------------------------------------------------------------ gSimpleRender :: Assertion gSimpleRender = do let hdl = with heist $ HS.gRender "foopage" res <- runHandler Nothing (ST.get "" Map.empty) hdl appInit either (assertFailure . show) ST.assertSuccess res gSimpleRenderAnother :: Assertion gSimpleRenderAnother = do let hdl = with heist $ HS.gRender "bazpage" res <- runHandler Nothing (ST.get "" Map.empty) hdl appInit either (assertFailure . show) ST.assertSuccess res ------------------------------------------------------------------------------ simpleRender :: Bool -> Assertion simpleRender interp = do let hdl = with heist $ HS.chooseMode (HS.cRender "foopage") (HS.render "foopage") res <- runHandler Nothing (ST.get "" Map.empty) hdl (appInit' interp False) either (assertFailure . show) ST.assertSuccess res ------------------------------------------------------------------------------ gSimpleRenderAs :: Assertion gSimpleRenderAs = do let hdl = with heist $ HS.gRenderAs "audio/ogg" "foopage" defReq = ST.get "" Map.empty rs = either (return . T.unpack) (\r -> (BSC.unpack <$> ST.responseToString r)) resStr <- join $ rs <$> runHandler Nothing defReq hdl appInit assertBool "gRenderAs should set content to audio/ogg" $ ("audio/ogg" `isInfixOf` resStr) ------------------------------------------------------------------------------ simpleRenderAs :: Bool -> Assertion simpleRenderAs interp = do let hdl = with heist $ HS.chooseMode (HS.cRenderAs "audio/ogg" "foopage") (HS.renderAs "audio/ogg" "foopage") defReq = ST.get "" Map.empty rs = either (return . T.unpack) (\r -> (BSC.unpack <$> ST.responseToString r)) resStr <- join $ rs <$> runHandler Nothing defReq hdl (appInit' interp False) assertBool "renderAs should set content to audio/ogg" $ ("audio/ogg" `isInfixOf` resStr) ------------------------------------------------------------------------------ gSimpleHeistServeOK :: Assertion gSimpleHeistServeOK = do let hdl = with heist HS.gHeistServe res <- runHandler Nothing (ST.get "index" Map.empty) hdl appInit either (assertFailure . show) ST.assertSuccess res ------------------------------------------------------------------------------ simpleHeistServeOK :: Bool -> Assertion simpleHeistServeOK interp = do let hdl = with heist $ HS.chooseMode HS.cHeistServe HS.heistServe res <- runHandler Nothing (ST.get "foopage" Map.empty) hdl (appInit' interp False) either (assertFailure . show) ST.assertSuccess res ------------------------------------------------------------------------------ gSimpleHeistServeUnd :: Assertion gSimpleHeistServeUnd = do let hdl = with heist HS.gHeistServe res <- runHandler Nothing (ST.get "_foopage" Map.empty) hdl appInit either (assertFailure . show) ST.assert404 res ------------------------------------------------------------------------------ gSimpleHeistServeMissing :: Assertion gSimpleHeistServeMissing = do let hdl = with heist HS.gHeistServe res <- runHandler Nothing (ST.get "nonexisting" Map.empty) hdl appInit either (assertFailure . show) ST.assert404 res simpleHeistServeSingle :: Bool -> Assertion simpleHeistServeSingle interp = do let hdl = with heist $ HS.chooseMode (HS.cHeistServeSingle "foopage") (HS.heistServeSingle "foopage") res <- runHandler Nothing (ST.get "foopage" Map.empty) hdl (appInit' interp False) either (assertFailure . show) ST.assertSuccess res ------------------------------------------------------------------------------ -- Serves foopage, despite request for nonexistent gSimpleHeistServeSingle :: Assertion gSimpleHeistServeSingle = do let hdl = with heist $ HS.gHeistServeSingle "foopage" res <- runHandler Nothing (ST.get "nonexistent" Map.empty) hdl appInit either (assertFailure . show) ST.assertSuccess res ------------------------------------------------------------------------------ -- serveSingle does not filter out underscored templates gSimpleHeistServeSingleUnd :: Assertion gSimpleHeistServeSingleUnd = do let hdl = with heist $ I.heistServeSingle "_foopage" res <- runHandler Nothing (ST.get "_foopage" Map.empty) hdl appInit either (assertFailure . show) ST.assertSuccess res ------------------------------------------------------------------------------ gSimpleHeistServeSingleMissing :: Assertion gSimpleHeistServeSingleMissing = do let hdl = with heist $ HS.gHeistServeSingle "nonexistent" expectException "gHeistServeSingle failed to throw when serving nonexistent template" (runHandler Nothing (ST.get "nonexistent" Map.empty) hdl appInit) ------------------------------------------------------------------------------ chooseCompiled :: Assertion chooseCompiled = do let hdl = with heist $ HS.chooseMode (liftIO $ return ()) (liftIO $ assertFailure "Should have chosen compiled mode") res <- evalHandler Nothing (ST.get "" Map.empty) hdl appInit either (assertFailure . show) return res ------------------------------------------------------------------------------ chooseInterpreted :: Assertion chooseInterpreted = do let hdl = with heist $ HS.chooseMode (liftIO $ assertFailure "Should have chosen intpreted mode") (liftIO $ return ()) res <- evalHandler Nothing (ST.get "" Map.empty) hdl (appInit' True False) either (assertFailure . show) return res ------------------------------------------------------------------------------ fooRenderWith :: Assertion fooRenderWith = do let mySplices = ("aSplice" ## I.textSplice "Content") hdl = with heist $ HS.renderWithSplices "foopage" mySplices res <- runHandler Nothing (ST.get "" Map.empty) hdl appInit rStr <- either (const $ return "") ST.responseToString res assertBool "Splice was not spliced in" (BSC.isInfixOf "Content" (rStr :: BSC.ByteString)) ------------------------------------------------------------------------------ seeLocalSplices :: Assertion seeLocalSplices = do let mySplices = do "aSplice" ## I.textSplice "Content" "bSplice" ## I.textSplice "BContent" hdl = with heist $ HS.withSplices mySplices (HS.withHeistState H.spliceNames) res <- evalHandler Nothing (ST.get "" Map.empty) hdl appInit either (assertFailure . show) (\r -> assertBool "Local splices not stored" $ all (`elem` r) ["aSplice","bSplice"]) res ------------------------------------------------------------------------------ seeLocalState :: Assertion seeLocalState = do let hdl = with heist $ HS.heistLocal (I.addTemplate "tinyTemplate" [XML.TextNode "aNode"] Nothing) (HS.withHeistState H.templateNames) res <- evalHandler Nothing (ST.get "" Map.empty) hdl appInit either (assertFailure . show) (\r -> assertBool "Local state template not found" $ "tinyTemplate" `elem` (map head r)) res ------------------------------------------------------------------------------ compiledModuleRender :: Assertion compiledModuleRender = do let hdl = with heist $ C.render "foopage" res <- runHandler Nothing (ST.get "" Map.empty) hdl appInit either (assertFailure . show) ST.assertSuccess res ------------------------------------------------------------------------------ compiledModuleRenderAs :: Assertion compiledModuleRenderAs = do let hdl = with heist $ C.renderAs "audio/ogg" "foopage" res <- runHandler Nothing (ST.get "" Map.empty) hdl appInit rStr <- either (\_ -> return "") (ST.responseToString) res assertBool "Compiled Heist snaplet response should contain \"audoi/ogg\"" (BSC.isInfixOf "audio/ogg" rStr) ------------------------------------------------------------------------------ compiledModuleServe :: Assertion compiledModuleServe = do let hdl = with heist $ C.heistServe res <- runHandler Nothing (ST.get "foopage" Map.empty) hdl appInit either (assertFailure . show) ST.assertSuccess res ------------------------------------------------------------------------------ compiledModuleServeOne :: Assertion compiledModuleServeOne = do let hdl = with heist $ C.heistServeSingle "foopage" res <- runHandler Nothing (ST.get "foopage" Map.empty) hdl appInit either (assertFailure . show) ST.assertSuccess res