packages feed

monomer-1.3.0.0: test/unit/Monomer/Widgets/Containers/GridSpec.hs

{-|
Module      : Monomer.Widgets.Containers.GridSpec
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 Grid widget.
-}
{-# LANGUAGE FlexibleContexts #-}

module Monomer.Widgets.Containers.GridSpec (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.Grid
import Monomer.Widgets.Singles.Label
import Monomer.Widgets.Singles.Spacer

import qualified Monomer.Lens as L

spec :: Spec
spec = describe "Grid" $ do
  getSizeReq
  resize

getSizeReq :: Spec
getSizeReq = describe "getSizeReq" $ do
  getSizeReqEmpty
  getSizeReqItemsH
  getSizeReqItemsV
  getSizeReqMixedH
  getSizeReqMixedV
  getSizeReqUpdater
  getSizeReqChildSpacing

getSizeReqEmpty :: Spec
getSizeReqEmpty = describe "empty" $ do
  it "should return width = Fixed 0" $
    sizeReqW `shouldBe` fixedSize 0

  it "should return height = Fixed 0" $
    sizeReqH `shouldBe` fixedSize 0

  where
    wenv = mockWenv ()
    gridNode = vgrid []
    (sizeReqW, sizeReqH) = nodeGetSizeReq wenv gridNode

getSizeReqItemsH :: Spec
getSizeReqItemsH = describe "several items, horizontal" $ do
  it "should return width = Fixed 240 (largest width * 3)" $
    sizeReqW `shouldBe` fixedSize 240

  it "should return height = Fixed 20" $
    sizeReqH `shouldBe` fixedSize 20

  where
    wenv = mockWenv ()
    gridNode = hgrid [
        label "Hello",
        label "how",
        label "are you?"
      ]
    (sizeReqW, sizeReqH) = nodeGetSizeReq wenv gridNode

getSizeReqItemsV :: Spec
getSizeReqItemsV = describe "several items, vertical, one not visible" $ do
  it "should return width = Fixed 80" $
    sizeReqW `shouldBe` fixedSize 80

  it "should return height = Fixed 60" $
    sizeReqH `shouldBe` fixedSize 60

  where
    wenv = mockWenv ()
    gridNode = vgrid [
        label "Hello",
        label "how",
        label "" `nodeVisible` False,
        label "are you?"
      ]
    (sizeReqW, sizeReqH) = nodeGetSizeReq wenv gridNode

getSizeReqMixedH :: Spec
getSizeReqMixedH = describe "several items, different reqSizes" $ do
  it "should return width = Range 300 900 1 (3 * Range 100 300)" $
    sizeReqW `shouldBe` rangeSize 300 900 1

  it "should return height = Range 100 300 1" $
    sizeReqH `shouldBe` rangeSize 100 300 1

  where
    wenv = mockWenv ()
    gridNode = hgrid [
        label "Label 1" `styleBasic` [width 100, height 100],
        label "Label 2" `styleBasic` [maxWidth 300, maxHeight 300],
        label "Label 3"
      ]
    (sizeReqW, sizeReqH) = nodeGetSizeReq wenv gridNode

getSizeReqMixedV :: Spec
getSizeReqMixedV = describe "several items, different reqSizes" $ do
  it "should return width = Min 100 1" $
    sizeReqW `shouldBe` SizeReq 100 200 100 1

  it "should return height = Min 300 1 (3 * Min 100)" $
    sizeReqH `shouldBe` SizeReq 300 600 300 1

  where
    wenv = mockWenv ()
    gridNode = vgrid [
        label "Label 1" `styleBasic` [minWidth 100, minHeight 100],
        label "Label 2" `styleBasic` [maxWidth 300, maxHeight 300],
        label "Label 3"
      ]
    (sizeReqW, sizeReqH) = nodeGetSizeReq wenv gridNode

getSizeReqUpdater :: Spec
getSizeReqUpdater = describe "getSizeReqUpdater" $ do
  it "should return width = Min 50 2" $
    sizeReqW `shouldBe` minSize 50 2

  it "should return height = Max 20" $
    sizeReqH `shouldBe` maxSize 20 3

  where
    wenv = mockWenv ()
    vgridNode = vgrid_ [sizeReqUpdater (fixedToMinW 2), sizeReqUpdater (fixedToMaxH 3)] [label "Label"]
    (sizeReqW, sizeReqH) = nodeGetSizeReq wenv vgridNode

getSizeReqChildSpacing :: Spec
getSizeReqChildSpacing = describe "with childSpacing" $ do
  it "should not add spacing when empty" $
    testGridSizeReq [] `shouldBe` fixedSize 0

  it "should not add spacing when singleton" $
    testGridSizeReq [spacer3] `shouldBe` fixedSize 3

  it "should add spacing between children" $
    testGridSizeReq [spacer3, spacer3] `shouldBe` fixedSize 8
  
  it "should not add spacing between invisible children" $ do
    testGridSizeReq [spacer3, spacer3 `nodeVisible` False] `shouldBe` fixedSize 3
  
  where
    wenv = mockWenv ()
    spacer3 = spacer_ [width 3, resizeFactor 0]
    testGridSizeReq children = sizeReqH where
      (_sizeReqW, sizeReqH) = nodeGetSizeReq wenv vgridNode
      vgridNode = vgrid_ [childSpacing_ 2] children

resize :: Spec
resize = describe "resize" $ do
  resizeEmpty
  resizeItemsH
  resizeItemsV
  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 ()
    vp = Rect 0 0 640 480
    gridNode = vgrid []
    newNode = nodeInit wenv gridNode
    viewport = newNode ^. L.info . L.viewport
    children = newNode ^. L.children

resizeItemsH :: Spec
resizeItemsH = describe "several items, horizontal" $ do
  it "should have the provided viewport size" $
    viewport `shouldBe` vp

  it "should assign the same viewport 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 160 640
    cvp2 = Rect 160 0 160 640
    cvp3 = Rect 320 0 160 640
    gridNode = hgrid [
        label "Label 1",
        label "Label Number Two",
        label "Label 3"
      ]
    newNode = nodeInit wenv gridNode
    viewport = newNode ^. L.info . L.viewport
    childrenVp = (^. L.info . L.viewport) <$> newNode ^. L.children

resizeItemsV :: Spec
resizeItemsV = describe "several items, vertical, one not visible" $ do
  it "should have the provided viewport size" $
    viewport `shouldBe` vp

  it "should assign the same viewport size to each children" $
    childrenVp `shouldBe` Seq.fromList [cvp1, cvp2, cvp3, cvp4]

  where
    wenv = mockWenv ()
    vp   = Rect 0   0 640 480
    cvp1 = Rect 0   0 640 160
    cvp2 = Rect 0 160 640 160
    cvp3 = Rect 0   0   0   0
    cvp4 = Rect 0 320 640 160
    gridNode = vgrid [
        label "Label 1",
        label "Label Number Two",
        label "Label invisible" `nodeVisible` False,
        label "Label 3"
      ]
    newNode = nodeInit wenv gridNode
    viewport = newNode ^. L.info . L.viewport
    childrenVp = (^. L.info . L.viewport) <$> newNode ^. L.children

resizeChildSpacing :: Spec
resizeChildSpacing = describe "with childSpacing" $ do

  it "should add spacing between children" $
    testGridChildLocations [spacer, spacer] `shouldBe`
      Seq.fromList [Rect 0 0 640 215, Rect 0 265 640 215]
  
  it "should not add spacing between invisible children" $
    testGridChildLocations [spacer, spacer `nodeVisible` False, spacer] `shouldBe`
      Seq.fromList [Rect 0 0 640 215, Rect 0 0 0 0, Rect 0 265 640 215]
  
  where
    wenv = mockWenv ()
    testGridChildLocations children = childLocations where
      vgridNode = vgrid_ [childSpacing_ 50] children
      newNode = nodeInit wenv vgridNode
      childLocations = roundRectUnits . _wniViewport . _wnInfo <$> newNode ^. L.children