reflex-vty-1.3.0.0: test/Reflex/Vty/Widget/CursorSpec.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
module Reflex.Vty.Widget.CursorSpec (spec) where
import qualified Graphics.Vty as V
import Reflex (never)
import Test.Hspec
import Reflex.Vty.Host
import Reflex.Vty.Test.AppHarness
import Reflex.Vty.Widget
spec :: Spec
spec = describe "Reflex.Vty.Widget cursor" $ do
describe "defaultCursorState" $
it "starts hidden with terminal-default style" $
defaultCursorState `shouldBe` CursorState CursorHidden CursorStyleDefault (0, 0)
describe "translateCursorState" $ do
it "translates visible viewport-relative positions to absolute positions" $
translateCursorState
(Region 10 20 5 3)
(CursorState CursorVisible CursorStyleBar (2, 1))
`shouldBe` CursorState CursorVisible CursorStyleBar (12, 21)
it "hides visible cursors outside the viewport" $
translateCursorState
(Region 10 20 5 3)
(CursorState CursorVisible CursorStyleBlock (5, 1))
`shouldBe` CursorState CursorHidden CursorStyleBlock (15, 21)
it "translates hidden cursor positions without changing visibility" $
translateCursorState
(Region 10 20 5 3)
(CursorState CursorHidden CursorStyleUnderline (7, 4))
`shouldBe` CursorState CursorHidden CursorStyleUnderline (17, 24)
describe "cursorStateToVtyCursor" $ do
it "maps hidden cursor state to NoCursor" $
cursorStateToVtyCursor (CursorState CursorHidden CursorStyleBlock (2, 3))
`shouldBe` V.NoCursor
it "maps visible cursor state to absolute terminal-cell coordinates" $
-- reflex-vty coordinates are terminal cells. A visible cursor
-- maps to 'V.AbsoluteCursor' (cell coordinates). It never maps
-- to 'V.Cursor' (character offsets).
cursorStateToVtyCursor (CursorState CursorVisible CursorStyleBlock (2, 3))
`shouldBe` V.AbsoluteCursor 2 3
describe "setCursor through the production host" $ do
it "reports the cursor at the cell position after the wide glyph" $
withApp defaultVtyAppConfig (20, 3) cursorApp $ \driver -> do
fs <- driverFrames driver
case reverse fs of
(f : _) -> frameCursor f `shouldBe` V.AbsoluteCursor 3 0
[] -> expectationFailure "expected an initial frame"
stopApp driver
describe "ScreenMode" $ do
it "has two constructors" $
[ScreenNormal ..] `shouldBe` [ScreenNormal, ScreenAlternate]
it "ScreenNormal /= ScreenAlternate" $
ScreenNormal `shouldNotBe` ScreenAlternate
-- | A static row with one wide glyph. The terminal cursor sits three
-- cells from the left edge.
cursorApp :: TestApp () ()
cursorApp _cmd = do
tellImages (pure [V.string V.defAttr "a\30028|"])
setCursor (pure (CursorState CursorVisible CursorStyleDefault (3, 0)))
pure (pure (), never)