packages feed

atomic-css-0.1.0: test/Test/RuleSpec.hs

module Test.RuleSpec where

import Skeletest
import Web.Atomic.CSS.Select (addAncestor, addMedia, addPseudo)
import Web.Atomic.Types
import Web.Atomic.Types.Rule as Rule


spec :: Spec
spec = do
  describe "Unique Rules" $ do
    it "should only set same class once" $ do
      uniqueRules ["asdf", "asdf"] `shouldBe` ["asdf"]

      fmap (.className) [bold, bold] `shouldBe` ["bold", "bold"]
      fmap (.className) (uniqueRules [bold, bold]) `shouldBe` ["bold"]

    it "should set different properties" $ do
      let rs = [bold, fs12]
      length (uniqueRules rs) `shouldBe` 2

    it "should unset same property" $ do
      let rs = [fs24, bold, fs12]
      fmap (.className) (uniqueRules rs) `shouldBe` ["fs-24", "bold"]

    it "should treat hover states as unique" $ do
      let hoverBold = addPseudo "hover" bold
          hoverNormal = addPseudo "hover" normal
          hoverActiveNormal = addPseudo "hover" $ addPseudo "active" normal

      length (uniqueRules [hoverBold, normal]) `shouldBe` 2
      length (uniqueRules [hoverBold, hoverNormal]) `shouldBe` 1
      length (uniqueRules [hoverActiveNormal, hoverBold]) `shouldBe` 2

    it "should ignore custom selectors" $ do
      length (uniqueRules [bold, custom]) `shouldBe` 2
      length (uniqueRules [custom, bold]) `shouldBe` 2

  describe "className" $ do
    it "basic" $ do
      ruleClassName (Rule.fromClass "hello") `shouldBe` "hello"

    it "includes pseudo" $ do
      ruleClassName (addPseudo "active" $ addPseudo "hover" "hello") `shouldBe` "active:hover:hello"

    it "includes media" $ do
      ruleClassName (addMedia (MinWidth 100) "hello") `shouldBe` "mmnw100:hello"

    it "includes pseudo + media" $ do
      ruleClassName (addMedia (MinWidth 100) $ addPseudo "hover" "hello") `shouldBe` "mmnw100:hover:hello"

  describe "selector" $ do
    it "creates selector from class name" $ do
      ruleSelector (Rule.fromClass "p-10") `shouldBe` ".p-10"

    it "adds pseudo" $ do
      ruleSelector (addPseudo "hover" "p-10") `shouldBe` ".hover\\:p-10:hover"

    it "adds media" $ do
      ruleSelector (addMedia (MinWidth 100) "hello") `shouldBe` ".mmnw100\\:hello"

    it "adds pseudo + media " $ do
      ruleSelector (addMedia (MinWidth 100) $ addPseudo "hover" "hello") `shouldBe` ".mmnw100\\:hover\\:hello:hover"

  describe "ancestor" $ do
    it "prepends selector" $ do
      let r = addAncestor "htmx-request" "hello"
      let cn = ruleClassName r
      cn `shouldBe` "htmx-request:hello"
      ruleSelector r `shouldBe` ".htmx-request " <> selector cn

    it "ancestor + pseudo" $ do
      let r = addAncestor "htmx-request" $ addPseudo "hover" "hello"
      let cn = ruleClassName r
      cn `shouldBe` "htmx-request:hover:hello"
      ruleSelector r `shouldBe` ".htmx-request " <> selector cn <> ":hover"

    -- what dopes this mean? Are they the same?
    -- hover (ancestor "htmx-request" "bold")
    -- ancestor "htmx-request" (hover "bold")
    -- certain things should be outermost....
    it "pseudo + ancestor" $ do
      let r = addPseudo "hover" $ addAncestor "htmx-request" "hello"
      let cn = ruleClassName r
      cn `shouldBe` "hover:htmx-request:hello"
      ruleSelector r `shouldBe` ".htmx-request " <> selector cn <> ":hover"

    it "ignores when custom selector" $ do
      let r = addAncestor "htmx-request" $ addPseudo "hover" $ (rule "hello" []){selector = CustomRule ".woot"}
      let cn = ruleClassName r
      cn `shouldBe` "hello"
      ruleSelector r `shouldBe` ".woot"
 where
  -- it "doesn't change with custom selectors" $ do
  --   ruleSelector (Rule "hello" (Just ".hello") [Hover] [MinWidth 100] []) `shouldBe` ".hello"

  fs12 = Rule "fs-12" mempty mempty ["font-size" :. "12px"]
  fs24 = Rule "fs-24" mempty mempty ["font-size" :. "24px"]
  bold = Rule "bold" mempty mempty ["font-weight" :. "bold"]
  normal = Rule "normal" mempty mempty ["font-weight" :. "normal"]
  custom = Rule "custom" (CustomRule ".custom > *") mempty ["font-weight" :. "bold"]