packages feed

type-of-html-1.6.0.0: test/Value.hs

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

module Main where

import Html

import Data.Proxy
import Test.Hspec
import Test.QuickCheck
import Custom

main :: IO ()
main = hspec spec

spec :: Spec
spec = parallel $ do

  describe "render" $ do

    it "is id on strings without escaping" $ do

      property $ \x ->
        renderString (Raw x)
        ===
        x

    it "handles single elements" $ do

      property $ \x ->
        renderString (Div :> Raw x)
        ===
        "<div>" ++ x ++ "</div>"

    it "handles nested elements" $ do

      property $ \x ->
        renderString (Div :> Div :> Raw x)
        ===
        "<div><div>" ++ x ++ "</div></div>"

    it "handles parallel elements" $ do

      property $ \x y ->
        renderString (Div :> Raw x # Div :> Raw y)
        ===
        "<div>" ++ x ++ "</div><div>" ++ y ++ "</div>"

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

      renderString Area
        `shouldBe`
        "<area>"

      renderString Base
       `shouldBe`
        "<base>"

      renderString Br
       `shouldBe`
        "<br>"

      renderString Col
       `shouldBe`
        "<col>"

      renderString Embed
       `shouldBe`
        "<embed>"

      renderString Hr
       `shouldBe`
        "<hr>"

      renderString Iframe
       `shouldBe`
        "<iframe>"

      renderString Img
       `shouldBe`
        "<img>"

      renderString Link
       `shouldBe`
        "<link>"

      renderString Meta
       `shouldBe`
        "<meta>"

      renderString Param
       `shouldBe`
        "<param>"

      renderString Source
       `shouldBe`
        "<source>"

      renderString Track
       `shouldBe`
        "<track>"

      renderString Wbr
       `shouldBe`
        "<wbr>"

    it "handles trailing text" $ do

      property $ \x y ->
        renderString (Td :> (Raw x) # (Raw y))
        ===
        "<td>" ++ x ++ "</td>" ++ y

    it "handles a single compile time text" $ do

      renderString (Proxy :: Proxy "a")
       `shouldBe`
        "a"

    it "handles trailing compile time text" $ do

      renderString (Div :> "a" # (Proxy :: Proxy "b"))
       `shouldBe`
        "<div>a</div>b"

    it "handles nested compile time text" $ do

      renderString (Div :> (Proxy :: Proxy "a"))
       `shouldBe`
        "<div>a</div>"

    it "handles an empty list" $ do

      renderString (tail [Td :> "a"])
       `shouldBe`
        ""

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

      renderString [Td :> "a"]
       `shouldBe`
        "<td>a</td>"

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

      renderString [Div :> "a" # I :> "b"]
       `shouldBe`
        "<div>a</div><i>b</i>"

    it "handles nested lists" $ do

      renderString (Div :> [Div :> [Div :> (4 :: Int)]])
       `shouldBe`
        "<div><div><div>4</div></div></div>"

    it "handles utf8 correctly" $ do

      renderString (Div :> "a ä € 𝄞")
       `shouldBe`
        "<div>a ä € 𝄞</div>"

      renderString (Img :@ (IdA := "a ä € 𝄞"))
       `shouldBe`
        "<img id=\"a ä € 𝄞\">"

    it "handles Chars" $ do

      property $ \x ->
        renderString (Div :> [x :: Char])
        ===
        renderString (Div :> x)

    it "handles maybes" $ do

      renderString (Div :> (Just (Div :> "a")))
       `shouldBe`
        "<div><div>a</div></div>"

      renderString (Just (42 :: Int))
       `shouldBe`
        "42"

      renderString (Div :@ (Just (IdA := "a")) :> "b")
       `shouldBe`
        "<div id=\"a\">b</div>"

      renderString (Div :> (if True then Nothing else Just (Div :> "a")))
       `shouldBe`
        "<div></div>"

    it "handles eithers" $ do

      renderString (Div :> (if True then Left (Div :> "a") else Right "b"))
       `shouldBe`
        "<div><div>a</div></div>"

      renderString (Div :@ (if True then Right (IdA := "a") else Left (ClassA := "a")) :> "b")
       `shouldBe`
        "<div id=\"a\">b</div>"

    it "handles attributes" $ do

      renderString (Div :@ (IdA := "a") :> "b" # "c")
       `shouldBe`
        "<div id=\"a\">b</div>c"

      renderString (Div :@ (IdA := ()) :> "a")
       `shouldBe`
        "<div id>a</div>"

      renderString (Div :@ HiddenA :> "a")
       `shouldBe`
        "<div hidden>a</div>"

      renderString (Div :@ HiddenA :> ())
       `shouldBe`
        "<div hidden></div>"

      renderString (Div :@ HiddenA :> () # "a")
       `shouldBe`
        "<div hidden></div>a"

      renderString (Div :@ HiddenA :> () # Img)
       `shouldBe`
        "<div hidden></div><img>"

    it "handles custom attributes" $ do

      renderString (Div :@ (hxPost := "x") :> "y")
        `shouldBe`
        "<div hx-post=\"x\">y</div>"

    it "handles Ints" $ do

      property $ \x ->
        renderString (Div :> (x :: Int))
        ===
        renderString (Div :> (show x))

    it "handles complex compile time documents" $ do

      renderString (Div :> () # I :> ())
       `shouldBe`
        "<div></div><i></i>"

      renderString (Div :> () # "a")
       `shouldBe`
        "<div></div>a"

      renderString ("a" # I :> ())
       `shouldBe`
        "a<i></i>"

      renderString (Div :> () # I :> (Proxy @"a"))
       `shouldBe`
        "<div></div><i>a</i>"

      renderString (Div :> (Proxy @"a") # I :> ())
       `shouldBe`
        "<div>a</div><i></i>"

      renderString (Proxy @"1" # "2")
       `shouldBe`
        "12"

      renderString ("1" # Proxy @"2")
       `shouldBe`
        "12"

      renderString (Div :> () # Td :> (Proxy @"1" # "2" # Div :> () # I :@ (IdA := (Proxy @"3")) :> "4"))
       `shouldBe`
        "<div></div><td>12<div></div><i id=\"3\">4</i></td>"

    it "handles list of convertibles" $ do

      renderString (Div :> [1..5 :: Int])
       `shouldBe`
        "<div>12345</div>"

      renderString [1..5 :: Int]
       `shouldBe`
        "12345"

      renderString (Div :> ["abc"])
       `shouldBe`
        "<div>abc</div>"