packages feed

type-of-html-0.2.1.1: test/Main.hs

{-# LANGUAGE TypeOperators    #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DataKinds        #-}

module Main where

import Html
import Test.Hspec

import Data.Proxy

import qualified Data.Text as T
import qualified Data.Text.Lazy as LT
import qualified Data.Text.Lazy.Builder as LT

main :: IO ()
main = hspec spec

spec :: Spec
spec = let {-# INLINE allT #-}
           allT a b c = b (render a, render a, render a , render a       )
                          (c       , T.pack c, LT.pack c, LT.fromString c)

       in parallel $ do

  describe "render" $ do

    it "is id on empty string" $ do

      allT ""
        shouldBe
        ""

    it "handles single elements" $ do

      allT (div_ "a")
        shouldBe
        "<div>a</div>"

    it "handles nested elements" $ do

      allT (div_ (div_ "a"))
        shouldBe
        "<div><div>a</div></div>"

    it "handles parallel elements" $ do

      allT (div_ "a" # div_ "b")
        shouldBe
        "<div>a</div><div>b</div>"

    it "doesn't use closing tags for empty elements" $ do

      allT area_
        shouldBe
        "<area>"

      allT base_
        shouldBe
        "<base>"

      allT br_
        shouldBe
        "<br>"

      allT col_
        shouldBe
        "<col>"

      allT embed_
        shouldBe
        "<embed>"

      allT hr_
        shouldBe
        "<hr>"

      allT iframe_
        shouldBe
        "<iframe>"

      allT img_
        shouldBe
        "<img>"

      allT link_
        shouldBe
        "<link>"

      allT menuitem_
        shouldBe
        "<menuitem>"

      allT meta_
        shouldBe
        "<meta>"

      allT param_
        shouldBe
        "<param>"

      allT source_
        shouldBe
        "<source>"

      allT track_
        shouldBe
        "<track>"

      allT wbr_
        shouldBe
        "<wbr>"

    it "avoids optional closing tags" $ do

      -- The closing tag at the end is because we can't know what
      -- element will follow.

      allT (td_ () # td_ ())
        shouldBe
        "<td><td></td>"

      allT (tr_ $ td_ ())
        shouldBe
        "<tr><td></tr>"

      allT (table_ . tr_ $ td_ ())
        shouldBe
        "<table><tr><td></table>"

    it "handles trailing text" $ do

      allT (td_ "a" # "b")
        shouldBe
        "<td>a</td>b"

    it "handles a single compile time text" $ do

      allT (Proxy :: Proxy "a")
        shouldBe
        "a"

    it "handles trailing compile time text" $ do

      allT (div_ "a" # (Proxy :: Proxy "b"))
        shouldBe
        "<div>a</div>b"

    it "handles nested compile time text" $ do

      allT (div_ (Proxy :: Proxy "a"))
        shouldBe
        "<div>a</div>"

    it "handles an empty list" $ do

      allT (tail [td_ "a"])
        shouldBe
        ""

    it "handles a list with a single element" $ do

      allT [td_ "a"]
        shouldBe
        "<td>a</td>"

    it "handles tags in a list with parallel elements" $ do

      allT [td_ "a" # td_ "b"]
        shouldBe
        "<td>a<td>b</td>"

    it "handles tags in a list with parallel elements and a following tag" $ do

      pendingWith "This is a not yet implemented optimization"

      allT ([td_ "a" # td_ "b"] # td_ "c")
        shouldBe
        "<td>a<td>b<td>c</td>"

      allT ([td_ "a" # td_ "b"] # div_ "c")
        shouldBe
        "<td>a<td>b</td><div>c</div>"

      allT ([div_ "a" # td_ "b"] # td_ "c")
        shouldBe
        "<div>a</div><td>b</td><td>c</td>"

    it "handles tags in a list when the list is the last child" $ do

      allT (tr_ [td_ "a" # td_ "b"])
        shouldBe
        "<tr><td>a<td>b</tr>"

    it "handles nested lists" $ do

      allT (table_ [tr_ [td_ (4 :: Int)]])
        shouldBe
        "<table><tr><td>4</table>"

    it "handles tags before a list" $ do

      pendingWith "This is a not yet implemented optimization"

      allT (td_ "a" # [td_ "b"] # table_ ())
        shouldBe
        "<td>a</td><td>b</td><table></table>"

      allT (td_ "a" # [td_ "b"] # td_ "c")
        shouldBe
        "<td>a<td>b<td>c</td>"

    it "computes its result lazily" $ do

      take 5 (render (div_ (errorWithoutStackTrace "not lazy" :: String)))
        `shouldBe`
        "<div>"

      take 5 (render (errorWithoutStackTrace "not lazy" :: 'Img > ()))
        `shouldBe`
        "<img>"

      take 5 (render (errorWithoutStackTrace "not lazy" :: 'Div > String))
        `shouldBe`
        "<div>"

      take 12 (render (div_ "a" # (errorWithoutStackTrace "not lazy" :: String)))
        `shouldBe`
        "<div>a</div>"

      take 17 (render (div_ "a" # [img_ # (errorWithoutStackTrace "not lazy" :: String)]))
        `shouldBe`
        "<div>a</div><img>"