packages feed

monomer-1.0.0.0: test/unit/Monomer/Widgets/Containers/TooltipSpec.hs

{-|
Module      : Monomer.Widgets.Containers.TooltipSpec
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 Tooltip widget.
-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Monomer.Widgets.Containers.TooltipSpec (spec) where

import Control.Lens ((&), (^.), (.~), (%~))
import Data.Default
import Data.Sequence (Seq(..))
import Data.Text (Text)
import Test.Hspec

import qualified Data.Map.Strict as M
import qualified Data.Sequence as Seq

import Monomer.Core
import Monomer.Core.Combinators
import Monomer.Core.Themes.SampleThemes
import Monomer.Event
import Monomer.Main
import Monomer.TestUtil
import Monomer.TestEventUtil
import Monomer.Widgets.Containers.Stack
import Monomer.Widgets.Containers.Tooltip
import Monomer.Widgets.Singles.Label

import qualified Monomer.Lens as L

spec :: Spec
spec = describe "Tooltip" $ do
  handleEvent
  handleEventFollow
  getSizeReq

handleEvent :: Spec
handleEvent = describe "handleEvent" $ do
  it "should not generate a render schedule" $ do
    reqs [] `shouldBe` Seq.empty

  it "should generate a render schedule after moving" $ do
    let evt = Move (Point 10 10)
    let widgetId = WidgetId 0 rootPath
    let renderEveryReq = RenderEvery widgetId 1000 (Just 1)
    reqs [evt] `shouldBe` Seq.fromList [renderEveryReq]

  it "should ony generate a render schedule even after moving, since delay has not passed" $ do
    let evt1 = Move (Point 10 10)
    let evt2 = Move (Point 50 50)
    let widgetId = WidgetId 0 rootPath
    let renderEveryReq = RenderEvery widgetId 1000 (Just 1)
    reqs [evt1, evt2] `shouldBe` Seq.fromList [renderEveryReq]

  where
    wenv = mockWenvEvtUnit ()
    ttNode = tooltip "" (label "Test")
    reqs es = getReqs wenv ttNode es

handleEventFollow :: Spec
handleEventFollow = describe "handleEventFollow" $ do
  it "should not generate a render schedule" $ do
    reqs [] `shouldBe` Seq.empty

  it "should generate a render schedule after moving" $ do
    let evt = Move (Point 10 10)
    let widgetId = WidgetId 0 rootPath
    let renderEveryReq = RenderEvery widgetId 500 (Just 1)
    reqs [evt] `shouldBe` Seq.fromList [renderEveryReq]

  it "should generate a render schedule even after moving, and RenderOnce after" $ do
    let evt1 = Move (Point 10 10)
    let evt2 = Move (Point 50 50)
    let widgetId = WidgetId 0 rootPath
    let renderEveryReq = RenderEvery widgetId 500 (Just 1)
    reqs [evt1, evt2] `shouldBe` Seq.fromList [renderEveryReq, RenderOnce]

  where
    wenv = mockWenvEvtUnit ()
    ttNode = tooltip_ "" [tooltipDelay 500, tooltipFollow] (label "Test")
    reqs es = getReqs wenv ttNode es

getReqs
  :: Eq s
  => WidgetEnv s e
  -> WidgetNode s e
  -> [SystemEvent]
  -> Seq (WidgetRequest s e)
getReqs wenv node [] = Seq.empty
getReqs wenv node (e:es) = tmpReqs <> newReqs where
  -- Each component generates a RenderOnce request when Enter event is received
  tmpNode = nodeHandleEventRoot wenv [e] node
  tmpReqs = Seq.drop 2 $ nodeHandleEventReqs wenv [e] node
  newWenv = wenv & L.timestamp %~ (+1000)
  newReqs = Seq.drop 2 $ nodeHandleEventReqs newWenv es tmpNode

getSizeReq :: Spec
getSizeReq = describe "getSizeReq" $ do
  it "should return same reqW as child node" $
    tSizeReqW `shouldBe` lSizeReqW

  it "should return same reqH as child node" $
    tSizeReqH `shouldBe` lSizeReqH

  where
    wenv = mockWenvEvtUnit ()
      & L.theme .~ darkTheme
    lblNode = label "Test label"
    (lSizeReqW, lSizeReqH) = nodeGetSizeReq wenv lblNode
    (tSizeReqW, tSizeReqH) = nodeGetSizeReq wenv (tooltip "" lblNode)