monomer-1.0.0.0: test/unit/Monomer/Widgets/Util/FocusSpec.hs
{-|
Module : Monomer.Widgets.Util.FocusSpec
Copyright : (c) 2018 Francisco Vallarino
License : BSD-3-Clause (see the LICENSE file)
Maintainer : fjvallarino@gmail.com
Stability : experimental
Portability : non-portable
Unit tests for Focus handling.
-}
module Monomer.Widgets.Util.FocusSpec (spec) where
import Control.Lens ((&), (^.), (.~), ix)
import Data.Default
import Data.Text (Text)
import Test.Hspec
import qualified Data.Sequence as Seq
import Monomer.Core
import Monomer.Widgets.Singles.Label
import Monomer.Widgets.Util.Focus
import Monomer.TestUtil
import qualified Monomer.Lens as L
spec :: Spec
spec = describe "Focus" $ do
testParentPath
testNextTargetStep
testIsFocusCandidate
testParentPath :: Spec
testParentPath = describe "parentPath" $ do
it "should return root path" $ do
parentPath (pathNode []) `shouldBe` emptyPath
parentPath (pathNode [0]) `shouldBe` emptyPath
it "should return a single element path" $ do
parentPath (pathNode [0, 1]) `shouldBe` Seq.fromList [0]
parentPath (pathNode [1, 4]) `shouldBe` Seq.fromList [1]
it "should return a multiple element path" $ do
parentPath (pathNode [0, 1, 2]) `shouldBe` Seq.fromList [0, 1]
parentPath (pathNode [0, 1, 2, 3, 4]) `shouldBe` Seq.fromList [0, 1, 2, 3]
testNextTargetStep :: Spec
testNextTargetStep = describe "nextTargetStep" $ do
it "should return Nothing if next step is not valid" $ do
nextTargetStep (pathNode []) (path []) `shouldBe` Nothing
nextTargetStep (pathNode_ [] 5) (path []) `shouldBe` Nothing
nextTargetStep (pathNode_ [0] 5) (path [0]) `shouldBe` Nothing
nextTargetStep (pathNode_ [0] 5) (path [3]) `shouldBe` Nothing
it "should return a valid target step" $ do
nextTargetStep (pathNode_ [] 5) (path [2]) `shouldBe` Just 2
nextTargetStep (pathNode_ [0] 5) (path [0, 3]) `shouldBe` Just 3
testIsFocusCandidate :: Spec
testIsFocusCandidate = describe "isFocusCandidate" $ do
it "should return False if not backward candidate" $ do
isFocusCandidate (pathNode [0]) (path [0]) FocusBwd `shouldBe` False
isFocusCandidate (pathNode [0, 1]) (path [0, 0]) FocusBwd `shouldBe` False
it "should return True if backward candidate" $ do
isFocusCandidate (pathNode []) (path []) FocusBwd `shouldBe` True
isFocusCandidate (pathNode []) (path [0]) FocusBwd `shouldBe` True
isFocusCandidate (pathNode [0]) (path [1]) FocusBwd `shouldBe` True
isFocusCandidate (pathNode [0, 0]) (path [0, 1]) FocusBwd `shouldBe` True
isFocusCandidate (pathNode [0, 0]) (path [0, 0, 1]) FocusBwd `shouldBe` True
isFocusCandidate (pathNode [0, 1, 1]) (path [0, 2]) FocusBwd `shouldBe` True
it "should return False if not forward candidate" $ do
isFocusCandidate (pathNode []) (path []) FocusFwd `shouldBe` False
isFocusCandidate (pathNode []) (path [0]) FocusFwd `shouldBe` False
isFocusCandidate (pathNode [0]) (path [1]) FocusFwd `shouldBe` False
isFocusCandidate (pathNode [0, 0]) (path [0, 1]) FocusFwd `shouldBe` False
it "should return True if forward candidate" $ do
isFocusCandidate (pathNode [0]) (path []) FocusFwd `shouldBe` True
isFocusCandidate (pathNode [1]) (path [0]) FocusFwd `shouldBe` True
isFocusCandidate (pathNode [0, 1]) (path [0, 0]) FocusFwd `shouldBe` True
isFocusCandidate (pathNode [0, 2]) (path [0, 1, 1]) FocusFwd `shouldBe` True
path :: [PathStep] -> Path
path p = Seq.fromList p
pathNode :: [PathStep] -> WidgetNode s e
pathNode path = pathNode_ path 0
pathNode_ :: [PathStep] -> Int -> WidgetNode s e
pathNode_ path childCount = newNode where
mkChild idx = pathNode_ (path ++ [idx]) 0
newNode = label "Test"
& L.info . L.path .~ Seq.fromList path
& L.info . L.visible .~ True
& L.info . L.enabled .~ True
& L.info . L.focusable .~ True
& L.children .~ Seq.fromList (fmap mkChild [0..childCount - 1])