{-| Module : Monomer.Widgets.Containers.StackSpec 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 Stack widget. -} {-# LANGUAGE FlexibleContexts #-} module Monomer.Widgets.Containers.StackSpec (spec) where import Control.Lens ((&), (^.), (.~)) import Data.Text (Text) import Test.Hspec import qualified Data.Sequence as Seq import Monomer.Core import Monomer.Core.Combinators import Monomer.Event import Monomer.TestUtil import Monomer.Widgets.Containers.Stack import Monomer.Widgets.Singles.Label import Monomer.Widgets.Singles.Spacer import qualified Monomer.Lens as L -- Event handling (ignoreEmptyClick) is tested in zstack spec :: Spec spec = describe "Stack" $ do getSizeReq resize getSizeReq :: Spec getSizeReq = describe "getSizeReq" $ do getSizeReqEmpty getSizeReqItems getSizeReqUpdater getSizeReqChildSpacing getSizeReqEmpty :: Spec getSizeReqEmpty = describe "empty" $ do it "should return Fixed width = 0" $ sizeReqW `shouldBe` fixedSize 0 it "should return Fixed height = 0" $ sizeReqH `shouldBe` fixedSize 0 where wenv = mockWenv () vstackNode = vstack [] (sizeReqW, sizeReqH) = nodeGetSizeReq wenv vstackNode getSizeReqItems :: Spec getSizeReqItems = describe "several items" $ do it "should return width = Fixed 80" $ sizeReqW `shouldBe` fixedSize 80 it "should return height = Fixed 60" $ sizeReqH `shouldBe` fixedSize 60 where wenv = mockWenv () vstackNode = vstack [ label "Hello", label "how", label "are you?" ] (sizeReqW, sizeReqH) = nodeGetSizeReq wenv vstackNode getSizeReqUpdater :: Spec getSizeReqUpdater = describe "getSizeReqUpdater" $ do it "should return width = Min 50 2" $ sizeReqW1 `shouldBe` minSize 50 2 it "should return height = Max 20" $ sizeReqH1 `shouldBe` maxSize 20 3 it "should return width = Min 50 10" $ sizeReqW2 `shouldBe` minSize 50 10 it "should return height = Max 20 15" $ sizeReqH2 `shouldBe` maxSize 20 15 where wenv = mockWenv () updater (rw, rh) = (minSize (rw ^. L.fixed) 2, maxSize (rh ^. L.fixed) 3) vstackNode1 = vstack_ [sizeReqUpdater updater] [label "Label"] vstackNode2 = vstack_ [sizeReqUpdater (fixedToMinW 10), sizeReqUpdater (fixedToMaxH 15)] [label "Label"] (sizeReqW1, sizeReqH1) = nodeGetSizeReq wenv vstackNode1 (sizeReqW2, sizeReqH2) = nodeGetSizeReq wenv vstackNode2 getSizeReqChildSpacing :: Spec getSizeReqChildSpacing = describe "with childSpacing" $ do it "should not add spacing when empty" $ testStackSizeReq [] `shouldBe` fixedSize 0 it "should not add spacing when singleton" $ testStackSizeReq [spacer3] `shouldBe` fixedSize 3 it "should add spacing between children" $ testStackSizeReq [spacer3, spacer3] `shouldBe` fixedSize 8 it "should not add spacing between invisible children" $ do testStackSizeReq [spacer3, spacer3 `nodeVisible` False] `shouldBe` fixedSize 3 where wenv = mockWenv () spacer3 = spacer_ [width 3, resizeFactor 0] testStackSizeReq children = sizeReqH where (_sizeReqW, sizeReqH) = nodeGetSizeReq wenv vstackNode vstackNode = vstack_ [childSpacing_ 2] children resize :: Spec resize = describe "resize" $ do resizeEmpty resizeFlexibleH resizeFlexibleV resizeStrictFlexH resizeStrictFlexV resizeMixedH resizeMixedV resizeAllV resizeNoSpaceV resizeSpacerFlexH resizeSpacerFixedH resizeChildSpacing resizeEmpty :: Spec resizeEmpty = describe "empty" $ do it "should have the provided viewport size" $ viewport `shouldBe` vp it "should not have children" $ children `shouldSatisfy` Seq.null where wenv = mockWenv () -- Main axis is adjusted to content vp = Rect 0 0 640 0 vstackNode = vstack [] newNode = nodeInit wenv vstackNode viewport = newNode ^. L.info . L.viewport children = newNode ^. L.children resizeFlexibleH :: Spec resizeFlexibleH = describe "flexible items, horizontal" $ do it "should have the provided viewport size" $ viewport `shouldBe` vp it "should assign size proportional to requested size to each children" $ childrenVp `shouldBe` Seq.fromList [cvp1, cvp2, cvp3] where wenv = mockWenv () & L.windowSize .~ Size 480 640 vp = Rect 0 0 480 640 cvp1 = Rect 0 0 112 640 cvp2 = Rect 112 0 256 640 cvp3 = Rect 368 0 112 640 hstackNode = hstack [ label "Label 1" `styleBasic` [expandWidth 70], label "Label 2" `styleBasic` [expandWidth 160], label "Label 3" `styleBasic` [expandWidth 70] ] newNode = nodeInit wenv hstackNode viewport = newNode ^. L.info . L.viewport childrenVp = roundRectUnits . _wniViewport . _wnInfo <$> newNode ^. L.children resizeFlexibleV :: Spec resizeFlexibleV = describe "flexible items, vertical" $ do it "should have the provided viewport size" $ viewport `shouldBe` vp it "should assign size proportional to requested size to each children" $ childrenVp `shouldBe` Seq.fromList [cvp1, cvp2, cvp3] where wenv = mockWenv () vp = Rect 0 0 640 480 cvp1 = Rect 0 0 640 160 cvp2 = Rect 0 160 640 160 cvp3 = Rect 0 320 640 160 vstackNode = vstack [ label "Label 1" `styleBasic` [flexHeight 20], label "Label Number Two" `styleBasic` [flexHeight 20], label "Label 3" `styleBasic` [flexHeight 20] ] newNode = nodeInit wenv vstackNode viewport = newNode ^. L.info . L.viewport childrenVp = (^. L.info . L.viewport) <$> newNode ^. L.children resizeStrictFlexH :: Spec resizeStrictFlexH = describe "strict/flexible items, horizontal" $ do it "should have the provided viewport size" $ viewport `shouldBe` vp it "should assign requested size to the main labels and the rest to grid" $ childrenVp `shouldBe` Seq.fromList [cvp1, cvp2, cvp3] where wenv = mockWenv () vp = Rect 0 0 640 480 cvp1 = Rect 0 0 100 480 cvp2 = Rect 100 0 100 480 cvp3 = Rect 200 0 440 480 hstackNode = hstack [ label "Label 1" `styleBasic` [width 100], label "Label 2" `styleBasic` [width 100], label "Label 3" `styleBasic` [expandWidth 70] ] newNode = nodeInit wenv hstackNode viewport = newNode ^. L.info . L.viewport childrenVp = (^. L.info . L.viewport) <$> newNode ^. L.children resizeStrictFlexV :: Spec resizeStrictFlexV = describe "strict/flexible items, vertical" $ do it "should have the provided viewport size" $ viewport `shouldBe` vp it "should assign requested size to the main labels and the rest to grid" $ childrenVp `shouldBe` Seq.fromList [cvp1, cvp2, cvp3] where wenv = mockWenv () vp = Rect 0 0 640 480 cvp1 = Rect 0 0 640 100 cvp2 = Rect 0 100 640 20 cvp3 = Rect 0 120 640 360 vstackNode = vstack [ label "Label 1" `styleBasic` [height 100], label "Label 2", label "Label 3" `styleBasic` [flexHeight 100] ] newNode = nodeInit wenv vstackNode viewport = newNode ^. L.info . L.viewport childrenVp = (^. L.info . L.viewport) <$> newNode ^. L.children resizeMixedH :: Spec resizeMixedH = describe "mixed items, horizontal" $ do it "should have the provided viewport size" $ viewport `shouldBe` vp it "should assign size proportional to requested size to each children" $ childrenVp `shouldBe` Seq.fromList [cvp1, cvp2] where wenv = mockWenv () vp = Rect 0 0 640 20 cvp1 = Rect 0 0 196 20 cvp2 = Rect 196 0 444 20 hstackNode = vstack [ hstack [ label "Label 1" `styleBasic` [expandWidth 110], label "Label 2" `styleBasic` [expandWidth 250] ] ] newNode = nodeInit wenv hstackNode viewport = newNode ^. L.info . L.viewport firstChild = Seq.index (newNode ^. L.children) 0 childrenVp = roundRectUnits . _wniViewport . _wnInfo <$> firstChild ^. L.children resizeMixedV :: Spec resizeMixedV = describe "mixed items, vertical" $ do it "should have the provided viewport size" $ viewport `shouldBe` vp it "should assign size proportional to requested size to each children" $ childrenVp `shouldBe` Seq.fromList [cvp1, cvp2, cvp3] where wenv = mockWenv () vp = Rect 0 0 70 480 cvp1 = Rect 0 0 70 20 cvp2 = Rect 0 20 70 426 cvp3 = Rect 0 446 70 34 vstackNode = hstack [ vstack [ label "Label 1", label "Label 2" `styleBasic` [minHeight 250], label "Label 3" `styleBasic` [flexHeight 20] ] ] newNode = nodeInit wenv vstackNode viewport = newNode ^. L.info . L.viewport firstChild = Seq.index (newNode ^. L.children) 0 childrenVp = roundRectUnits . _wniViewport . _wnInfo <$> firstChild ^. L.children resizeAllV :: Spec resizeAllV = describe "all kinds of sizeReq, vertical" $ do it "should have the provided viewport size" $ viewport `shouldBe` vp it "should assign size proportional to requested size to each children" $ childrenVp `shouldBe` Seq.fromList [cvp1, cvp2, cvp3, cvp4, cvp5] where wenv = mockWenv () vp = Rect 0 0 640 480 cvp1 = Rect 0 0 640 50 cvp2 = Rect 0 50 640 115 cvp3 = Rect 0 165 640 135 cvp4 = Rect 0 300 640 80 cvp5 = Rect 0 380 640 100 vstackNode = vstack [ label "Label 1" `styleBasic` [width 50, height 50], label "Label 2" `styleBasic` [flexWidth 60, flexHeight 60], label "Label 3" `styleBasic` [minWidth 70, minHeight 70], label "Label 4" `styleBasic` [maxWidth 80, maxHeight 80], label "Label 5" `styleBasic` [rangeWidth 90 100, rangeHeight 90 100] ] newNode = nodeInit wenv vstackNode viewport = newNode ^. L.info . L.viewport childrenVp = roundRectUnits . _wniViewport . _wnInfo <$> newNode ^. L.children resizeNoSpaceV :: Spec resizeNoSpaceV = describe "vertical, without enough space" $ do it "should have a larger viewport size (parent should fix it)" $ do viewport `shouldBe` vp viewport `shouldBe` vp it "should assign size proportional to requested size to each children" $ childrenVp `shouldBe` Seq.fromList [cvp1, cvp2, cvp3, cvp4, cvp5] where wenv = mockWenv () vp = Rect 0 0 640 800 cvp1 = Rect 0 0 640 200 cvp2 = Rect 0 200 640 200 cvp3 = Rect 0 400 640 0 cvp4 = Rect 0 400 640 200 cvp5 = Rect 0 600 640 200 vstackNode = vstack [ label "Label 1" `styleBasic` [height 200], label "Label 2" `styleBasic` [height 200], label "Label 3" `styleBasic` [flexHeight 200], label "Label 4" `styleBasic` [height 200], label "Label 5" `styleBasic` [height 200] ] newNode = nodeInit wenv vstackNode viewport = newNode ^. L.info . L.viewport childrenVp = roundRectUnits . _wniViewport . _wnInfo <$> newNode ^. L.children resizeSpacerFlexH :: Spec resizeSpacerFlexH = describe "label flex and spacer, horizontal" $ do it "should have the provided viewport size" $ roundRectUnits viewport `shouldBe` vp it "should assign size proportional to requested size to each children" $ childrenVp `shouldBe` Seq.fromList [cvp1, cvp2, cvp3] where wenv = mockWenv () vp = Rect 0 0 640 480 cvp1 = Rect 0 0 211 480 cvp2 = Rect 211 0 8 480 cvp3 = Rect 219 0 421 480 hstackNode = hstack [ label "Label" `styleBasic` [flexWidth 100], filler, label "Label" `styleBasic` [flexWidth 200] ] newNode = nodeInit wenv hstackNode viewport = newNode ^. L.info . L.viewport childrenVp = roundRectUnits . _wniViewport . _wnInfo <$> newNode ^. L.children resizeSpacerFixedH :: Spec resizeSpacerFixedH = describe "label fixed and spacer, horizontal" $ do it "should have the provided viewport size" $ viewport `shouldBe` vp it "should assign size proportional to requested size to each children" $ childrenVp `shouldBe` Seq.fromList [cvp1, cvp2, cvp3] where wenv = mockWenv () vp = Rect 0 0 640 480 cvp1 = Rect 0 0 100 480 cvp2 = Rect 100 0 340 480 cvp3 = Rect 440 0 200 480 hstackNode = hstack [ label "Label" `styleBasic` [width 100], filler, label "Label" `styleBasic` [width 200] ] newNode = nodeInit wenv hstackNode viewport = newNode ^. L.info . L.viewport childrenVp = roundRectUnits . _wniViewport . _wnInfo <$> newNode ^. L.children resizeChildSpacing :: Spec resizeChildSpacing = describe "with childSpacing" $ do it "should add spacing between children" $ testStackChildLocations [spacer3, spacer3] `shouldBe` Seq.fromList [Rect 0 0 640 3, Rect 0 5 640 3] it "should not add spacing between invisible children" $ testStackChildLocations [spacer3, spacer3 `nodeVisible` False, spacer3] `shouldBe` Seq.fromList [Rect 0 0 640 3, Rect 0 0 0 0, Rect 0 5 640 3] where wenv = mockWenv () spacer3 = spacer_ [width 3, resizeFactor 0] testStackChildLocations children = childLocations where vstackNode = vstack_ [childSpacing_ 2] children newNode = nodeInit wenv vstackNode childLocations = roundRectUnits . _wniViewport . _wnInfo <$> newNode ^. L.children